[layout] Port sanitize() to use dispatch()

Needed some rework of Extension table.  Hopefully I got it right, and
the new template usage doesn't break any compilers...
This commit is contained in:
Behdad Esfahbod 2015-02-19 10:29:41 +03:00
parent 758fb20630
commit 095a1257cc
4 changed files with 37 additions and 206 deletions

View File

@ -179,10 +179,13 @@ struct hb_sanitize_context_t
inline const char *get_name (void) { return "SANITIZE"; }
static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE;
typedef bool return_t;
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format)
{ return format->sanitize (this); }
template <typename T>
inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
static return_t default_return_value (void) { return true; }
bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; }
bool stop_sublookup_iteration (const return_t r) const { return !r; }
inline void init (hb_blob_t *b)
{

View File

@ -556,17 +556,6 @@ struct SinglePos
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -862,17 +851,6 @@ struct PairPos
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -1031,16 +1009,6 @@ struct CursivePos
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -1134,16 +1102,6 @@ struct MarkBasePos
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -1259,16 +1217,6 @@ struct MarkLigPos
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -1382,16 +1330,6 @@ struct MarkMarkPos
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -1436,6 +1374,7 @@ struct PosLookupSubTable
inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
{
TRACE_DISPATCH (this, lookup_type);
/* The sub_format passed to may_dispatch is unnecessary but harmless. */
if (unlikely (!c->may_dispatch (this, &u.sub_format))) TRACE_RETURN (c->default_return_value ());
switch (lookup_type) {
case Single: return TRACE_RETURN (u.single.dispatch (c));
@ -1451,23 +1390,6 @@ struct PosLookupSubTable
}
}
inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) const
{
TRACE_SANITIZE (this);
switch (lookup_type) {
case Single: return TRACE_RETURN (u.single.sanitize (c));
case Pair: return TRACE_RETURN (u.pair.sanitize (c));
case Cursive: return TRACE_RETURN (u.cursive.sanitize (c));
case MarkBase: return TRACE_RETURN (u.markBase.sanitize (c));
case MarkLig: return TRACE_RETURN (u.markLig.sanitize (c));
case MarkMark: return TRACE_RETURN (u.markMark.sanitize (c));
case Context: return TRACE_RETURN (u.context.sanitize (c));
case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
case Extension: return TRACE_RETURN (u.extension.sanitize (c));
default: return TRACE_RETURN (true);
}
}
protected:
union {
USHORT sub_format;
@ -1531,7 +1453,7 @@ struct PosLookup : Lookup
TRACE_SANITIZE (this);
if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
const OffsetArrayOf<PosLookupSubTable> &list = get_subtables<PosLookupSubTable> ();
return TRACE_RETURN (list.sanitize (c, this, get_type ()));
return TRACE_RETURN (dispatch (c));
}
};

View File

