Merge branch 'master' into cff-subset
This commit is contained in:
commit
f2c4720ae6
|
@ -529,18 +529,20 @@ struct hb_array_t
|
||||||
|
|
||||||
struct hb_bytes_t
|
struct hb_bytes_t
|
||||||
{
|
{
|
||||||
inline hb_bytes_t (void) : bytes (nullptr), len (0) {}
|
inline hb_bytes_t (void) : arrayZ (nullptr), len (0) {}
|
||||||
inline hb_bytes_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
|
inline hb_bytes_t (const char *bytes_, unsigned int len_) : arrayZ (bytes_), len (len_) {}
|
||||||
inline hb_bytes_t (const void *bytes_, unsigned int len_) : bytes ((const char *) bytes_), len (len_) {}
|
inline hb_bytes_t (const void *bytes_, unsigned int len_) : arrayZ ((const char *) bytes_), len (len_) {}
|
||||||
|
template <typename T>
|
||||||
|
inline hb_bytes_t (const T& array) : arrayZ ((const char *) array.arrayZ), len (array.len) {}
|
||||||
|
|
||||||
inline void free (void) { ::free ((void *) bytes); bytes = nullptr; len = 0; }
|
inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
|
||||||
|
|
||||||
inline int cmp (const hb_bytes_t &a) const
|
inline int cmp (const hb_bytes_t &a) const
|
||||||
{
|
{
|
||||||
if (len != a.len)
|
if (len != a.len)
|
||||||
return (int) a.len - (int) len;
|
return (int) a.len - (int) len;
|
||||||
|
|
||||||
return memcmp (a.bytes, bytes, len);
|
return memcmp (a.arrayZ, arrayZ, len);
|
||||||
}
|
}
|
||||||
static inline int cmp (const void *pa, const void *pb)
|
static inline int cmp (const void *pa, const void *pb)
|
||||||
{
|
{
|
||||||
|
@ -549,7 +551,7 @@ struct hb_bytes_t
|
||||||
return b->cmp (*a);
|
return b->cmp (*a);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *bytes;
|
const char *arrayZ;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -287,52 +287,69 @@ struct TTCHeader
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mac Resource Fork
|
* Mac Resource Fork
|
||||||
|
*
|
||||||
|
* http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct ResourceRefItem
|
struct ResourceRecord
|
||||||
{
|
{
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
inline const OpenTypeFontFace & get_face (const void *data_base) const
|
||||||
|
{ return CastR<OpenTypeFontFace> ((data_base+offset).arrayZ); }
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c,
|
||||||
|
const void *data_base) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
// actual data sanitization is done on ResourceForkHeader sanitizer
|
return_trace (c->check_struct (this) &&
|
||||||
return_trace (likely (c->check_struct (this)));
|
offset.sanitize (c, data_base) &&
|
||||||
|
get_face (data_base).sanitize (c));
|
||||||
}
|
}
|
||||||
|
|
||||||
HBINT16 id; /* Resource ID, is really should be signed? */
|
protected:
|
||||||
|
HBUINT16 id; /* Resource ID. */
|
||||||
HBINT16 nameOffset; /* Offset from beginning of resource name list
|
HBINT16 nameOffset; /* Offset from beginning of resource name list
|
||||||
* to resource name, minus means there is none. */
|
* to resource name, -1 means there is none. */
|
||||||
HBUINT8 attr; /* Resource attributes */
|
HBUINT8 attrs; /* Resource attributes */
|
||||||
HBUINT24 dataOffset; /* Offset from beginning of resource data to
|
OffsetTo<LArrayOf<HBUINT8>, HBUINT24, false>
|
||||||
|
offset; /* Offset from beginning of data block to
|
||||||
* data for this resource */
|
* data for this resource */
|
||||||
HBUINT32 reserved; /* Reserved for handle to resource */
|
HBUINT32 reserved; /* Reserved for handle to resource */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_STATIC (12);
|
DEFINE_SIZE_STATIC (12);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ResourceTypeItem
|
#define HB_TAG_sfnt HB_TAG ('s','f','n','t')
|
||||||
|
|
||||||
|
struct ResourceTypeRecord
|
||||||
{
|
{
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
inline unsigned int get_resource_count (void) const
|
||||||
|
{ return tag == HB_TAG_sfnt ? resCountM1 + 1 : 0; }
|
||||||
|
|
||||||
|
inline bool is_sfnt (void) const { return tag == HB_TAG_sfnt; }
|
||||||
|
|
||||||
|
inline const ResourceRecord& get_resource_record (unsigned int i,
|
||||||
|
const void *type_base) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
return hb_array_t<ResourceRecord> ((type_base+resourcesZ).arrayZ,
|
||||||
// RefList sanitization is done on ResourceMap sanitizer
|
get_resource_count ()) [i];
|
||||||
return_trace (likely (c->check_struct (this)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int get_resource_count () const { return numRes + 1; }
|
inline bool sanitize (hb_sanitize_context_t *c,
|
||||||
|
const void *type_base,
|
||||||
inline bool is_sfnt () const { return type == HB_TAG ('s','f','n','t'); }
|
const void *data_base) const
|
||||||
|
|
||||||
inline const ResourceRefItem& get_ref_item (const void *base,
|
|
||||||
unsigned int i) const
|
|
||||||
{
|
{
|
||||||
return (base+refList)[i];
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this) &&
|
||||||
|
resourcesZ.sanitize (c, type_base,
|
||||||
|
get_resource_count (),
|
||||||
|
data_base));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Tag type; /* Resource type. */
|
Tag tag; /* Resource type. */
|
||||||
HBUINT16 numRes; /* Number of resources minus 1. */
|
HBUINT16 resCountM1; /* Number of resources minus 1. */
|
||||||
OffsetTo<UnsizedArrayOf<ResourceRefItem> >
|
OffsetTo<UnsizedArrayOf<ResourceRecord> >
|
||||||
refList; /* Offset from beginning of resource type list
|
resourcesZ; /* Offset from beginning of resource type list
|
||||||
* to reference item list for this type. */
|
* to reference item list for this type. */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_STATIC (8);
|
DEFINE_SIZE_STATIC (8);
|
||||||
|
@ -340,132 +357,88 @@ struct ResourceTypeItem
|
||||||
|
|
||||||
struct ResourceMap
|
struct ResourceMap
|
||||||
{
|
{
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
inline unsigned int get_face_count (void) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
unsigned int count = get_type_count ();
|
||||||
if (unlikely (!c->check_struct (this)))
|
for (unsigned int i = 0; i < count; i++)
|
||||||
return_trace (false);
|
|
||||||
for (unsigned int i = 0; i < get_types_count (); ++i)
|
|
||||||
{
|
{
|
||||||
const ResourceTypeItem& type = get_type (i);
|
const ResourceTypeRecord& type = get_type_record (i);
|
||||||
if (unlikely (!type.sanitize (c)))
|
|
||||||
return_trace (false);
|
|
||||||
for (unsigned int j = 0; j < type.get_resource_count (); ++j)
|
|
||||||
if (unlikely (!get_ref_item (type, j).sanitize (c)))
|
|
||||||
return_trace (false);
|
|
||||||
}
|
|
||||||
return_trace (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const ResourceTypeItem& get_type (unsigned int i) const
|
|
||||||
{
|
|
||||||
// Why offset from the second byte of the object? I'm not sure
|
|
||||||
return ((&reserved[2])+typeList)[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int get_types_count () const
|
|
||||||
{
|
|
||||||
return nTypes + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const ResourceRefItem &get_ref_item (const ResourceTypeItem &type,
|
|
||||||
unsigned int i) const
|
|
||||||
{
|
|
||||||
return type.get_ref_item (&(this+typeList), i);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const PString& get_name (const ResourceRefItem &item,
|
|
||||||
unsigned int i) const
|
|
||||||
{
|
|
||||||
if (item.nameOffset == -1)
|
|
||||||
return Null (PString);
|
|
||||||
|
|
||||||
return StructAtOffset<PString> (this, nameList + item.nameOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
HBUINT8 reserved[16]; /* Reserved for copy of resource header */
|
|
||||||
LOffsetTo<ResourceMap>
|
|
||||||
reserved1; /* Reserved for handle to next resource map */
|
|
||||||
HBUINT16 reserved2; /* Reserved for file reference number */
|
|
||||||
HBUINT16 attr; /* Resource fork attribute */
|
|
||||||
OffsetTo<UnsizedArrayOf<ResourceTypeItem> >
|
|
||||||
typeList; /* Offset from beginning of map to
|
|
||||||
* resource type list */
|
|
||||||
HBUINT16 nameList; /* Offset from beginning of map to
|
|
||||||
* resource name list */
|
|
||||||
HBUINT16 nTypes; /* Number of types in the map minus 1 */
|
|
||||||
public:
|
|
||||||
DEFINE_SIZE_STATIC (30);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ResourceForkHeader
|
|
||||||
{
|
|
||||||
inline unsigned int get_face_count () const
|
|
||||||
{
|
|
||||||
const ResourceMap &resource_map = this+map;
|
|
||||||
for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
|
|
||||||
{
|
|
||||||
const ResourceTypeItem& type = resource_map.get_type (i);
|
|
||||||
if (type.is_sfnt ())
|
if (type.is_sfnt ())
|
||||||
return type.get_resource_count ();
|
return type.get_resource_count ();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const LArrayOf<HBUINT8>& get_data (const ResourceTypeItem& type,
|
inline const OpenTypeFontFace& get_face (unsigned int idx,
|
||||||
unsigned int idx) const
|
const void *data_base) const
|
||||||
{
|
{
|
||||||
const ResourceMap &resource_map = this+map;
|
unsigned int count = get_type_count ();
|
||||||
unsigned int offset = dataOffset;
|
for (unsigned int i = 0; i < count; i++)
|
||||||
offset += resource_map.get_ref_item (type, idx).dataOffset;
|
|
||||||
return StructAtOffset<LArrayOf<HBUINT8> > (this, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const OpenTypeFontFace& get_face (unsigned int idx, unsigned int *base_offset = nullptr) const
|
|
||||||
{
|
|
||||||
const ResourceMap &resource_map = this+map;
|
|
||||||
for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
|
|
||||||
{
|
{
|
||||||
const ResourceTypeItem& type = resource_map.get_type (i);
|
const ResourceTypeRecord& type = get_type_record (i);
|
||||||
|
/* The check for idx < count is here because ResourceRecord is NOT null-safe.
|
||||||
|
* Because an offset of 0 there does NOT mean null. */
|
||||||
if (type.is_sfnt () && idx < type.get_resource_count ())
|
if (type.is_sfnt () && idx < type.get_resource_count ())
|
||||||
{
|
return type.get_resource_record (idx, &(this+typeList)).get_face (data_base);
|
||||||
const OpenTypeFontFace &face = (OpenTypeFontFace&) get_data (type, idx).arrayZ;
|
|
||||||
if (base_offset)
|
|
||||||
*base_offset = (const char *) &face - (const char *) this;
|
|
||||||
return face;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Null (OpenTypeFontFace);
|
return Null (OpenTypeFontFace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
const void *type_base = &(this+typeList);
|
||||||
|
return_trace (c->check_struct (this) &&
|
||||||
|
typeList.sanitize (c, this,
|
||||||
|
type_base,
|
||||||
|
data_base));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline unsigned int get_type_count (void) const { return (this+typeList).lenM1 + 1; }
|
||||||
|
|
||||||
|
inline const ResourceTypeRecord& get_type_record (unsigned int i) const
|
||||||
|
{ return (this+typeList)[i]; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT8 reserved0[16]; /* Reserved for copy of resource header */
|
||||||
|
HBUINT32 reserved1; /* Reserved for handle to next resource map */
|
||||||
|
HBUINT16 resreved2; /* Reserved for file reference number */
|
||||||
|
HBUINT16 attrs; /* Resource fork attribute */
|
||||||
|
OffsetTo<ArrayOfM1<ResourceTypeRecord> >
|
||||||
|
typeList; /* Offset from beginning of map to
|
||||||
|
* resource type list */
|
||||||
|
Offset16 nameList; /* Offset from beginning of map to
|
||||||
|
* resource name list */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (28);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResourceForkHeader
|
||||||
|
{
|
||||||
|
inline unsigned int get_face_count (void) const
|
||||||
|
{ return (this+map).get_face_count (); }
|
||||||
|
|
||||||
|
inline const OpenTypeFontFace& get_face (unsigned int idx,
|
||||||
|
unsigned int *base_offset = nullptr) const
|
||||||
|
{
|
||||||
|
const OpenTypeFontFace &face = (this+map).get_face (idx, &(this+data));
|
||||||
|
if (base_offset)
|
||||||
|
*base_offset = (const char *) &face - (const char *) this;
|
||||||
|
return face;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
if (unlikely (!c->check_struct (this)))
|
return_trace (c->check_struct (this) &&
|
||||||
return_trace (false);
|
data.sanitize (c, this, dataLen) &&
|
||||||
|
map.sanitize (c, this, &(this+data)));
|
||||||
const ResourceMap &resource_map = this+map;
|
|
||||||
if (unlikely (!resource_map.sanitize (c)))
|
|
||||||
return_trace (false);
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
|
|
||||||
{
|
|
||||||
const ResourceTypeItem& type = resource_map.get_type (i);
|
|
||||||
for (unsigned int j = 0; j < type.get_resource_count (); ++j)
|
|
||||||
{
|
|
||||||
const LArrayOf<HBUINT8>& data = get_data (type, j);
|
|
||||||
if (unlikely (!(data.sanitize (c) &&
|
|
||||||
((OpenTypeFontFace&) data.arrayZ).sanitize (c))))
|
|
||||||
return_trace (false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return_trace (true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HBUINT32 dataOffset; /* Offset from beginning of resource fork
|
LOffsetTo<UnsizedArrayOf<HBUINT8> >
|
||||||
|
data; /* Offset from beginning of resource fork
|
||||||
* to resource data */
|
* to resource data */
|
||||||
LOffsetTo<ResourceMap>
|
LOffsetTo<ResourceMap>
|
||||||
map; /* Offset from beginning of resource fork
|
map; /* Offset from beginning of resource fork
|
||||||
|
|
|
@ -155,10 +155,10 @@ struct Index : HBUINT16 {
|
||||||
DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
|
DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
|
||||||
|
|
||||||
/* Offset, Null offset = 0 */
|
/* Offset, Null offset = 0 */
|
||||||
template <typename Type>
|
template <typename Type, bool has_null=true>
|
||||||
struct Offset : Type
|
struct Offset : Type
|
||||||
{
|
{
|
||||||
inline bool is_null (void) const { return 0 == *this; }
|
inline bool is_null (void) const { return has_null && 0 == *this; }
|
||||||
|
|
||||||
inline void *serialize (hb_serialize_context_t *c, const void *base)
|
inline void *serialize (hb_serialize_context_t *c, const void *base)
|
||||||
{
|
{
|
||||||
|
@ -226,20 +226,18 @@ struct FixedVersion
|
||||||
* Use: (base+offset)
|
* Use: (base+offset)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename Type, typename OffsetType=HBUINT16>
|
template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
|
||||||
struct OffsetTo : Offset<OffsetType>
|
struct OffsetTo : Offset<OffsetType, has_null>
|
||||||
{
|
{
|
||||||
inline const Type& operator () (const void *base) const
|
inline const Type& operator () (const void *base) const
|
||||||
{
|
{
|
||||||
unsigned int offset = *this;
|
if (unlikely (this->is_null ())) return Null(Type);
|
||||||
if (unlikely (!offset)) return Null(Type);
|
return StructAtOffset<const Type> (base, *this);
|
||||||
return StructAtOffset<const Type> (base, offset);
|
|
||||||
}
|
}
|
||||||
inline Type& operator () (void *base) const
|
inline Type& operator () (void *base) const
|
||||||
{
|
{
|
||||||
unsigned int offset = *this;
|
if (unlikely (this->is_null ())) return Crap(Type);
|
||||||
if (unlikely (!offset)) return Crap(Type);
|
return StructAtOffset<Type> (base, *this);
|
||||||
return StructAtOffset<Type> (base, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Type& serialize (hb_serialize_context_t *c, const void *base)
|
inline Type& serialize (hb_serialize_context_t *c, const void *base)
|
||||||
|
@ -260,39 +258,64 @@ struct OffsetTo : Offset<OffsetType>
|
||||||
this->set (0);
|
this->set (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (unlikely (!c->check_struct (this))) return_trace (false);
|
||||||
|
if (unlikely (this->is_null ())) return_trace (true);
|
||||||
|
if (unlikely (!c->check_range (base, *this))) return_trace (false);
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
if (unlikely (!c->check_struct (this))) return_trace (false);
|
return_trace (sanitize_shallow (c, base) &&
|
||||||
unsigned int offset = *this;
|
(this->is_null () ||
|
||||||
if (unlikely (!offset)) return_trace (true);
|
StructAtOffset<Type> (base, *this).sanitize (c) ||
|
||||||
if (unlikely (!c->check_range (base, offset))) return_trace (false);
|
neuter (c)));
|
||||||
const Type &obj = StructAtOffset<Type> (base, offset);
|
|
||||||
return_trace (likely (obj.sanitize (c)) || neuter (c));
|
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T1>
|
||||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
|
inline bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
if (unlikely (!c->check_struct (this))) return_trace (false);
|
return_trace (sanitize_shallow (c, base) &&
|
||||||
unsigned int offset = *this;
|
(this->is_null () ||
|
||||||
if (unlikely (!offset)) return_trace (true);
|
StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
|
||||||
if (unlikely (!c->check_range (base, offset))) return_trace (false);
|
neuter (c)));
|
||||||
const Type &obj = StructAtOffset<Type> (base, offset);
|
}
|
||||||
return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
|
template <typename T1, typename T2>
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (sanitize_shallow (c, base) &&
|
||||||
|
(this->is_null () ||
|
||||||
|
StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) ||
|
||||||
|
neuter (c)));
|
||||||
|
}
|
||||||
|
template <typename T1, typename T2, typename T3>
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (sanitize_shallow (c, base) &&
|
||||||
|
(this->is_null () ||
|
||||||
|
StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) ||
|
||||||
|
neuter (c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the offset to Null */
|
/* Set the offset to Null */
|
||||||
inline bool neuter (hb_sanitize_context_t *c) const {
|
inline bool neuter (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
if (!has_null) return false;
|
||||||
return c->try_set (this, 0);
|
return c->try_set (this, 0);
|
||||||
}
|
}
|
||||||
DEFINE_SIZE_STATIC (sizeof(OffsetType));
|
DEFINE_SIZE_STATIC (sizeof(OffsetType));
|
||||||
};
|
};
|
||||||
template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
|
template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
|
||||||
template <typename Base, typename OffsetType, typename Type>
|
template <typename Base, typename OffsetType, bool has_null, typename Type>
|
||||||
static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
|
static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
|
||||||
template <typename Base, typename OffsetType, typename Type>
|
template <typename Base, typename OffsetType, bool has_null, typename Type>
|
||||||
static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
|
static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -547,16 +570,16 @@ struct HeadlessArrayOf
|
||||||
{
|
{
|
||||||
inline const Type& operator [] (unsigned int i) const
|
inline const Type& operator [] (unsigned int i) const
|
||||||
{
|
{
|
||||||
if (unlikely (i >= len || !i)) return Null(Type);
|
if (unlikely (i >= lenP1 || !i)) return Null(Type);
|
||||||
return arrayZ[i-1];
|
return arrayZ[i-1];
|
||||||
}
|
}
|
||||||
inline Type& operator [] (unsigned int i)
|
inline Type& operator [] (unsigned int i)
|
||||||
{
|
{
|
||||||
if (unlikely (i >= len || !i)) return Crap(Type);
|
if (unlikely (i >= lenP1 || !i)) return Crap(Type);
|
||||||
return arrayZ[i-1];
|
return arrayZ[i-1];
|
||||||
}
|
}
|
||||||
inline unsigned int get_size (void) const
|
inline unsigned int get_size (void) const
|
||||||
{ return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
|
{ return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; }
|
||||||
|
|
||||||
inline bool serialize (hb_serialize_context_t *c,
|
inline bool serialize (hb_serialize_context_t *c,
|
||||||
Supplier<Type> &items,
|
Supplier<Type> &items,
|
||||||
|
@ -564,7 +587,7 @@ struct HeadlessArrayOf
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||||
len.set (items_len); /* TODO(serialize) Overflow? */
|
lenP1.set (items_len); /* TODO(serialize) Overflow? */
|
||||||
if (unlikely (!items_len)) return_trace (true);
|
if (unlikely (!items_len)) return_trace (true);
|
||||||
if (unlikely (!c->extend (*this))) return_trace (false);
|
if (unlikely (!c->extend (*this))) return_trace (false);
|
||||||
for (unsigned int i = 0; i < items_len - 1; i++)
|
for (unsigned int i = 0; i < items_len - 1; i++)
|
||||||
|
@ -594,12 +617,56 @@ struct HeadlessArrayOf
|
||||||
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
|
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
return_trace (len.sanitize (c) &&
|
return_trace (lenP1.sanitize (c) &&
|
||||||
(!len || c->check_array (arrayZ, len - 1)));
|
(!lenP1 || c->check_array (arrayZ, lenP1 - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LenType len;
|
LenType lenP1;
|
||||||
|
Type arrayZ[VAR];
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* An array storing length-1. */
|
||||||
|
template <typename Type, typename LenType=HBUINT16>
|
||||||
|
struct ArrayOfM1
|
||||||
|
{
|
||||||
|
inline const Type& operator [] (unsigned int i) const
|
||||||
|
{
|
||||||
|
if (unlikely (i > lenM1)) return Null(Type);
|
||||||
|
return arrayZ[i];
|
||||||
|
}
|
||||||
|
inline Type& operator [] (unsigned int i)
|
||||||
|
{
|
||||||
|
if (unlikely (i > lenM1)) return Crap(Type);
|
||||||
|
return arrayZ[i];
|
||||||
|
}
|
||||||
|
inline unsigned int get_size (void) const
|
||||||
|
{ return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||||
|
unsigned int count = lenM1 + 1;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
|
||||||
|
return_trace (false);
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (lenM1.sanitize (c) &&
|
||||||
|
(c->check_array (arrayZ, lenM1 + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
LenType lenM1;
|
||||||
Type arrayZ[VAR];
|
Type arrayZ[VAR];
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
|
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
|
||||||
|
|
|
@ -710,7 +710,7 @@ struct Ligature
|
||||||
{
|
{
|
||||||
inline bool intersects (const hb_set_t *glyphs) const
|
inline bool intersects (const hb_set_t *glyphs) const
|
||||||
{
|
{
|
||||||
unsigned int count = component.len;
|
unsigned int count = component.lenP1;
|
||||||
for (unsigned int i = 1; i < count; i++)
|
for (unsigned int i = 1; i < count; i++)
|
||||||
if (!glyphs->has (component[i]))
|
if (!glyphs->has (component[i]))
|
||||||
return false;
|
return false;
|
||||||
|
@ -720,7 +720,7 @@ struct Ligature
|
||||||
inline void closure (hb_closure_context_t *c) const
|
inline void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_CLOSURE (this);
|
TRACE_CLOSURE (this);
|
||||||
unsigned int count = component.len;
|
unsigned int count = component.lenP1;
|
||||||
for (unsigned int i = 1; i < count; i++)
|
for (unsigned int i = 1; i < count; i++)
|
||||||
if (!c->glyphs->has (component[i]))
|
if (!c->glyphs->has (component[i]))
|
||||||
return;
|
return;
|
||||||
|
@ -730,14 +730,14 @@ struct Ligature
|
||||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_COLLECT_GLYPHS (this);
|
TRACE_COLLECT_GLYPHS (this);
|
||||||
c->input->add_array (component.arrayZ, component.len ? component.len - 1 : 0);
|
c->input->add_array (component.arrayZ, component.lenP1 ? component.lenP1 - 1 : 0);
|
||||||
c->output->add (ligGlyph);
|
c->output->add (ligGlyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_WOULD_APPLY (this);
|
TRACE_WOULD_APPLY (this);
|
||||||
if (c->len != component.len)
|
if (c->len != component.lenP1)
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
for (unsigned int i = 1; i < c->len; i++)
|
for (unsigned int i = 1; i < c->len; i++)
|
||||||
|
@ -750,7 +750,7 @@ struct Ligature
|
||||||
inline bool apply (hb_ot_apply_context_t *c) const
|
inline bool apply (hb_ot_apply_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
TRACE_APPLY (this);
|
||||||
unsigned int count = component.len;
|
unsigned int count = component.lenP1;
|
||||||
|
|
||||||
if (unlikely (!count)) return_trace (false);
|
if (unlikely (!count)) return_trace (false);
|
||||||
|
|
||||||
|
|
|
@ -1879,7 +1879,7 @@ struct ChainRule
|
||||||
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
|
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
|
||||||
return chain_context_intersects (glyphs,
|
return chain_context_intersects (glyphs,
|
||||||
backtrack.len, backtrack.arrayZ,
|
backtrack.len, backtrack.arrayZ,
|
||||||
input.len, input.arrayZ,
|
input.lenP1, input.arrayZ,
|
||||||
lookahead.len, lookahead.arrayZ,
|
lookahead.len, lookahead.arrayZ,
|
||||||
lookup_context);
|
lookup_context);
|
||||||
}
|
}
|
||||||
|
@ -1892,7 +1892,7 @@ struct ChainRule
|
||||||
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
||||||
chain_context_closure_lookup (c,
|
chain_context_closure_lookup (c,
|
||||||
backtrack.len, backtrack.arrayZ,
|
backtrack.len, backtrack.arrayZ,
|
||||||
input.len, input.arrayZ,
|
input.lenP1, input.arrayZ,
|
||||||
lookahead.len, lookahead.arrayZ,
|
lookahead.len, lookahead.arrayZ,
|
||||||
lookup.len, lookup.arrayZ,
|
lookup.len, lookup.arrayZ,
|
||||||
lookup_context);
|
lookup_context);
|
||||||
|
@ -1906,7 +1906,7 @@ struct ChainRule
|
||||||
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
||||||
chain_context_collect_glyphs_lookup (c,
|
chain_context_collect_glyphs_lookup (c,
|
||||||
backtrack.len, backtrack.arrayZ,
|
backtrack.len, backtrack.arrayZ,
|
||||||
input.len, input.arrayZ,
|
input.lenP1, input.arrayZ,
|
||||||
lookahead.len, lookahead.arrayZ,
|
lookahead.len, lookahead.arrayZ,
|
||||||
lookup.len, lookup.arrayZ,
|
lookup.len, lookup.arrayZ,
|
||||||
lookup_context);
|
lookup_context);
|
||||||
|
@ -1920,7 +1920,7 @@ struct ChainRule
|
||||||
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
||||||
return_trace (chain_context_would_apply_lookup (c,
|
return_trace (chain_context_would_apply_lookup (c,
|
||||||
backtrack.len, backtrack.arrayZ,
|
backtrack.len, backtrack.arrayZ,
|
||||||
input.len, input.arrayZ,
|
input.lenP1, input.arrayZ,
|
||||||
lookahead.len, lookahead.arrayZ, lookup.len,
|
lookahead.len, lookahead.arrayZ, lookup.len,
|
||||||
lookup.arrayZ, lookup_context));
|
lookup.arrayZ, lookup_context));
|
||||||
}
|
}
|
||||||
|
@ -1933,7 +1933,7 @@ struct ChainRule
|
||||||
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
||||||
return_trace (chain_context_apply_lookup (c,
|
return_trace (chain_context_apply_lookup (c,
|
||||||
backtrack.len, backtrack.arrayZ,
|
backtrack.len, backtrack.arrayZ,
|
||||||
input.len, input.arrayZ,
|
input.lenP1, input.arrayZ,
|
||||||
lookahead.len, lookahead.arrayZ, lookup.len,
|
lookahead.len, lookahead.arrayZ, lookup.len,
|
||||||
lookup.arrayZ, lookup_context));
|
lookup.arrayZ, lookup_context));
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ struct post
|
||||||
return true;
|
return true;
|
||||||
if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
|
if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
|
||||||
return false;
|
return false;
|
||||||
strncpy (buf, s.bytes, s.len);
|
strncpy (buf, s.arrayZ, s.len);
|
||||||
buf[s.len] = '\0';
|
buf[s.len] = '\0';
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue