From 809200a83e366141d543336503635cf57c626434 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 15 Dec 2017 13:00:39 +0100 Subject: Update bundled HarfBuzz-NG copy to 1.7.4 This is the latest released version, fixing a large amount of bugs and adding Unicode 10 support. [ChangeLog] Bundled HarfBuzz-NG copy updated to 1.7.4 Change-Id: Idc8092dfc4e593d64fff2fd51ff9e1b3d84049a7 Reviewed-by: Lars Knoll --- .../harfbuzz-ng/src/hb-open-type-private.hh | 277 +++++++++++++++------ 1 file changed, 197 insertions(+), 80 deletions(-) (limited to 'src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh') diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh index 2cc1fb20d2..2f4e1b9e9e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh @@ -30,6 +30,8 @@ #define HB_OPEN_TYPE_PRIVATE_HH #include "hb-private.hh" +#include "hb-debug.hh" +#include "hb-face-private.hh" namespace OT { @@ -84,7 +86,7 @@ static inline Type& StructAfter(TObject &X) #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ inline void _instance_assertion_on_line_##_line (void) const \ { \ - ASSERT_STATIC (_assertion); \ + static_assert ((_assertion), ""); \ ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ } # define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) @@ -129,14 +131,16 @@ static inline Type& StructAfter(TObject &X) */ /* Global nul-content Null pool. Enlarge as necessary. */ -/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ -static const void *_NullPool[(256+8) / sizeof (void *)]; + +#define HB_NULL_POOL_SIZE 264 +static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE."); +extern HB_INTERNAL const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]; /* Generic nul-content Null objects. */ template static inline const Type& Null (void) { - ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); - return *CastP (_NullPool); + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + return *CastP (_hb_NullPool); } /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ @@ -146,7 +150,7 @@ template <> \ /*static*/ inline const Type& Null (void) { \ return *CastP (_Null##Type); \ } /* The following line really exists such that we end in a place needing semicolon */ \ -ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) +static_assert (Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.") /* Accessor macro. */ #define Null(Type) Null() @@ -171,16 +175,6 @@ struct hb_dispatch_context_t * Sanitize */ -#ifndef HB_DEBUG_SANITIZE -#define HB_DEBUG_SANITIZE (HB_DEBUG+0) -#endif - - -#define TRACE_SANITIZE(this) \ - hb_auto_trace_t trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - /* This limits sanitizing time on really broken fonts. */ #ifndef HB_SANITIZE_MAX_EDITS #define HB_SANITIZE_MAX_EDITS 32 @@ -191,9 +185,9 @@ struct hb_sanitize_context_t : { inline hb_sanitize_context_t (void) : debug_depth (0), - start (NULL), end (NULL), + start (nullptr), end (nullptr), writable (false), edit_count (0), - blob (NULL) {} + blob (nullptr) {} inline const char *get_name (void) { return "SANITIZE"; } template @@ -213,7 +207,7 @@ struct hb_sanitize_context_t : inline void start_processing (void) { - this->start = hb_blob_get_data (this->blob, NULL); + this->start = hb_blob_get_data (this->blob, nullptr); this->end = this->start + hb_blob_get_length (this->blob); assert (this->start <= this->end); /* Must not overflow. */ this->edit_count = 0; @@ -232,8 +226,8 @@ struct hb_sanitize_context_t : this->start, this->end, this->edit_count); hb_blob_destroy (this->blob); - this->blob = NULL; - this->start = this->end = NULL; + this->blob = nullptr; + this->start = this->end = nullptr; } inline bool check_range (const void *base, unsigned int len) const @@ -348,7 +342,7 @@ struct Sanitizer } else { unsigned int edit_count = c->edit_count; if (edit_count && !c->writable) { - c->start = hb_blob_get_data_writable (blob, NULL); + c->start = hb_blob_get_data_writable (blob, nullptr); c->end = c->start + hb_blob_get_length (blob); if (c->start) { @@ -373,7 +367,7 @@ struct Sanitizer static const Type* lock_instance (hb_blob_t *blob) { hb_blob_make_immutable (blob); - const char *base = hb_blob_get_data (blob, NULL); + const char *base = hb_blob_get_data (blob, nullptr); return unlikely (!base) ? &Null(Type) : CastP (base); } }; @@ -384,16 +378,6 @@ struct Sanitizer * Serialize */ -#ifndef HB_DEBUG_SERIALIZE -#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) -#endif - - -#define TRACE_SERIALIZE(this) \ - hb_auto_trace_t trace \ - (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ - ""); - struct hb_serialize_context_t { @@ -444,7 +428,7 @@ struct hb_serialize_context_t { if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) { this->ran_out_of_room = true; - return NULL; + return nullptr; } memset (this->head, 0, size); char *ret = this->head; @@ -470,7 +454,7 @@ struct hb_serialize_context_t { unsigned int size = obj.get_size (); Type *ret = this->allocate_size (size); - if (unlikely (!ret)) return NULL; + if (unlikely (!ret)) return nullptr; memcpy (ret, obj, size); return ret; } @@ -480,7 +464,7 @@ struct hb_serialize_context_t { unsigned int size = obj.min_size; assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); - if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return NULL; + if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return nullptr; return reinterpret_cast (&obj); } @@ -489,7 +473,7 @@ struct hb_serialize_context_t { unsigned int size = obj.get_size (); assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); - if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return NULL; + if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return nullptr; return reinterpret_cast (&obj); } @@ -631,10 +615,11 @@ struct IntType inline bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } inline bool operator != (const IntType &o) const { return !(*this == o); } static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } - inline int cmp (Type a) const + template + inline int cmp (Type2 a) const { Type b = v; - if (sizeof (Type) < sizeof (int)) + if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int)) return (int) a - (int) b; else return a < b ? -1 : a == b ? 0 : +1; @@ -650,23 +635,22 @@ struct IntType DEFINE_SIZE_STATIC (Size); }; -typedef IntType CHAR; /* 8-bit signed integer. */ -typedef IntType BYTE; /* 8-bit unsigned integer. */ -typedef IntType INT8; /* 8-bit signed integer. */ -typedef IntType USHORT; /* 16-bit unsigned integer. */ -typedef IntType SHORT; /* 16-bit signed integer. */ -typedef IntType ULONG; /* 32-bit unsigned integer. */ -typedef IntType LONG; /* 32-bit signed integer. */ +typedef IntType UINT8; /* 8-bit unsigned integer. */ +typedef IntType INT8; /* 8-bit signed integer. */ +typedef IntType UINT16; /* 16-bit unsigned integer. */ +typedef IntType INT16; /* 16-bit signed integer. */ +typedef IntType UINT32; /* 32-bit unsigned integer. */ +typedef IntType INT32; /* 32-bit signed integer. */ typedef IntType UINT24; /* 24-bit unsigned integer. */ -/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ -typedef SHORT FWORD; +/* 16-bit signed integer (INT16) that describes a quantity in FUnits. */ +typedef INT16 FWORD; -/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ -typedef USHORT UFWORD; +/* 16-bit unsigned integer (UINT16) that describes a quantity in FUnits. */ +typedef UINT16 UFWORD; /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ -struct F2DOT14 : SHORT +struct F2DOT14 : INT16 { //inline float to_float (void) const { return ???; } //inline void set_float (float f) { v.set (f * ???); } @@ -675,7 +659,7 @@ struct F2DOT14 : SHORT }; /* 32-bit signed fixed-point number (16.16). */ -struct Fixed: LONG +struct Fixed: INT32 { //inline float to_float (void) const { return ???; } //inline void set_float (float f) { v.set (f * ???); } @@ -693,15 +677,15 @@ struct LONGDATETIME return_trace (likely (c->check_struct (this))); } protected: - LONG major; - ULONG minor; + INT32 major; + UINT32 minor; public: DEFINE_SIZE_STATIC (8); }; /* Array of four uint8s (length = 32 bits) used to identify a script, language * system, feature, or baseline */ -struct Tag : ULONG +struct Tag : UINT32 { /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ inline operator const char* (void) const { return reinterpret_cast (&this->v); } @@ -712,19 +696,16 @@ struct Tag : ULONG DEFINE_NULL_DATA (Tag, " "); /* Glyph index number, same as uint16 (length = 16 bits) */ -struct GlyphID : USHORT { - static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); } - inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; } -}; +typedef UINT16 GlyphID; /* Script/language-system/feature index */ -struct Index : USHORT { +struct Index : UINT16 { static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; }; DEFINE_NULL_DATA (Index, "\xff\xff"); /* Offset, Null offset = 0 */ -template +template struct Offset : Type { inline bool is_null (void) const { return 0 == *this; } @@ -732,15 +713,18 @@ struct Offset : Type DEFINE_SIZE_STATIC (sizeof(Type)); }; +typedef Offset Offset16; +typedef Offset Offset32; + /* CheckSum */ -struct CheckSum : ULONG +struct CheckSum : UINT32 { /* This is reference implementation from the spec. */ - static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length) + static inline uint32_t CalcTableChecksum (const UINT32 *Table, uint32_t Length) { uint32_t Sum = 0L; - const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; + const UINT32 *EndPtr = Table+((Length+3) & ~3) / UINT32::static_size; while (Table < EndPtr) Sum += *Table++; @@ -749,7 +733,7 @@ struct CheckSum : ULONG /* Note: data should be 4byte aligned and have 4byte padding at the end. */ inline void set_for_data (const void *data, unsigned int length) - { set (CalcTableChecksum ((const ULONG *) data, length)); } + { set (CalcTableChecksum ((const UINT32 *) data, length)); } public: DEFINE_SIZE_STATIC (4); @@ -760,7 +744,7 @@ struct CheckSum : ULONG * Version Numbers */ -template +template struct FixedVersion { inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; } @@ -784,7 +768,7 @@ struct FixedVersion * Use: (base+offset) */ -template +template struct OffsetTo : Offset { inline const Type& operator () (const void *base) const @@ -829,6 +813,7 @@ struct OffsetTo : Offset } DEFINE_SIZE_STATIC (sizeof(OffsetType)); }; +template struct LOffsetTo : OffsetTo {}; template static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); } template @@ -840,7 +825,7 @@ static inline Type& operator + (Base &base, OffsetTo &offset) */ /* An array with a number of elements. */ -template +template struct ArrayOf { const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const @@ -941,7 +926,7 @@ struct ArrayOf inline bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len)); + return_trace (len.sanitize (c) && c->check_array (array, Type::static_size, len)); } public: @@ -950,9 +935,10 @@ struct ArrayOf public: DEFINE_SIZE_ARRAY (sizeof (LenType), array); }; +template struct LArrayOf : ArrayOf {}; /* Array of Offset's */ -template +template struct OffsetArrayOf : ArrayOf > {}; /* Array of offsets relative to the beginning of the array itself. */ @@ -980,7 +966,7 @@ struct OffsetListOf : OffsetArrayOf /* An array starting at second element. */ -template +template struct HeadlessArrayOf { inline const Type& operator [] (unsigned int i) const @@ -1006,12 +992,6 @@ struct HeadlessArrayOf return_trace (true); } - inline bool sanitize_shallow (hb_sanitize_context_t *c) const - { - return c->check_struct (this) - && c->check_array (this, Type::static_size, len); - } - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1029,6 +1009,15 @@ struct HeadlessArrayOf return_trace (true); } + private: + inline bool sanitize_shallow (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (len.sanitize (c) && + (!len || c->check_array (array, Type::static_size, len - 1))); + } + + public: LenType len; Type array[VAR]; public: @@ -1036,19 +1025,22 @@ struct HeadlessArrayOf }; -/* An array with sorted elements. Supports binary searching. */ -template +/* + * An array with sorted elements. Supports binary searching. + */ +template struct SortedArrayOf : ArrayOf { template inline int bsearch (const SearchType &x) const { /* Hand-coded bsearch here since this is in the hot inner loop. */ + const Type *array = this->array; int min = 0, max = (int) this->len - 1; while (min <= max) { int mid = (min + max) / 2; - int c = this->array[mid].cmp (x); + int c = array[mid].cmp (x); if (c < 0) max = mid - 1; else if (c > 0) @@ -1060,6 +1052,131 @@ struct SortedArrayOf : ArrayOf } }; +/* + * Binary-search arrays + */ + +struct BinSearchHeader +{ + inline operator uint32_t (void) const { return len; } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + UINT16 len; + UINT16 searchRangeZ; + UINT16 entrySelectorZ; + UINT16 rangeShiftZ; + + public: + DEFINE_SIZE_STATIC (8); +}; + +template +struct BinSearchArrayOf : SortedArrayOf {}; + + +/* Lazy struct and blob loaders. */ + +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ +template +struct hb_lazy_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = nullptr; + } + + inline void fini (void) + { + if (instance && instance != &OT::Null(T)) + { + instance->fini(); + free (instance); + } + } + + inline const T* get (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + p = (T *) calloc (1, sizeof (T)); + if (unlikely (!p)) + p = const_cast (&OT::Null(T)); + else + p->init (face); + if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&instance), nullptr, p))) + { + if (p != &OT::Null(T)) + p->fini (); + goto retry; + } + } + return p; + } + + inline const T* operator-> (void) const + { + return get (); + } + + private: + hb_face_t *face; + T *instance; +}; + +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ +template +struct hb_lazy_table_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = nullptr; + blob = nullptr; + } + + inline void fini (void) + { + hb_blob_destroy (blob); + } + + inline const T* get (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + hb_blob_t *blob_ = OT::Sanitizer::sanitize (face->reference_table (T::tableTag)); + p = const_cast(OT::Sanitizer::lock_instance (blob_)); + if (!hb_atomic_ptr_cmpexch (const_cast(&instance), nullptr, p)) + { + hb_blob_destroy (blob_); + goto retry; + } + blob = blob_; + } + return p; + } + + inline const T* operator-> (void) const + { + return get(); + } + + private: + hb_face_t *face; + T *instance; + mutable hb_blob_t *blob; +}; + } /* namespace OT */ -- cgit v1.2.3