@ -233,17 +233,6 @@ struct SingleSubst
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -436,16 +425,6 @@ struct MultipleSubst
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -590,16 +569,6 @@ struct AlternateSubst
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -911,16 +880,6 @@ struct LigatureSubst
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -1078,16 +1037,6 @@ struct ReverseChainSingleSubst
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -1120,6 +1069,7 @@ struct SubstLookupSubTable
inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
{
TRACE_DISPATCH (this, lookup_type);
/* The sub_format passed to may_dispatch is unnecessary but harmless. */
if (unlikely (!c->may_dispatch (this, &u.sub_format))) TRACE_RETURN (c->default_return_value ());
switch (lookup_type) {
case Single: return TRACE_RETURN (u.single.dispatch (c));
@ -1134,22 +1084,6 @@ struct SubstLookupSubTable
}
}
inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) const
{
TRACE_SANITIZE (this);
switch (lookup_type) {
case Single: return TRACE_RETURN (u.single.sanitize (c));
case Multiple: return TRACE_RETURN (u.multiple.sanitize (c));
case Alternate: return TRACE_RETURN (u.alternate.sanitize (c));
case Ligature: return TRACE_RETURN (u.ligature.sanitize (c));
case Context: return TRACE_RETURN (u.context.sanitize (c));
case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
case Extension: return TRACE_RETURN (u.extension.sanitize (c));
case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.sanitize (c));
default: return TRACE_RETURN (true);
}
}
protected:
union {
USHORT sub_format;
@ -1291,7 +1225,7 @@ struct SubstLookup : Lookup
TRACE_SANITIZE (this);
if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
const OffsetArrayOf<SubstLookupSubTable> &list = get_subtables<SubstLookupSubTable> ();
if (unlikely (!list.sanitize (c, this, get_type ()))) return TRACE_RETURN (false);
if (unlikely (!dispatch (c))) return TRACE_RETURN (false);
if (unlikely (get_type () == SubstLookupSubTable::Extension))
{
@ -1363,7 +1297,7 @@ GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSE
{
unsigned int type = get_type ();
if (unlikely (type == SubstLookupSubTable::Extension))
return CastR<ExtensionSubst> (get_subtable<SubstLookupSubTable>()).is_reverse ();
return CastR<ExtensionSubst> (get_subtable<LookupSubTable>()).is_reverse ();
return SubstLookup::lookup_type_is_reverse (type);
}

View File

@ -1524,18 +1524,6 @@ struct Context
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
case 3: return TRACE_RETURN (u.format3.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -2149,18 +2137,6 @@ struct ChainContext
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
case 3: return TRACE_RETURN (u.format3.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected:
union {
USHORT format; /* Format identifier */
@ -2171,15 +2147,32 @@ struct ChainContext
};
template <typename T>
struct ExtensionFormat1
{
inline unsigned int get_type (void) const { return extensionLookupType; }
inline unsigned int get_offset (void) const { return extensionOffset; }
template <typename X>
inline const X& get_subtable (void) const
{
unsigned int offset = extensionOffset;
if (unlikely (!offset)) return Null(typename T::LookupSubTable);
return StructAtOffset<typename T::LookupSubTable> (this, offset);
}
template <typename context_t>
inline typename context_t::return_t dispatch (context_t *c) const
{
TRACE_DISPATCH (this, format);
if (unlikely (!c->may_dispatch (this, this))) TRACE_RETURN (c->default_return_value ());
return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ());
}
/* This is called from may_dispatch() above with hb_sanitize_context_t. */
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this));
return TRACE_RETURN (c->check_struct (this) && extensionOffset != 0);
}
protected:
@ -2203,51 +2196,30 @@ struct Extension
default:return 0;
}
}
inline unsigned int get_offset (void) const
{
switch (u.format) {
case 1: return u.format1.get_offset ();
default:return 0;
}
}
template <typename X>
inline const X& get_subtable (void) const
{
unsigned int offset = get_offset ();
if (unlikely (!offset)) return Null(typename T::LookupSubTable);
return StructAtOffset<typename T::LookupSubTable> (this, offset);
switch (u.format) {
case 1: return u.format1.template get_subtable<typename T::LookupSubTable> ();
default:return Null(typename T::LookupSubTable);
}
}
template <typename context_t>
inline typename context_t::return_t dispatch (context_t *c) const
{
return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ());
}
inline bool sanitize_self (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
case 1: return TRACE_RETURN (u.format1.dispatch (c));
default:return TRACE_RETURN (c->default_return_value ());
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!sanitize_self (c)) return TRACE_RETURN (false);
unsigned int offset = get_offset ();
if (unlikely (!offset)) return TRACE_RETURN (true);
return TRACE_RETURN (StructAtOffset<typename T::LookupSubTable> (this, offset).sanitize (c, get_type ()));
}
protected:
union {
USHORT format; /* Format identifier */
ExtensionFormat1 format1;
ExtensionFormat1<T> format1;
} u;
};