diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 65ea1f909..f012fbdbb 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -208,10 +208,12 @@ hb_font_funcs_set_glyph_contour_point_func hb_font_funcs_set_glyph_extents_func hb_font_funcs_set_glyph_from_name_func hb_font_funcs_set_glyph_h_advance_func +hb_font_funcs_set_glyph_h_advances_func hb_font_funcs_set_glyph_h_kerning_func hb_font_funcs_set_glyph_h_origin_func hb_font_funcs_set_glyph_name_func hb_font_funcs_set_glyph_v_advance_func +hb_font_funcs_set_glyph_v_advances_func hb_font_funcs_set_glyph_v_kerning_func hb_font_funcs_set_glyph_v_origin_func hb_font_funcs_set_nominal_glyph_func @@ -233,6 +235,8 @@ hb_font_get_glyph_from_name hb_font_get_glyph_from_name_func_t hb_font_get_glyph_h_advance hb_font_get_glyph_h_advance_func_t +hb_font_get_glyph_h_advances +hb_font_get_glyph_h_advances_func_t hb_font_get_glyph_h_kerning hb_font_get_glyph_h_kerning_func_t hb_font_get_glyph_h_origin @@ -245,6 +249,8 @@ hb_font_get_glyph_origin_for_direction hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_advance hb_font_get_glyph_v_advance_func_t +hb_font_get_glyph_v_advances +hb_font_get_glyph_v_advances_func_t hb_font_get_glyph_v_kerning hb_font_get_glyph_v_kerning_func_t hb_font_get_glyph_v_origin diff --git a/src/Makefile.sources b/src/Makefile.sources index 6779002af..4346c836f 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -19,6 +19,7 @@ HB_BASE_sources = \ hb-map.cc \ hb-machinery-private.hh \ hb-mutex-private.hh \ + hb-null.hh \ hb-object-private.hh \ hb-open-file-private.hh \ hb-open-type-private.hh \ @@ -53,6 +54,7 @@ HB_BASE_sources = \ hb-string-array.hh \ hb-unicode-private.hh \ hb-unicode.cc \ + hb-vector-private.hh \ hb-utf-private.hh \ hb-warning.cc \ $(NULL) diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index 3417033fa..36d4037ad 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -52,9 +52,9 @@ _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr) return Null(AAT::morx); } hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - const AAT::morx& morx = *(layout->morx.get ()); + const AAT::morx& morx = *(layout->table.morx.get ()); if (blob) - *blob = layout->morx.get_blob (); + *blob = layout->table.morx.get_blob (); return morx; } diff --git a/src/hb-blob-private.hh b/src/hb-blob-private.hh index 93fbc2d51..49ad68ece 100644 --- a/src/hb-blob-private.hh +++ b/src/hb-blob-private.hh @@ -76,6 +76,7 @@ struct hb_blob_t void *user_data; hb_destroy_func_t destroy; }; +DECLARE_NULL_INSTANCE (hb_blob_t); #endif /* HB_BLOB_PRIVATE_HH */ diff --git a/src/hb-blob.cc b/src/hb-blob.cc index 5bab1abbe..25c3e05aa 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -45,6 +45,20 @@ #include +DEFINE_NULL_INSTANCE (hb_blob_t) = +{ + HB_OBJECT_HEADER_STATIC, + + true, /* immutable */ + + nullptr, /* data */ + 0, /* length */ + HB_MEMORY_MODE_READONLY, /* mode */ + + nullptr, /* user_data */ + nullptr /* destroy */ +}; + /** * hb_blob_create: (skip) * @data: Pointer to blob data. @@ -182,20 +196,7 @@ hb_blob_copy_writable_or_fail (hb_blob_t *blob) hb_blob_t * hb_blob_get_empty (void) { - static const hb_blob_t _hb_blob_nil = { - HB_OBJECT_HEADER_STATIC, - - true, /* immutable */ - - nullptr, /* data */ - 0, /* length */ - HB_MEMORY_MODE_READONLY, /* mode */ - - nullptr, /* user_data */ - nullptr /* destroy */ - }; - - return const_cast (&_hb_blob_nil); + return const_cast (&Null(hb_blob_t)); } /** diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh index f45814070..a6c4b6963 100644 --- a/src/hb-buffer-private.hh +++ b/src/hb-buffer-private.hh @@ -83,7 +83,8 @@ HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t); * hb_buffer_t */ -struct hb_buffer_t { +struct hb_buffer_t +{ hb_object_header_t header; ASSERT_POD (); @@ -352,6 +353,7 @@ struct hb_buffer_t { info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; } }; +DECLARE_NULL_INSTANCE (hb_buffer_t); /* Loop over clusters. Duplicated in foreach_syllable(). */ diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index d04e1e80f..e79b45ae4 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -701,6 +701,28 @@ hb_buffer_t::guess_segment_properties (void) /* Public API */ +DEFINE_NULL_INSTANCE (hb_buffer_t) = +{ + HB_OBJECT_HEADER_STATIC, + + const_cast (&_hb_Null_hb_unicode_funcs_t), + HB_BUFFER_FLAG_DEFAULT, + HB_BUFFER_CLUSTER_LEVEL_DEFAULT, + HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, + HB_BUFFER_SCRATCH_FLAG_DEFAULT, + HB_BUFFER_MAX_LEN_DEFAULT, + HB_BUFFER_MAX_OPS_DEFAULT, + + HB_BUFFER_CONTENT_TYPE_INVALID, + HB_SEGMENT_PROPERTIES_DEFAULT, + false, /* successful */ + true, /* have_output */ + true /* have_positions */ + + /* Zero is good enough for everything else. */ +}; + + /** * hb_buffer_create: (Xconstructor) * @@ -743,27 +765,7 @@ hb_buffer_create (void) hb_buffer_t * hb_buffer_get_empty (void) { - static const hb_buffer_t _hb_buffer_nil = { - HB_OBJECT_HEADER_STATIC, - - const_cast (&_hb_unicode_funcs_nil), - HB_BUFFER_FLAG_DEFAULT, - HB_BUFFER_CLUSTER_LEVEL_DEFAULT, - HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, - HB_BUFFER_SCRATCH_FLAG_DEFAULT, - HB_BUFFER_MAX_LEN_DEFAULT, - HB_BUFFER_MAX_OPS_DEFAULT, - - HB_BUFFER_CONTENT_TYPE_INVALID, - HB_SEGMENT_PROPERTIES_DEFAULT, - false, /* successful */ - true, /* have_output */ - true /* have_positions */ - - /* Zero is good enough for everything else. */ - }; - - return const_cast (&_hb_buffer_nil); + return const_cast (&Null(hb_buffer_t)); } /** diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index fc7d1f0a9..8cbe6584b 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -232,6 +232,18 @@ hb_ctz (T v) * Tiny stuff. */ +/* ASCII tag/character handling */ +static inline bool ISALPHA (unsigned char c) +{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } +static inline bool ISALNUM (unsigned char c) +{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); } +static inline bool ISSPACE (unsigned char c) +{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; } +static inline unsigned char TOUPPER (unsigned char c) +{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; } +static inline unsigned char TOLOWER (unsigned char c) +{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; } + #undef MIN template static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; } @@ -262,6 +274,37 @@ hb_ceil_to_4 (unsigned int v) return ((v - 1) | 3) + 1; } +template class hb_assert_unsigned_t; +template <> class hb_assert_unsigned_t {}; +template <> class hb_assert_unsigned_t {}; +template <> class hb_assert_unsigned_t {}; +template <> class hb_assert_unsigned_t {}; + +template static inline bool +hb_in_range (T u, T lo, T hi) +{ + /* The sizeof() is here to force template instantiation. + * I'm sure there are better ways to do this but can't think of + * one right now. Declaring a variable won't work as HB_UNUSED + * is unusable on some platforms and unused types are less likely + * to generate a warning than unused variables. */ + static_assert ((sizeof (hb_assert_unsigned_t) >= 0), ""); + + /* The casts below are important as if T is smaller than int, + * the subtract results will become a signed int! */ + return (T)(u - lo) <= (T)(hi - lo); +} +template static inline bool +hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2) +{ + return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2); +} +template static inline bool +hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) +{ + return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3); +} + /* * Sort and search. @@ -445,303 +488,6 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o } -#define HB_VECTOR_INIT {0, 0, false, nullptr} -template -struct hb_vector_t -{ - unsigned int len; - unsigned int allocated; /* == 0 means allocation failed. */ - Type *arrayZ; - Type static_array[StaticSize]; - - void init (void) - { - len = 0; - allocated = ARRAY_LENGTH (static_array); - arrayZ = static_array; - } - - inline Type& operator [] (unsigned int i) - { - if (unlikely (i >= len)) - return Crap (Type); - return arrayZ[i]; - } - inline const Type& operator [] (unsigned int i) const - { - if (unlikely (i >= len)) - return Null(Type); - return arrayZ[i]; - } - - inline Type *push (void) - { - if (unlikely (!resize (len + 1))) - return &Crap(Type); - return &arrayZ[len - 1]; - } - inline Type *push (const Type& v) - { - Type *p = push (); - *p = v; - return p; - } - - /* Allocate for size but don't adjust len. */ - inline bool alloc (unsigned int size) - { - if (unlikely (!allocated)) - return false; - - if (likely (size <= allocated)) - return true; - - /* Reallocate */ - - unsigned int new_allocated = allocated; - while (size >= new_allocated) - new_allocated += (new_allocated >> 1) + 8; - - Type *new_array = nullptr; - - if (arrayZ == static_array) - { - new_array = (Type *) calloc (new_allocated, sizeof (Type)); - if (new_array) - memcpy (new_array, arrayZ, len * sizeof (Type)); - } - else - { - bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type)); - if (likely (!overflows)) - new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type)); - } - - if (unlikely (!new_array)) - { - allocated = 0; - return false; - } - - arrayZ = new_array; - allocated = new_allocated; - - return true; - } - - inline bool resize (int size_) - { - unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; - if (!alloc (size)) - return false; - - if (size > len) - memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ)); - - len = size; - return true; - } - - inline void pop (void) - { - if (!len) return; - len--; - } - - inline void remove (unsigned int i) - { - if (unlikely (i >= len)) - return; - memmove (static_cast (&arrayZ[i]), - static_cast (&arrayZ[i + 1]), - (len - i - 1) * sizeof (Type)); - len--; - } - - inline void shrink (int size_) - { - unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; - if (size < len) - len = size; - } - - template - inline Type *find (T v) { - for (unsigned int i = 0; i < len; i++) - if (arrayZ[i] == v) - return &arrayZ[i]; - return nullptr; - } - template - inline const Type *find (T v) const { - for (unsigned int i = 0; i < len; i++) - if (arrayZ[i] == v) - return &arrayZ[i]; - return nullptr; - } - - inline void qsort (int (*cmp)(const void*, const void*)) - { - ::qsort (arrayZ, len, sizeof (Type), cmp); - } - - inline void qsort (void) - { - ::qsort (arrayZ, len, sizeof (Type), Type::cmp); - } - - inline void qsort (unsigned int start, unsigned int end) - { - ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp); - } - - template - inline Type *lsearch (const T &x) - { - for (unsigned int i = 0; i < len; i++) - if (0 == this->arrayZ[i].cmp (&x)) - return &arrayZ[i]; - return nullptr; - } - - template - inline Type *bsearch (const T &x) - { - unsigned int i; - return bfind (x, &i) ? &arrayZ[i] : nullptr; - } - template - inline const Type *bsearch (const T &x) const - { - unsigned int i; - return bfind (x, &i) ? &arrayZ[i] : nullptr; - } - template - inline bool bfind (const T &x, unsigned int *i) const - { - int min = 0, max = (int) this->len - 1; - while (min <= max) - { - int mid = (min + max) / 2; - int c = this->arrayZ[mid].cmp (&x); - if (c < 0) - max = mid - 1; - else if (c > 0) - min = mid + 1; - else - { - *i = mid; - return true; - } - } - if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0)) - max++; - *i = max; - return false; - } - - inline void fini (void) - { - if (arrayZ != static_array) - free (arrayZ); - arrayZ = nullptr; - allocated = len = 0; - } -}; - - -#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT} -template -struct hb_lockable_set_t -{ - hb_vector_t items; - - inline void init (void) { items.init (); } - - template - inline item_t *replace_or_insert (T v, lock_t &l, bool replace) - { - l.lock (); - item_t *item = items.find (v); - if (item) { - if (replace) { - item_t old = *item; - *item = v; - l.unlock (); - old.fini (); - } - else { - item = nullptr; - l.unlock (); - } - } else { - item = items.push (v); - l.unlock (); - } - return item; - } - - template - inline void remove (T v, lock_t &l) - { - l.lock (); - item_t *item = items.find (v); - if (item) { - item_t old = *item; - *item = items[items.len - 1]; - items.pop (); - l.unlock (); - old.fini (); - } else { - l.unlock (); - } - } - - template - inline bool find (T v, item_t *i, lock_t &l) - { - l.lock (); - item_t *item = items.find (v); - if (item) - *i = *item; - l.unlock (); - return !!item; - } - - template - inline item_t *find_or_insert (T v, lock_t &l) - { - l.lock (); - item_t *item = items.find (v); - if (!item) { - item = items.push (v); - } - l.unlock (); - return item; - } - - inline void fini (lock_t &l) - { - if (!items.len) { - /* No need for locking. */ - items.fini (); - return; - } - l.lock (); - while (items.len) { - item_t old = items[items.len - 1]; - items.pop (); - l.unlock (); - old.fini (); - l.lock (); - } - items.fini (); - l.unlock (); - } - -}; - - template struct hb_auto_t : Type { diff --git a/src/hb-face-private.hh b/src/hb-face-private.hh index fe3b8b240..a4b2cd36d 100644 --- a/src/hb-face-private.hh +++ b/src/hb-face-private.hh @@ -39,7 +39,8 @@ * hb_face_t */ -struct hb_face_t { +struct hb_face_t +{ hb_object_header_t header; ASSERT_POD (); @@ -55,16 +56,13 @@ struct hb_face_t { struct hb_shaper_data_t shaper_data; /* Various shaper data. */ - /* Various non-shaping data. */ - /* ... */ - /* Cache */ - struct plan_node_t { + struct plan_node_t + { hb_shape_plan_t *shape_plan; plan_node_t *next; } *shape_plans; - inline hb_blob_t *reference_table (hb_tag_t tag) const { hb_blob_t *blob; @@ -97,8 +95,7 @@ struct hb_face_t { HB_INTERNAL void load_upem (void) const; HB_INTERNAL void load_num_glyphs (void) const; }; - -extern HB_INTERNAL const hb_face_t _hb_face_nil; +DECLARE_NULL_INSTANCE (hb_face_t); #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face); diff --git a/src/hb-face.cc b/src/hb-face.cc index 9d17c4a5f..e1492756c 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -63,7 +63,8 @@ hb_face_count (hb_blob_t *blob) * hb_face_t */ -const hb_face_t _hb_face_nil = { +DEFINE_NULL_INSTANCE (hb_face_t) = +{ HB_OBJECT_HEADER_STATIC, true, /* immutable */ @@ -215,7 +216,7 @@ hb_face_create (hb_blob_t *blob, hb_face_t * hb_face_get_empty (void) { - return const_cast (&_hb_face_nil); + return const_cast (&Null(hb_face_t)); } diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 9f657db60..6862e0621 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -35,7 +35,6 @@ #include "hb-shaper-private.hh" - /* * hb_font_funcs_t */ @@ -47,6 +46,8 @@ HB_FONT_FUNC_IMPLEMENT (variation_glyph) \ HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \ HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ @@ -57,7 +58,8 @@ HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \ /* ^--- Add new callbacks here */ -struct hb_font_funcs_t { +struct hb_font_funcs_t +{ hb_object_header_t header; ASSERT_POD (); @@ -89,14 +91,15 @@ struct hb_font_funcs_t { ]) (void); } get; }; - +DECLARE_NULL_INSTANCE (hb_font_funcs_t); /* * hb_font_t */ -struct hb_font_t { +struct hb_font_t +{ hb_object_header_t header; ASSERT_POD (); @@ -233,6 +236,32 @@ struct hb_font_t { klass->user_data.glyph_v_advance); } + inline void get_glyph_h_advances (unsigned int count, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + hb_position_t *first_advance, + unsigned int advance_stride) + { + return klass->get.f.glyph_h_advances (this, user_data, + count, + first_glyph, glyph_stride, + first_advance, advance_stride, + klass->user_data.glyph_h_advances); + } + + inline void get_glyph_v_advances (unsigned int count, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + hb_position_t *first_advance, + unsigned int advance_stride) + { + return klass->get.f.glyph_v_advances (this, user_data, + count, + first_glyph, glyph_stride, + first_advance, advance_stride, + klass->user_data.glyph_v_advances); + } + inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y) { @@ -553,6 +582,7 @@ struct hb_font_t { return (float) v * scale / face->get_upem (); } }; +DECLARE_NULL_INSTANCE (hb_font_t); #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font); diff --git a/src/hb-font.cc b/src/hb-font.cc index 4d62b9e9c..e29b80f4d 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -29,6 +29,7 @@ #include "hb-private.hh" #include "hb-font-private.hh" +#include "hb-machinery-private.hh" /* @@ -45,10 +46,10 @@ hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED, return false; } static hb_bool_t -hb_font_get_font_h_extents_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_font_extents_t *metrics, - void *user_data HB_UNUSED) +hb_font_get_font_h_extents_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) { hb_bool_t ret = font->parent->get_font_h_extents (metrics); if (ret) { @@ -69,10 +70,10 @@ hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED, return false; } static hb_bool_t -hb_font_get_font_v_extents_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_font_extents_t *metrics, - void *user_data HB_UNUSED) +hb_font_get_font_v_extents_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) { hb_bool_t ret = font->parent->get_font_v_extents (metrics); if (ret) { @@ -94,11 +95,11 @@ hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED, return false; } static hb_bool_t -hb_font_get_nominal_glyph_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t unicode, - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) +hb_font_get_nominal_glyph_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) { return font->parent->get_nominal_glyph (unicode, glyph); } @@ -115,12 +116,12 @@ hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED, return false; } static hb_bool_t -hb_font_get_variation_glyph_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t unicode, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) +hb_font_get_variation_glyph_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) { return font->parent->get_variation_glyph (unicode, variation_selector, glyph); } @@ -129,16 +130,16 @@ hb_font_get_variation_glyph_parent (hb_font_t *font, static hb_position_t hb_font_get_glyph_h_advance_nil (hb_font_t *font, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, void *user_data HB_UNUSED) { return font->x_scale; } static hb_position_t -hb_font_get_glyph_h_advance_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - void *user_data HB_UNUSED) +hb_font_get_glyph_h_advance_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) { return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); } @@ -146,21 +147,117 @@ hb_font_get_glyph_h_advance_parent (hb_font_t *font, static hb_position_t hb_font_get_glyph_v_advance_nil (hb_font_t *font, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, void *user_data HB_UNUSED) { /* TODO use font_extents.ascender+descender */ return font->y_scale; } static hb_position_t -hb_font_get_glyph_v_advance_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - void *user_data HB_UNUSED) +hb_font_get_glyph_v_advance_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) { return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); } +static void +hb_font_get_glyph_h_advances_nil (hb_font_t* font, + void* font_data HB_UNUSED, + unsigned int count, + hb_codepoint_t *first_glyph HB_UNUSED, + unsigned int glyph_stride HB_UNUSED, + hb_position_t *first_advance, + unsigned int advance_stride, + void *user_data HB_UNUSED) +{ + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->get_glyph_h_advance (*first_glyph); + first_glyph = &StructAtOffset (first_glyph, glyph_stride); + first_advance = &StructAtOffset (first_advance, advance_stride); + } +} +static void +hb_font_get_glyph_h_advances_default (hb_font_t* font, + void* font_data HB_UNUSED, + unsigned int count, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + hb_position_t *first_advance, + unsigned int advance_stride, + void *user_data HB_UNUSED) +{ + if (font->has_glyph_h_advance_func ()) + { + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->get_glyph_h_advance (*first_glyph); + first_glyph = &StructAtOffset (first_glyph, glyph_stride); + first_advance = &StructAtOffset (first_advance, advance_stride); + } + return; + } + + font->parent->get_glyph_h_advances (count, + first_glyph, glyph_stride, + first_advance, advance_stride); + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->parent_scale_x_distance (*first_advance); + first_advance = &StructAtOffset (first_advance, advance_stride); + } +} + +static void +hb_font_get_glyph_v_advances_nil (hb_font_t* font, + void* font_data HB_UNUSED, + unsigned int count, + hb_codepoint_t *first_glyph HB_UNUSED, + unsigned int glyph_stride HB_UNUSED, + hb_position_t *first_advance, + unsigned int advance_stride, + void *user_data HB_UNUSED) +{ + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->get_glyph_v_advance (*first_glyph); + first_glyph = &StructAtOffset (first_glyph, glyph_stride); + first_advance = &StructAtOffset (first_advance, advance_stride); + } +} +static void +hb_font_get_glyph_v_advances_default (hb_font_t* font, + void* font_data HB_UNUSED, + unsigned int count, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + hb_position_t *first_advance, + unsigned int advance_stride, + void *user_data HB_UNUSED) +{ + if (font->has_glyph_v_advance_func ()) + { + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->get_glyph_v_advance (*first_glyph); + first_glyph = &StructAtOffset (first_glyph, glyph_stride); + first_advance = &StructAtOffset (first_advance, advance_stride); + } + return; + } + + font->parent->get_glyph_v_advances (count, + first_glyph, glyph_stride, + first_advance, advance_stride); + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->parent_scale_y_distance (*first_advance); + first_advance = &StructAtOffset (first_advance, advance_stride); + } +} + static hb_bool_t hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, @@ -173,12 +270,12 @@ hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED, return true; } static hb_bool_t -hb_font_get_glyph_h_origin_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_position_t *x, - hb_position_t *y, - void *user_data HB_UNUSED) +hb_font_get_glyph_h_origin_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) { hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y); if (ret) @@ -198,12 +295,12 @@ hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED, return false; } static hb_bool_t -hb_font_get_glyph_v_origin_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_position_t *x, - hb_position_t *y, - void *user_data HB_UNUSED) +hb_font_get_glyph_v_origin_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) { hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y); if (ret) @@ -221,11 +318,11 @@ hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED, return 0; } static hb_position_t -hb_font_get_glyph_h_kerning_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t left_glyph, - hb_codepoint_t right_glyph, - void *user_data HB_UNUSED) +hb_font_get_glyph_h_kerning_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t left_glyph, + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) { return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); } @@ -240,11 +337,11 @@ hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED, return 0; } static hb_position_t -hb_font_get_glyph_v_kerning_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t top_glyph, - hb_codepoint_t bottom_glyph, - void *user_data HB_UNUSED) +hb_font_get_glyph_v_kerning_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t top_glyph, + hb_codepoint_t bottom_glyph, + void *user_data HB_UNUSED) { return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); } @@ -260,11 +357,11 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED, return false; } static hb_bool_t -hb_font_get_glyph_extents_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_glyph_extents_t *extents, - void *user_data HB_UNUSED) +hb_font_get_glyph_extents_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + void *user_data HB_UNUSED) { hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); if (ret) { @@ -287,13 +384,13 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED, return false; } static hb_bool_t -hb_font_get_glyph_contour_point_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - unsigned int point_index, - hb_position_t *x, - hb_position_t *y, - void *user_data HB_UNUSED) +hb_font_get_glyph_contour_point_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + unsigned int point_index, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) { hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); if (ret) @@ -312,11 +409,11 @@ hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED, return false; } static hb_bool_t -hb_font_get_glyph_name_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - char *name, unsigned int size, - void *user_data HB_UNUSED) +hb_font_get_glyph_name_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + char *name, unsigned int size, + void *user_data HB_UNUSED) { return font->parent->get_glyph_name (glyph, name, size); } @@ -332,16 +429,17 @@ hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED, return false; } static hb_bool_t -hb_font_get_glyph_from_name_parent (hb_font_t *font, - void *font_data HB_UNUSED, - const char *name, int len, /* -1 means nul-terminated */ - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) +hb_font_get_glyph_from_name_default (hb_font_t *font, + void *font_data HB_UNUSED, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) { return font->parent->get_glyph_from_name (name, len, glyph); } -static const hb_font_funcs_t _hb_font_funcs_nil = { +DEFINE_NULL_INSTANCE (hb_font_funcs_t) = +{ HB_OBJECT_HEADER_STATIC, true, /* immutable */ @@ -364,7 +462,8 @@ static const hb_font_funcs_t _hb_font_funcs_nil = { } } }; -static const hb_font_funcs_t _hb_font_funcs_parent = { + +static const hb_font_funcs_t _hb_font_funcs_default = { HB_OBJECT_HEADER_STATIC, true, /* immutable */ @@ -381,7 +480,7 @@ static const hb_font_funcs_t _hb_font_funcs_parent = { }, { { -#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent, +#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT } @@ -406,7 +505,7 @@ hb_font_funcs_create (void) if (!(ffuncs = hb_object_create ())) return hb_font_funcs_get_empty (); - ffuncs->get = _hb_font_funcs_parent.get; + ffuncs->get = _hb_font_funcs_default.get; return ffuncs; } @@ -423,7 +522,7 @@ hb_font_funcs_create (void) hb_font_funcs_t * hb_font_funcs_get_empty (void) { - return const_cast (&_hb_font_funcs_parent); + return const_cast (&_hb_font_funcs_default); } /** @@ -562,9 +661,9 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ ffuncs->user_data.name = user_data; \ ffuncs->destroy.name = destroy; \ } else { \ - ffuncs->get.f.name = hb_font_get_##name##_parent; \ - ffuncs->user_data.name = nullptr; \ - ffuncs->destroy.name = nullptr; \ + ffuncs->get.f.name = hb_font_get_##name##_default; \ + ffuncs->user_data.name = nullptr; \ + ffuncs->destroy.name = nullptr; \ } \ } @@ -574,9 +673,8 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS bool hb_font_t::has_func (unsigned int i) { - if (parent && parent != hb_font_get_empty () && parent->has_func (i)) - return true; - return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i]; + return (this->klass->get.array[i] != _hb_font_funcs_default.get.array[i]) || + (parent && parent != &_hb_Null_hb_font_t && parent->has_func (i)); } /* Public getters */ @@ -1100,6 +1198,37 @@ hb_font_glyph_from_string (hb_font_t *font, * hb_font_t */ +DEFINE_NULL_INSTANCE (hb_font_t) = +{ + HB_OBJECT_HEADER_STATIC, + + true, /* immutable */ + + nullptr, /* parent */ + const_cast (&_hb_Null_hb_face_t), + + 1000, /* x_scale */ + 1000, /* y_scale */ + + 0, /* x_ppem */ + 0, /* y_ppem */ + 0, /* ptem */ + + 0, /* num_coords */ + nullptr, /* coords */ + + const_cast (&_hb_Null_hb_font_funcs_t), /* klass */ + nullptr, /* user_data */ + nullptr, /* destroy */ + + { +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT + } +}; + + /** * hb_font_create: (Xconstructor) * @face: a face. @@ -1187,36 +1316,7 @@ hb_font_create_sub_font (hb_font_t *parent) hb_font_t * hb_font_get_empty (void) { - static const hb_font_t _hb_font_nil = { - HB_OBJECT_HEADER_STATIC, - - true, /* immutable */ - - nullptr, /* parent */ - const_cast (&_hb_face_nil), - - 1000, /* x_scale */ - 1000, /* y_scale */ - - 0, /* x_ppem */ - 0, /* y_ppem */ - 0, /* ptem */ - - 0, /* num_coords */ - nullptr, /* coords */ - - const_cast (&_hb_font_funcs_nil), /* klass */ - nullptr, /* user_data */ - nullptr, /* destroy */ - - { -#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - } - }; - - return const_cast (&_hb_font_nil); + return const_cast (&Null(hb_font_t)); } /** diff --git a/src/hb-font.h b/src/hb-font.h index c95b61d2d..181d15ee3 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -132,6 +132,16 @@ typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t; typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t; +typedef void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data, + unsigned count, + hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride, + void *user_data); +typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_h_advances_func_t; +typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t; + typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y, @@ -264,6 +274,38 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_advance_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_glyph_h_advances_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: REPLACEME + **/ +HB_EXTERN void +hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_advances_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_glyph_v_advances_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: REPLACEME + **/ +HB_EXTERN void +hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_advances_func_t func, + void *user_data, hb_destroy_func_t destroy); + /** * hb_font_funcs_set_glyph_h_origin_func: * @ffuncs: font functions. diff --git a/src/hb-machinery-private.hh b/src/hb-machinery-private.hh index 40e42071f..119625c45 100644 --- a/src/hb-machinery-private.hh +++ b/src/hb-machinery-private.hh @@ -594,7 +594,7 @@ template -struct hb_base_lazy_loader_t +struct hb_lazy_loader_t { static_assert (WheresFace > 0, ""); @@ -602,6 +602,7 @@ struct hb_base_lazy_loader_t inline const Subclass* thiz (void) const { return static_cast (this); } inline Subclass* thiz (void) { return static_cast (this); } + inline void init0 (void) {} /* Init, when memory is already set to 0. No-op for us. */ inline void init (void) { instance = nullptr; @@ -612,10 +613,8 @@ struct hb_base_lazy_loader_t thiz ()->destroy (instance); } - inline const Returned * operator-> (void) const - { - return thiz ()->get (); - } + inline const Returned * operator -> (void) const { return thiz ()->get (); } + inline const Returned & operator * (void) const { return *thiz ()->get (); } inline Stored * get_stored (void) const { @@ -624,7 +623,11 @@ struct hb_base_lazy_loader_t if (unlikely (!p)) { hb_face_t *face = *(((hb_face_t **) this) - WheresFace); - p = thiz ()->create (face); + if (likely (!p)) + p = thiz ()->create (face); + if (unlikely (!p)) + p = thiz ()->create (nullptr); /* Produce nil object. */ + assert (p); if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&this->instance), nullptr, p))) { thiz ()->destroy (p); @@ -634,6 +637,12 @@ struct hb_base_lazy_loader_t return p; } + inline void set_stored (Stored *instance_) + { + assert (instance == nullptr); + instance = instance_; + } + inline const Returned * get (void) const { return thiz ()->convert (get_stored ()); @@ -652,7 +661,7 @@ struct hb_base_lazy_loader_t /* Specializations. */ template -struct hb_lazy_loader_t : hb_base_lazy_loader_t, T> +struct hb_object_lazy_loader_t : hb_lazy_loader_t, T> { static inline T *create (hb_face_t *face) { @@ -676,7 +685,7 @@ struct hb_lazy_loader_t : hb_base_lazy_loader_t -struct hb_table_lazy_loader_t : hb_base_lazy_loader_t, T, hb_blob_t> +struct hb_table_lazy_loader_t : hb_lazy_loader_t, T, hb_blob_t> { static inline hb_blob_t *create (hb_face_t *face) { diff --git a/src/hb-null.hh b/src/hb-null.hh new file mode 100644 index 000000000..713c88e39 --- /dev/null +++ b/src/hb-null.hh @@ -0,0 +1,106 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_NULL_HH +#define HB_NULL_HH + +#include "hb-private.hh" + + +/* + * Static pools + */ + +/* Global nul-content Null pool. Enlarge as necessary. */ + +#define HB_NULL_POOL_SIZE 800 + +extern HB_INTERNAL +hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)]; + +/* Generic nul-content Null objects. */ +template +static inline Type const & Null (void) { + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + return *reinterpret_cast (_hb_NullPool); +} +#define Null(Type) Null() + +/* Specializaitons for arbitrary-content Null objects expressed in bytes. */ +#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \ +} /* Close namespace. */ \ +extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]; \ +template <> \ +/*static*/ inline const Namespace::Type& Null (void) { \ + return *reinterpret_cast (_hb_Null_##Namespace##_##Type); \ +} \ +namespace Namespace { \ +static_assert (true, "Just so we take semicolon after.") +#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \ +const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size] + +/* Specializaitons for arbitrary-content Null objects expressed as struct initializer. */ +#define DECLARE_NULL_INSTANCE(Type) \ +extern HB_INTERNAL const Type _hb_Null_##Type; \ +template <> \ +/*static*/ inline const Type& Null (void) { \ + return _hb_Null_##Type; \ +} \ +static_assert (true, "Just so we take semicolon after.") +#define DEFINE_NULL_INSTANCE(Type) \ +const Type _hb_Null_##Type + +/* Global writable pool. Enlarge as necessary. */ + +/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool + * for correct operation. It only exist to catch and divert program logic bugs instead of + * causing bad memory access. So, races there are not actually introducing incorrectness + * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */ +extern HB_INTERNAL +/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)]; + +/* CRAP pool: Common Region for Access Protection. */ +template +static inline Type& Crap (void) { + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + Type *obj = reinterpret_cast (_hb_CrapPool); + *obj = Null(Type); + return *obj; +} +#define Crap(Type) Crap() + +template +struct CrapOrNull { + static inline Type & get (void) { return Crap(Type); } +}; +template +struct CrapOrNull { + static inline Type const & get (void) { return Null(Type); } +}; +#define CrapOrNull(Type) CrapOrNull::get () + + +#endif /* HB_NULL_HH */ diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh index 36d27a891..472554882 100644 --- a/src/hb-object-private.hh +++ b/src/hb-object-private.hh @@ -35,9 +35,107 @@ #include "hb-private.hh" #include "hb-atomic-private.hh" #include "hb-mutex-private.hh" +#include "hb-vector-private.hh" -/* reference_count */ +/* + * Lockable set + */ + +template +struct hb_lockable_set_t +{ + hb_vector_t items; + + inline void init (void) { items.init (); } + + template + inline item_t *replace_or_insert (T v, lock_t &l, bool replace) + { + l.lock (); + item_t *item = items.find (v); + if (item) { + if (replace) { + item_t old = *item; + *item = v; + l.unlock (); + old.fini (); + } + else { + item = nullptr; + l.unlock (); + } + } else { + item = items.push (v); + l.unlock (); + } + return item; + } + + template + inline void remove (T v, lock_t &l) + { + l.lock (); + item_t *item = items.find (v); + if (item) { + item_t old = *item; + *item = items[items.len - 1]; + items.pop (); + l.unlock (); + old.fini (); + } else { + l.unlock (); + } + } + + template + inline bool find (T v, item_t *i, lock_t &l) + { + l.lock (); + item_t *item = items.find (v); + if (item) + *i = *item; + l.unlock (); + return !!item; + } + + template + inline item_t *find_or_insert (T v, lock_t &l) + { + l.lock (); + item_t *item = items.find (v); + if (!item) { + item = items.push (v); + } + l.unlock (); + return item; + } + + inline void fini (lock_t &l) + { + if (!items.len) { + /* No need for locking. */ + items.fini (); + return; + } + l.lock (); + while (items.len) { + item_t old = items[items.len - 1]; + items.pop (); + l.unlock (); + old.fini (); + l.lock (); + } + items.fini (); + l.unlock (); + } + +}; + + +/* + * Reference-count. + */ #define HB_REFERENCE_COUNT_INERT_VALUE 0 #define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD @@ -89,7 +187,9 @@ struct hb_user_data_array_t }; -/* object_header */ +/* + * Object header + */ struct hb_object_header_t { @@ -103,7 +203,9 @@ struct hb_object_header_t }; -/* object */ +/* + * Object + */ template static inline void hb_object_trace (const Type *obj, const char *function) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index bae2eed81..5580565f1 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -140,7 +140,6 @@ struct Tag : HBUINT32 public: DEFINE_SIZE_STATIC (4); }; -DEFINE_NULL_DATA (OT, Tag, " "); /* Glyph index number, same as uint16 (length = 16 bits) */ typedef HBUINT16 GlyphID; @@ -152,7 +151,7 @@ typedef HBUINT16 NameID; struct Index : HBUINT16 { static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; }; -DEFINE_NULL_DATA (OT, Index, "\xff\xff"); +DECLARE_NULL_NAMESPACE_BYTES (OT, Index); /* Offset, Null offset = 0 */ template diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 565ca808f..e25bb6916 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -42,16 +42,39 @@ struct hb_ot_font_t { + inline void init (hb_face_t *face) + { + cmap.init (face); + h_metrics.init (face); + v_metrics.init (face, h_metrics.ascender - h_metrics.descender); /* TODO Can we do this lazily? */ + + this->face = face; + glyf.init (); + cbdt.init (); + post.init (); + kern.init (); + } + inline void fini (void) + { + cmap.fini (); + h_metrics.fini (); + v_metrics.fini (); + + glyf.fini (); + cbdt.fini (); + post.fini (); + kern.fini (); + } + OT::cmap::accelerator_t cmap; OT::hmtx::accelerator_t h_metrics; OT::vmtx::accelerator_t v_metrics; - hb_face_t *face; /* MUST be before the lazy loaders. */ - hb_lazy_loader_t<1, OT::glyf::accelerator_t> glyf; - hb_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt; - hb_lazy_loader_t<3, OT::post::accelerator_t> post; - hb_lazy_loader_t<4, OT::kern::accelerator_t> kern; - hb_lazy_loader_t<5, OT::kern::accelerator_t> cff2; + hb_face_t *face; /* MUST be JUST before the lazy loaders. */ + hb_object_lazy_loader_t<1, OT::glyf::accelerator_t> glyf; + hb_object_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt; + hb_object_lazy_loader_t<3, OT::post::accelerator_t> post; + hb_object_lazy_loader_t<4, OT::kern::accelerator_t> kern; }; @@ -63,14 +86,7 @@ _hb_ot_font_create (hb_face_t *face) if (unlikely (!ot_font)) return nullptr; - ot_font->cmap.init (face); - ot_font->h_metrics.init (face); - ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ - ot_font->face = face; - ot_font->glyf.init (); - ot_font->cbdt.init (); - ot_font->post.init (); - ot_font->kern.init (); + ot_font->init (face); return ot_font; } @@ -80,13 +96,7 @@ _hb_ot_font_destroy (void *data) { hb_ot_font_t *ot_font = (hb_ot_font_t *) data; - ot_font->cmap.fini (); - ot_font->h_metrics.fini (); - ot_font->v_metrics.fini (); - ot_font->glyf.fini (); - ot_font->cbdt.fini (); - ot_font->post.fini (); - ot_font->kern.fini (); + ot_font->fini (); free (ot_font); } diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh index ce6ee1e22..bcf89e462 100644 --- a/src/hb-ot-glyf-table.hh +++ b/src/hb-ot-glyf-table.hh @@ -238,9 +238,9 @@ struct glyf hb_blob_t *head_blob = hb_sanitize_context_t().reference_table (face); const head *head_table = head_blob->as (); - if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0) + if (head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0) { - /* head table is not present, or in an unknown format. Leave num_glyphs=0, that takes care of disabling us. */ + /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ hb_blob_destroy (head_blob); return; } @@ -270,7 +270,7 @@ struct glyf inline bool get_composite (hb_codepoint_t glyph, CompositeGlyphHeader::Iterator *composite /* OUT */) const { - if (this->glyf_table == &Null(glyf) || !num_glyphs) + if (unlikely (!num_glyphs)) return false; unsigned int start_offset, end_offset; diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh index 965e30a08..fded120be 100644 --- a/src/hb-ot-head-table.hh +++ b/src/hb-ot-head-table.hh @@ -141,8 +141,8 @@ struct head * -1: Only strongly right to left; * -2: Like -1 but also contains neutrals. */ public: - HBINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */ - HBINT16 glyphDataFormat; /* 0 for current format. */ + HBUINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */ + HBUINT16 glyphDataFormat; /* 0 for current format. */ DEFINE_SIZE_STATIC (54); }; diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index 33dce8909..96da07fb5 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -33,13 +33,16 @@ namespace OT { -#define NOT_INDEXED ((unsigned int) -1) - /* * BASE -- Baseline * https://docs.microsoft.com/en-us/typography/opentype/spec/base */ + +/* XXX Review this. */ +#define NOT_INDEXED ((unsigned int) -1) + + struct BaseCoordFormat1 { inline int get_coord (void) const { return coordinate; } @@ -52,7 +55,7 @@ struct BaseCoordFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - HBINT16 coordinate; /* X or Y value, in design units */ + FWORD coordinate; /* X or Y value, in design units */ public: DEFINE_SIZE_STATIC (4); }; @@ -73,7 +76,7 @@ struct BaseCoordFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - HBINT16 coordinate; /* X or Y value, in design units */ + FWORD coordinate; /* X or Y value, in design units */ GlyphID referenceGlyph; /* Glyph ID of control glyph */ HBUINT16 coordPoint; /* Index of contour point on the * reference glyph */ @@ -97,7 +100,7 @@ struct BaseCoordFormat3 protected: HBUINT16 format; /* Format identifier--format = 3 */ - HBINT16 coordinate; /* X or Y value, in design units */ + FWORD coordinate; /* X or Y value, in design units */ OffsetTo deviceTable; /* Offset to Device table for X or * Y value, from beginning of * BaseCoord table (may be NULL). */ @@ -109,6 +112,7 @@ struct BaseCoord { inline int get_coord (void) const { + /* XXX wire up direction and font. */ switch (u.format) { case 1: return u.format1.get_coord (); case 2: return u.format2.get_coord (); @@ -142,14 +146,10 @@ struct BaseCoord struct FeatMinMaxRecord { - inline int get_min_value (void) const - { return (this+minCoord).get_coord(); } + inline int get_min_value (void) const { return (this+minCoord).get_coord(); } + inline int get_max_value (void) const { return (this+maxCoord).get_coord(); } - inline int get_max_value (void) const - { return (this+maxCoord).get_coord(); } - - inline const Tag &get_tag () const - { return tag; } + inline const Tag& get_tag () const { return tag; } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { @@ -181,7 +181,7 @@ struct MinMax unsigned int count = featMinMaxRecords.len; for (unsigned int i = 0; i < count; i++) { - Tag tag = featMinMaxRecords[i].get_tag(); + Tag tag = featMinMaxRecords[i].get_tag (); int cmp = tag.cmp(featureTableTag); if (cmp == 0) return i; if (cmp > 0) return NOT_INDEXED; @@ -233,13 +233,13 @@ struct BaseLangSysRecord { return baseLangSysTag; } inline unsigned int get_feature_tag_index (Tag featureTableTag) const - { return (this+minMax).get_feature_tag_index(featureTableTag); } + { return (this+minMax).get_feature_tag_index( featureTableTag); } inline int get_min_value (unsigned int featureTableTagIndex) const - { return (this+minMax).get_min_value(featureTableTagIndex); } + { return (this+minMax).get_min_value( featureTableTagIndex); } inline int get_max_value (unsigned int featureTableTagIndex) const - { return (this+minMax).get_max_value(featureTableTagIndex); } + { return (this+minMax).get_max_value (featureTableTagIndex); } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { @@ -263,34 +263,34 @@ struct BaseValues inline int get_base_coord (unsigned int baselineTagIndex) const { - return (this+baseCoords[baselineTagIndex]).get_coord(); + return (this+baseCoords[baselineTagIndex]).get_coord (); } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - defaultIndex <= baseCoordCount && - baseCoords.sanitize (c, this)); + baseCoords.sanitize (c, this)); } protected: Index defaultIndex; - HBUINT16 baseCoordCount; OffsetArrayOf baseCoords; public: - DEFINE_SIZE_ARRAY (6, baseCoords); - + DEFINE_SIZE_ARRAY (4, baseCoords); }; struct BaseScript { inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const { + /* XXX bsearch */ Tag tag; int cmp; - for (unsigned int i = 0; i < baseLangSysCount; i++) { - tag = baseLangSysRecords[i].get_tag(); + unsigned int count = baseLangSysRecords.len; + for (unsigned int i = 0; i < count; i++) + { + tag = baseLangSysRecords[i].get_tag (); // taking advantage of alphabetical order cmp = tag.cmp(baseLangSysTag); if (cmp == 0) return i; @@ -301,51 +301,50 @@ struct BaseScript { inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const { - if (baseLangSysIndex == NOT_INDEXED) { + if (baseLangSysIndex == NOT_INDEXED) + { if (unlikely(defaultMinMax)) return NOT_INDEXED; - return (this+defaultMinMax).get_feature_tag_index(featureTableTag); + return (this+defaultMinMax).get_feature_tag_index (featureTableTag); } - if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED; - return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag); + return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index (featureTableTag); } inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const { if (baseLangSysIndex == NOT_INDEXED) - return (this+defaultMinMax).get_min_value(featureTableTagIndex); - return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex); + return (this+defaultMinMax).get_min_value (featureTableTagIndex); + return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex); } inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const { if (baseLangSysIndex == NOT_INDEXED) - return (this+defaultMinMax).get_min_value(featureTableTagIndex); - return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex); + return (this+defaultMinMax).get_min_value (featureTableTagIndex); + return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex); } inline unsigned int get_default_base_tag_index (void) const - { return (this+baseValues).get_default_base_tag_index(); } + { return (this+baseValues).get_default_base_tag_index (); } inline int get_base_coord (unsigned int baselineTagIndex) const - { return (this+baseValues).get_base_coord(baselineTagIndex); } + { return (this+baseValues).get_base_coord (baselineTagIndex); } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - baseValues.sanitize (c, this) && - defaultMinMax.sanitize (c, this) && - baseLangSysRecords.sanitize (c, this)); + baseValues.sanitize (c, this) && + defaultMinMax.sanitize (c, this) && + baseLangSysRecords.sanitize (c, this)); } protected: - OffsetTo baseValues; - OffsetTo defaultMinMax; - HBUINT16 baseLangSysCount; - ArrayOf baseLangSysRecords; + OffsetTo baseValues; + OffsetTo defaultMinMax; + ArrayOf baseLangSysRecords; public: - DEFINE_SIZE_ARRAY (8, baseLangSysRecords); + DEFINE_SIZE_ARRAY (6, baseLangSysRecords); }; @@ -355,29 +354,28 @@ struct BaseScriptRecord { { return baseScriptTag; } inline unsigned int get_default_base_tag_index(void) const - { return (this+baseScript).get_default_base_tag_index(); } + { return (this+baseScript).get_default_base_tag_index (); } inline int get_base_coord(unsigned int baselineTagIndex) const - { return (this+baseScript).get_base_coord(baselineTagIndex); } + { return (this+baseScript).get_base_coord (baselineTagIndex); } inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const - { return (this+baseScript).get_lang_tag_index(baseLangSysTag); } + { return (this+baseScript).get_lang_tag_index (baseLangSysTag); } inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const - { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); } + { return (this+baseScript).get_feature_tag_index (baseLangSysIndex, featureTableTag); } inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); } + { return (this+baseScript).get_max_value (baseLangSysIndex, featureTableTagIndex); } inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); } + { return (this+baseScript).get_min_value (baseLangSysIndex, featureTableTagIndex); } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - baseScript != Null(OffsetTo) && - baseScript.sanitize (c, base)); + baseScript.sanitize (c, base)); } protected: @@ -392,7 +390,9 @@ struct BaseScriptList { inline unsigned int get_base_script_index (Tag baseScriptTag) const { - for (unsigned int i = 0; i < baseScriptCount; i++) + /* XXX bsearch? */ + unsigned int count = baseScriptRecords.len; + for (unsigned int i = 0; i < count; i++) if (baseScriptRecords[i].get_tag() == baseScriptTag) return i; return NOT_INDEXED; @@ -400,7 +400,6 @@ struct BaseScriptList { inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const { - if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED; return baseScriptRecords[baseScriptIndex].get_default_base_tag_index(); } @@ -411,13 +410,11 @@ struct BaseScriptList { inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const { - if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED; return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag); } inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const { - if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED; return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag); } @@ -435,24 +432,23 @@ struct BaseScriptList { { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - baseScriptRecords.sanitize (c, this)); + baseScriptRecords.sanitize (c, this)); } protected: - HBUINT16 baseScriptCount; - ArrayOf baseScriptRecords; + ArrayOf baseScriptRecords; public: - DEFINE_SIZE_ARRAY (4, baseScriptRecords); - + DEFINE_SIZE_ARRAY (2, baseScriptRecords); }; struct BaseTagList { - - inline unsigned int get_tag_index(Tag baselineTag) const + inline unsigned int get_tag_index (Tag baselineTag) const { - for (unsigned int i = 0; i < baseTagCount; i++) + /* TODO bsearch? */ + unsigned int count = baselineTags.len; + for (unsigned int i = 0; i < count; i++) if (baselineTags[i] == baselineTag) return i; return NOT_INDEXED; @@ -465,42 +461,37 @@ struct BaseTagList } protected: - HBUINT16 baseTagCount; SortedArrayOf baselineTags; public: - DEFINE_SIZE_ARRAY (4, baselineTags); + DEFINE_SIZE_ARRAY (2, baselineTags); }; struct Axis { - inline unsigned int get_base_tag_index(Tag baselineTag) const + inline unsigned int get_base_tag_index (Tag baselineTag) const { - if (unlikely(baseTagList == Null(OffsetTo))) return NOT_INDEXED; return (this+baseTagList).get_tag_index(baselineTag); } inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const { - if (unlikely(baseScriptList == Null(OffsetTo))) return NOT_INDEXED; return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex); } - inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + inline int get_base_coord (unsigned int baseScriptIndex, unsigned int baselineTagIndex) const { return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex); } inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const { - if (unlikely(baseScriptList == Null(OffsetTo))) return NOT_INDEXED; return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag); } inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const { - if (unlikely(baseScriptList == Null(OffsetTo))) return NOT_INDEXED; return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); } @@ -518,13 +509,13 @@ struct Axis { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - baseTagList.sanitize (c, this) && - baseScriptList.sanitize (c, this)); + baseTagList.sanitize (c, this) && + baseScriptList.sanitize (c, this)); } protected: - OffsetTo baseTagList; - OffsetTo baseScriptList; + OffsetTo baseTagList; + OffsetTo baseScriptList; public: DEFINE_SIZE_STATIC (4); @@ -534,96 +525,78 @@ struct BASE { static const hb_tag_t tableTag = HB_OT_TAG_BASE; - inline bool has_vert_axis(void) - { return vertAxis != Null(OffsetTo); } + inline bool has_v_axis(void) { return vAxis != 0; } - inline bool has_horiz_axis(void) - { return horizAxis != Null(OffsetTo); } + inline bool has_h_axis(void) { return hAxis != 0; } - // horizontal axis base coords: - - inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const + inline unsigned int get_h_base_tag_index (Tag baselineTag) const { - if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+horizAxis).get_base_tag_index(baselineTag); + return (this+hAxis).get_base_tag_index(baselineTag); } - inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const + inline unsigned int get_h_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const { - if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); + return (this+hAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); } - inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + inline int get_h_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const { - return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex); + return (this+hAxis).get_base_coord(baseScriptIndex, baselineTagIndex); } - // vertical axis base coords: - - inline unsigned int get_vert_base_tag_index(Tag baselineTag) const + inline unsigned int get_v_base_tag_index(Tag baselineTag) const { - if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+vertAxis).get_base_tag_index(baselineTag); + return (this+vAxis).get_base_tag_index(baselineTag); } - inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const + inline unsigned int get_v_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const { - if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); + return (this+vAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); } - inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + inline int get_v_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const { - return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex); + return (this+vAxis).get_base_coord(baseScriptIndex, baselineTagIndex); } - // horizontal axis min/max coords: - - inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const + inline unsigned int get_h_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const { - if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); + return (this+hAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); } - inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + inline unsigned int get_h_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const { - if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); + return (this+hAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); } - inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + inline int get_h_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const { - return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + return (this+hAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } - inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + inline int get_h_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const { - return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + return (this+hAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } - // vertical axis min/max coords: - - inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const + inline unsigned int get_v_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const { - if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); + return (this+vAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); } - inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + inline unsigned int get_v_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const { - if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); + return (this+vAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); } - inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + inline int get_v_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const { - return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + return (this+vAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } - inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + inline int get_v_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const { - return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + return (this+vAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -631,15 +604,15 @@ struct BASE TRACE_SANITIZE (this); return_trace (c->check_struct (this) && likely (version.major == 1) && - horizAxis.sanitize (c, this) && - vertAxis.sanitize (c, this) && + hAxis.sanitize (c, this) && + vAxis.sanitize (c, this) && (version.to_int () < 0x00010001u || varStore.sanitize (c, this))); } protected: FixedVersion<> version; - OffsetTo horizAxis; - OffsetTo vertAxis; + OffsetTo hAxis; + OffsetTo vAxis; LOffsetTo varStore; /* Offset to the table of Item Variation * Store--from beginning of BASE diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 2da6e315c..89d5eae49 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -173,7 +173,7 @@ struct RangeRecord public: DEFINE_SIZE_STATIC (6); }; -DEFINE_NULL_DATA (OT, RangeRecord, "\000\001"); +DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord); struct IndexArray : ArrayOf @@ -240,8 +240,7 @@ struct LangSys public: DEFINE_SIZE_ARRAY (6, featureIndex); }; -DEFINE_NULL_DATA (OT, LangSys, "\0\0\xFF\xFF"); - +DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys); struct Script { diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index 60a8d3adf..d2b41a8ef 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -349,6 +349,7 @@ struct GDEF ComponentGlyph = 4 }; + inline bool has_data (void) const { return version.to_int () != 0; } inline bool has_glyph_classes (void) const { return glyphClassDef != 0; } inline unsigned int get_glyph_class (hb_codepoint_t glyph) const { return (this+glyphClassDef).get_class (glyph); } diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index b52c0144f..fe34a328b 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1628,14 +1628,14 @@ GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) template /*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) { - const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); + const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->table.GPOS); const PosLookup &l = gpos.get_lookup (lookup_index); return l.dispatch (c); } /*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index) { - const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); + const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->table.GPOS); const PosLookup &l = gpos.get_lookup (lookup_index); unsigned int saved_lookup_props = c->lookup_props; unsigned int saved_lookup_index = c->lookup_index; diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index eef8dc546..1d5a02a02 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -1335,7 +1335,7 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) { _hb_buffer_assert_gsubgpos_vars (buffer); - const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef; + const GDEF &gdef = *hb_ot_layout_from_face (font->face)->table.GDEF; unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) { @@ -1359,14 +1359,14 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) template /*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) { - const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); + const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->table.GSUB); const SubstLookup &l = gsub.get_lookup (lookup_index); return l.dispatch (c); } /*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index) { - const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); + const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->table.GSUB); const SubstLookup &l = gsub.get_lookup (lookup_index); unsigned int saved_lookup_props = c->lookup_props; unsigned int saved_lookup_index = c->lookup_index; diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 747811e6a..40a2fc4cc 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -480,7 +480,7 @@ struct hb_ot_apply_context_t : iter_input (), iter_context (), font (font_), face (font->face), buffer (buffer_), recurse_func (nullptr), - gdef (*hb_ot_layout_from_face (face)->gdef), + gdef (*hb_ot_layout_from_face (face)->table.GDEF), var_store (gdef.get_var_store ()), direction (buffer_->props.direction), lookup_mask (1), @@ -2320,6 +2320,7 @@ struct Extension struct GSUBGPOS { + inline bool has_data (void) const { return version.to_int () != 0; } inline unsigned int get_script_count (void) const { return (this+scriptList).len; } inline const Tag& get_script_tag (unsigned int i) const diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index c88557239..2a74135c8 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -121,25 +121,6 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, * hb_ot_layout_t */ -namespace OT { - struct BASE; - struct COLR; - struct CPAL; - struct GDEF; - struct GSUB; - struct GPOS; - struct MATH; - struct fvar; - struct avar; -} - -namespace AAT { - struct ankr; - struct kerx; - struct morx; - struct trak; -} - struct hb_ot_layout_lookup_accelerator_t { template @@ -161,28 +142,73 @@ struct hb_ot_layout_lookup_accelerator_t hb_set_digest_t digest; }; +/* Most of these tables are NOT needed for shaping. But we need to hook them *somewhere*. + * This is as good as any place. */ +#define HB_OT_LAYOUT_TABLES \ + /* OpenType shaping. */ \ + HB_OT_LAYOUT_TABLE(OT, GDEF) \ + HB_OT_LAYOUT_TABLE(OT, GSUB) \ + HB_OT_LAYOUT_TABLE(OT, GPOS) \ + HB_OT_LAYOUT_TABLE(OT, JSTF) \ + HB_OT_LAYOUT_TABLE(OT, BASE) \ + /* AAT shaping. */ \ + HB_OT_LAYOUT_TABLE(AAT, morx) \ + HB_OT_LAYOUT_TABLE(AAT, kerx) \ + HB_OT_LAYOUT_TABLE(AAT, ankr) \ + HB_OT_LAYOUT_TABLE(AAT, trak) \ + /* OpenType variations. */ \ + HB_OT_LAYOUT_TABLE(OT, fvar) \ + HB_OT_LAYOUT_TABLE(OT, avar) \ + HB_OT_LAYOUT_TABLE(OT, MVAR) \ + /* OpenType color. */ \ + HB_OT_LAYOUT_TABLE(OT, COLR) \ + HB_OT_LAYOUT_TABLE(OT, CPAL) \ + HB_OT_LAYOUT_TABLE(OT, CBDT) \ + HB_OT_LAYOUT_TABLE(OT, CBLC) \ + HB_OT_LAYOUT_TABLE(OT, sbix) \ + HB_OT_LAYOUT_TABLE(OT, svg) \ + /* OpenType math. */ \ + HB_OT_LAYOUT_TABLE(OT, MATH) \ + /* OpenType fundamentals. */ \ + HB_OT_LAYOUT_TABLE(OT, post) \ + /* */ + +/* Declare tables. */ +#define HB_OT_LAYOUT_TABLE(Namespace, Type) namespace Namespace { struct Type; } +HB_OT_LAYOUT_TABLES +#undef HB_OT_LAYOUT_TABLE + struct hb_ot_layout_t { - hb_blob_t *gdef_blob; - hb_blob_t *gsub_blob; - hb_blob_t *gpos_blob; - - const struct OT::GDEF *gdef; - const struct OT::GSUB *gsub; - const struct OT::GPOS *gpos; - unsigned int gsub_lookup_count; unsigned int gpos_lookup_count; hb_ot_layout_lookup_accelerator_t *gsub_accels; hb_ot_layout_lookup_accelerator_t *gpos_accels; - /* TODO Move the following out of this struct. */ - hb_face_t *face; /* MUST be before the lazy loaders. */ - hb_table_lazy_loader_t<1, struct OT::MATH> math; - hb_table_lazy_loader_t<2, struct OT::fvar> fvar; - hb_table_lazy_loader_t<3, struct OT::avar> avar; - hb_table_lazy_loader_t<4, struct AAT::morx> morx; + /* Various non-shaping tables. */ + struct tables_t + { + HB_INTERNAL void init0 (hb_face_t *face); + HB_INTERNAL void fini (void); + +#define HB_OT_LAYOUT_TABLE_ORDER(Namespace, Type) \ + HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type))) + enum order_t + { + ORDER_ZERO, +#define HB_OT_LAYOUT_TABLE(Namespace, Type) \ + HB_OT_LAYOUT_TABLE_ORDER (Namespace, Type), + HB_OT_LAYOUT_TABLES +#undef HB_OT_LAYOUT_TABLE + }; + + hb_face_t *face; /* MUST be JUST before the lazy loaders. */ +#define HB_OT_LAYOUT_TABLE(Namespace, Type) \ + hb_table_lazy_loader_t Type; + HB_OT_LAYOUT_TABLES +#undef HB_OT_LAYOUT_TABLE + } table; }; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 8a9eae45f..09ff0e6c0 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -31,6 +31,7 @@ #include "hb-open-type-private.hh" #include "hb-ot-layout-private.hh" #include "hb-ot-map-private.hh" +#include "hb-map-private.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" @@ -44,9 +45,124 @@ #include "hb-ot-color-sbix-table.hh" #include "hb-ot-color-svg-table.hh" #include "hb-ot-name-table.hh" -#include "hb-map-private.hh" +static bool +_hb_ot_blacklist_gdef (unsigned int gdef_len, + unsigned int gsub_len, + unsigned int gpos_len) +{ + /* The ugly business of blacklisting individual fonts' tables happen here! + * See this thread for why we finally had to bend in and do this: + * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html + * + * In certain versions of Times New Roman Italic and Bold Italic, + * ASCII double quotation mark U+0022 has wrong glyph class 3 (mark) + * in GDEF. Many versions of Tahoma have bad GDEF tables that + * incorrectly classify some spacing marks such as certain IPA + * symbols as glyph class 3. So do older versions of Microsoft + * Himalaya, and the version of Cantarell shipped by Ubuntu 16.04. + * + * Nuke the GDEF tables of to avoid unwanted width-zeroing. + * + * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875 + */ +#define ENCODE(x,y,z) ((int64_t) (x) << 32 | (int64_t) (y) << 16 | (z)) + switch ENCODE(gdef_len, gsub_len, gpos_len) + { + /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */ + case ENCODE (442, 2874, 42038): + /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */ + case ENCODE (430, 2874, 40662): + /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */ + case ENCODE (442, 2874, 39116): + /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */ + case ENCODE (430, 2874, 39374): + /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */ + case ENCODE (490, 3046, 41638): + /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */ + case ENCODE (478, 3046, 41902): + /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */ + case ENCODE (898, 12554, 46470): + /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */ + case ENCODE (910, 12566, 47732): + /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */ + case ENCODE (928, 23298, 59332): + /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */ + case ENCODE (940, 23310, 60732): + /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + case ENCODE (964, 23836, 60072): + /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + case ENCODE (976, 23832, 61456): + /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */ + case ENCODE (994, 24474, 60336): + /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ + case ENCODE (1006, 24470, 61740): + /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + case ENCODE (1006, 24576, 61346): + /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + case ENCODE (1018, 24572, 62828): + /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */ + case ENCODE (1006, 24576, 61352): + /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */ + case ENCODE (1018, 24572, 62834): + /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ + case ENCODE (832, 7324, 47162): + /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ + case ENCODE (844, 7302, 45474): + /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */ + case ENCODE (180, 13054, 7254): + /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ + case ENCODE (192, 12638, 7254): + /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ + case ENCODE (192, 12690, 7254): + /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */ + /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */ + case ENCODE (188, 248, 3852): + /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ + /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ + case ENCODE (188, 264, 3426): + /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */ + case ENCODE (1058, 47032, 11818): + /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/ + case ENCODE (1046, 47030, 12600): + /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */ + case ENCODE (1058, 71796, 16770): + /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */ + case ENCODE (1046, 71790, 17862): + /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */ + case ENCODE (1046, 71788, 17112): + /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */ + case ENCODE (1058, 71794, 17514): + /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */ + case ENCODE (1330, 109904, 57938): + /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ + case ENCODE (1330, 109904, 58972): + /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf + * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */ + case ENCODE (1004, 59092, 14836): + return true; +#undef ENCODE + } + return false; +} + +void hb_ot_layout_t::tables_t::init0 (hb_face_t *face) +{ + this->face = face; +#define HB_OT_LAYOUT_TABLE(Namespace, Type) Type.init0 (); + HB_OT_LAYOUT_TABLES +#undef HB_OT_LAYOUT_TABLE +} +void hb_ot_layout_t::tables_t::fini (void) +{ +#define HB_OT_LAYOUT_TABLE(Namespace, Type) Type.fini (); + HB_OT_LAYOUT_TABLES +#undef HB_OT_LAYOUT_TABLE +} + hb_ot_layout_t * _hb_ot_layout_create (hb_face_t *face) { @@ -54,145 +170,33 @@ _hb_ot_layout_create (hb_face_t *face) if (unlikely (!layout)) return nullptr; - layout->gdef_blob = hb_sanitize_context_t ().reference_table (face); - layout->gdef = layout->gdef_blob->as (); + layout->table.init0 (face); - layout->gsub_blob = hb_sanitize_context_t ().reference_table (face); - layout->gsub = layout->gsub_blob->as (); + const OT::GSUB &gsub = *layout->table.GSUB; + const OT::GPOS &gpos = *layout->table.GPOS; - layout->gpos_blob = hb_sanitize_context_t ().reference_table (face); - layout->gpos = layout->gpos_blob->as (); + if (unlikely (_hb_ot_blacklist_gdef (layout->table.GDEF.get_blob ()->length, + layout->table.GSUB.get_blob ()->length, + layout->table.GPOS.get_blob ()->length))) + layout->table.GDEF.set_stored (hb_blob_get_empty ()); - layout->face = face; - layout->math.init (); - layout->fvar.init (); - layout->avar.init (); - layout->morx.init (); + unsigned int gsub_lookup_count = layout->gsub_lookup_count = gsub.get_lookup_count (); + unsigned int gpos_lookup_count = layout->gpos_lookup_count = gpos.get_lookup_count (); - { - /* - * The ugly business of blacklisting individual fonts' tables happen here! - * See this thread for why we finally had to bend in and do this: - * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html - */ - unsigned int gdef_len = layout->gdef_blob->length; - unsigned int gsub_len = layout->gsub_blob->length; - unsigned int gpos_len = layout->gpos_blob->length; - if (0 - /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */ - || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len) - /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */ - || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len) - /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */ - || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len) - /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */ - || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len) - /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */ - || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len) - /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */ - || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len) - ) - { - /* In certain versions of Times New Roman Italic and Bold Italic, - * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong - * glyph class 3 (mark) in GDEF. Nuke the GDEF to avoid zero-width - * double-quote. See: - * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html - */ - if (3 == layout->gdef->get_glyph_class (5)) - layout->gdef = &Null(OT::GDEF); - } - else if (0 - /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */ - || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len) - /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */ - || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len) - /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */ - || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len) - /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */ - || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len) - /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - || (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len) - /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - || (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len) - /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */ - || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len) - /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ - || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len) - /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - || (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len) - /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - || (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len) - /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */ - || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len) - /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */ - || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len) - /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ - || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len) - /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ - || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len) - /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */ - || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len) - /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ - || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len) - /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ - || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len) - /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */ - /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */ - || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len) - /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ - /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ - || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len) - /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */ - || (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len) - /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/ - || (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len) - /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */ - || (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len) - /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */ - || (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len) - /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */ - || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len) - /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */ - || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len) - /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */ - || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len) - /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ - || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len) - /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf - * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */ - || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len) - ) - { - /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks - * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya, - * and the version of Cantarell shipped by Ubuntu 16.04. - * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing. - * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 - * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693 - * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875 - */ - layout->gdef = &Null(OT::GDEF); - } - } + layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (gsub_lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t)); + layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (gpos_lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t)); - layout->gsub_lookup_count = layout->gsub->get_lookup_count (); - layout->gpos_lookup_count = layout->gpos->get_lookup_count (); - - layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t)); - layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t)); - - if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) || - (layout->gpos_lookup_count && !layout->gpos_accels))) + if (unlikely ((gsub_lookup_count && !layout->gsub_accels) || + (gpos_lookup_count && !layout->gpos_accels))) { _hb_ot_layout_destroy (layout); return nullptr; } - for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) - layout->gsub_accels[i].init (layout->gsub->get_lookup (i)); - for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) - layout->gpos_accels[i].init (layout->gpos->get_lookup (i)); + for (unsigned int i = 0; i < gsub_lookup_count; i++) + layout->gsub_accels[i].init (gsub.get_lookup (i)); + for (unsigned int i = 0; i < gpos_lookup_count; i++) + layout->gpos_accels[i].init (gpos.get_lookup (i)); return layout; } @@ -210,14 +214,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) free (layout->gsub_accels); free (layout->gpos_accels); - hb_blob_destroy (layout->gdef_blob); - hb_blob_destroy (layout->gsub_blob); - hb_blob_destroy (layout->gpos_blob); - - layout->math.fini (); - layout->fvar.fini (); - layout->avar.fini (); - layout->morx.fini (); + layout->table.fini (); free (layout); } @@ -234,19 +231,19 @@ static inline const OT::GDEF& _get_gdef (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF); - return *hb_ot_layout_from_face (face)->gdef; + return *hb_ot_layout_from_face (face)->table.GDEF; } static inline const OT::GSUB& _get_gsub (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GSUB); - return *hb_ot_layout_from_face (face)->gsub; + return *hb_ot_layout_from_face (face)->table.GSUB; } static inline const OT::GPOS& _get_gpos (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GPOS); - return *hb_ot_layout_from_face (face)->gpos; + return *hb_ot_layout_from_face (face)->table.GPOS; } /* @@ -854,13 +851,13 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, { case HB_OT_TAG_GSUB: { - const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); + const OT::SubstLookup& l = hb_ot_layout_from_face (face)->table.GSUB->get_lookup (lookup_index); l.collect_glyphs (&c); return; } case HB_OT_TAG_GPOS: { - const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index); + const OT::PosLookup& l = hb_ot_layout_from_face (face)->table.GPOS->get_lookup (lookup_index); l.collect_glyphs (&c); return; } @@ -907,7 +904,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, hb_bool_t hb_ot_layout_has_substitution (hb_face_t *face) { - return &_get_gsub (face) != &Null(OT::GSUB); + return _get_gsub (face).has_data (); } /** @@ -936,7 +933,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face, if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false; OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context); - const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); + const OT::SubstLookup& l = hb_ot_layout_from_face (face)->table.GSUB->get_lookup (lookup_index); return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]); } @@ -1009,7 +1006,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, hb_bool_t hb_ot_layout_has_positioning (hb_face_t *face) { - return &_get_gpos (face) != &Null(OT::GPOS); + return _get_gpos (face).has_data (); } void @@ -1094,7 +1091,7 @@ struct GSUBProxy typedef OT::SubstLookup Lookup; GSUBProxy (hb_face_t *face) : - table (*hb_ot_layout_from_face (face)->gsub), + table (*hb_ot_layout_from_face (face)->table.GSUB), accels (hb_ot_layout_from_face (face)->gsub_accels) {} const OT::GSUB &table; @@ -1108,7 +1105,7 @@ struct GPOSProxy typedef OT::PosLookup Lookup; GPOSProxy (hb_face_t *face) : - table (*hb_ot_layout_from_face (face)->gpos), + table (*hb_ot_layout_from_face (face)->table.GPOS), accels (hb_ot_layout_from_face (face)->gpos_accels) {} const OT::GPOS &table; @@ -1344,5 +1341,5 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, // hb_bool_t // hb_ot_base_has_data (hb_face_t *face) // { -// return &_get_base (face) != &Null(OT::BASE); +// return _get_base (face).has_data (); // } diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh index 5fef2d28f..2dd714580 100644 --- a/src/hb-ot-math-table.hh +++ b/src/hb-ot-math-table.hh @@ -686,6 +686,8 @@ struct MATH { static const hb_tag_t tableTag = HB_OT_TAG_MATH; + inline bool has_data (void) const { return version.to_int () != 0; } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index 1667a7da8..66ce207a7 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -34,7 +34,7 @@ _get_math (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::MATH); hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - return *(layout->math.get ()); + return *(layout->table.MATH.get ()); } /* @@ -55,7 +55,7 @@ _get_math (hb_face_t *face) hb_bool_t hb_ot_math_has_data (hb_face_t *face) { - return &_get_math (face) != &Null(OT::MATH); + return _get_math (face).has_data (); } /** diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh index 40c5015c9..a55511aa0 100644 --- a/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/src/hb-ot-shape-complex-arabic-fallback.hh @@ -205,8 +205,6 @@ struct arabic_fallback_plan_t hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS]; }; -static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; - #if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256) #define HB_WITH_WIN1256 #endif @@ -215,7 +213,8 @@ static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; #include "hb-ot-shape-complex-arabic-win1256.hh" #endif -struct ManifestLookup { +struct ManifestLookup +{ OT::Tag tag; OT::OffsetTo lookupOffset; }; @@ -299,7 +298,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan, { arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t)); if (unlikely (!fallback_plan)) - return const_cast (&arabic_fallback_plan_nil); + return const_cast (&Null(arabic_fallback_plan_t)); fallback_plan->num_lookups = 0; fallback_plan->free_lookups = false; @@ -314,14 +313,15 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan, if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font)) return fallback_plan; + assert (fallback_plan->num_lookups == 0); free (fallback_plan); - return const_cast (&arabic_fallback_plan_nil); + return const_cast (&Null(arabic_fallback_plan_t)); } static void arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan) { - if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil) + if (!fallback_plan || fallback_plan->num_lookups == 0) return; for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index d7f4afeab..71632b563 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -680,8 +680,8 @@ hb_ot_position_default (hb_ot_shape_context_t *c) if (HB_DIRECTION_IS_HORIZONTAL (direction)) { - for (unsigned int i = 0; i < count; i++) - pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint); + c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]), + &pos[0].x_advance, sizeof(pos[0])); /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ if (c->font->has_glyph_h_origin_func ()) for (unsigned int i = 0; i < count; i++) @@ -691,9 +691,10 @@ hb_ot_position_default (hb_ot_shape_context_t *c) } else { + c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]), + &pos[0].y_advance, sizeof(pos[0])); for (unsigned int i = 0; i < count; i++) { - pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint); c->font->subtract_glyph_v_origin (info[i].codepoint, &pos[i].x_offset, &pos[i].y_offset); diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh index 82d299685..101476ed3 100644 --- a/src/hb-ot-var-fvar-table.hh +++ b/src/hb-ot-var-fvar-table.hh @@ -87,6 +87,8 @@ struct fvar { static const hb_tag_t tableTag = HB_OT_TAG_fvar; + inline bool has_data (void) const { return version.to_int () != 0; } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index f0612a611..6081ddfc3 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -41,14 +41,14 @@ _get_fvar (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::fvar); hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - return *(layout->fvar.get ()); + return *(layout->table.fvar.get ()); } static inline const OT::avar& _get_avar (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::avar); hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - return *(layout->avar.get ()); + return *(layout->table.avar.get ()); } /** @@ -65,7 +65,7 @@ _get_avar (hb_face_t *face) hb_bool_t hb_ot_var_has_data (hb_face_t *face) { - return &_get_fvar (face) != &Null(OT::fvar); + return _get_fvar (face).has_data (); } /** diff --git a/src/hb-private.hh b/src/hb-private.hh index 13d24267a..1bc996edb 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -86,7 +86,7 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size); /* * Compiler attributes - * */ + */ #if __cplusplus < 201103L @@ -98,7 +98,6 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size); #define constexpr const #endif -// Static assertions #ifndef static_assert #define static_assert(e, msg) \ HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1] @@ -124,7 +123,7 @@ struct _hb_alignof }; #ifndef alignof #define alignof(x) (_hb_alignof::value) -#endif // alignof +#endif #endif // __cplusplus < 201103L @@ -286,13 +285,12 @@ static int errno = 0; /* Use something better? */ #define HB_STMT_START do #define HB_STMT_END while (0) +/* Static-assert as expression. */ template class hb_assert_constant_t; template <> class hb_assert_constant_t<1> {}; - #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>)) /* Lets assert int types. Saves trouble down the road. */ - static_assert ((sizeof (int8_t) == 1), ""); static_assert ((sizeof (uint8_t) == 1), ""); static_assert ((sizeof (int16_t) == 2), ""); @@ -301,7 +299,6 @@ static_assert ((sizeof (int32_t) == 4), ""); static_assert ((sizeof (uint32_t) == 4), ""); static_assert ((sizeof (int64_t) == 8), ""); static_assert ((sizeof (uint64_t) == 8), ""); - static_assert ((sizeof (hb_codepoint_t) == 4), ""); static_assert ((sizeof (hb_position_t) == 4), ""); static_assert ((sizeof (hb_mask_t) == 4), ""); @@ -371,82 +368,6 @@ typedef uint64_t hb_vector_size_impl_t; #endif -/* - * Static pools - */ - -/* Global nul-content Null pool. Enlarge as necessary. */ - -#define HB_NULL_POOL_SIZE 800 - -extern HB_INTERNAL -hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)]; - -/* Generic nul-content Null objects. */ -template -static inline Type const & Null (void) { - static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); - return *reinterpret_cast (_hb_NullPool); -} -#define Null(Type) Null() - -/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ -#define DEFINE_NULL_DATA(Namespace, Type, data) \ -} /* Close namespace. */ \ -static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \ -template <> \ -/*static*/ inline const Namespace::Type& Null (void) { \ - return *reinterpret_cast (_Null##Type); \ -} \ -namespace Namespace { \ -/* The following line really exists such that we end in a place needing semicolon */ \ -static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.") - - -/* Global writable pool. Enlarge as necessary. */ - -/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool - * for correct operation. It only exist to catch and divert program logic bugs instead of - * causing bad memory access. So, races there are not actually introducing incorrectness - * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */ -extern HB_INTERNAL -/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)]; - -/* CRAP pool: Common Region for Access Protection. */ -template -static inline Type& Crap (void) { - static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); - Type *obj = reinterpret_cast (_hb_CrapPool); - *obj = Null(Type); - return *obj; -} -#define Crap(Type) Crap() - -template -struct CrapOrNull { - static inline Type & get (void) { return Crap(Type); } -}; -template -struct CrapOrNull { - static inline Type const & get (void) { return Null(Type); } -}; -#define CrapOrNull(Type) CrapOrNull::get () - - -/* ASCII tag/character handling */ - -static inline bool ISALPHA (unsigned char c) -{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } -static inline bool ISALNUM (unsigned char c) -{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); } -static inline bool ISSPACE (unsigned char c) -{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; } -static inline unsigned char TOUPPER (unsigned char c) -{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; } -static inline unsigned char TOLOWER (unsigned char c) -{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; } - - /* HB_NDEBUG disables some sanity checks that are very safe to disable and * should be disabled in production systems. If NDEBUG is defined, enable * HB_NDEBUG; but if it's desirable that normal assert()s (which are very @@ -457,41 +378,7 @@ static inline unsigned char TOLOWER (unsigned char c) #endif -/* Misc */ - -template class hb_assert_unsigned_t; -template <> class hb_assert_unsigned_t {}; -template <> class hb_assert_unsigned_t {}; -template <> class hb_assert_unsigned_t {}; -template <> class hb_assert_unsigned_t {}; - -template static inline bool -hb_in_range (T u, T lo, T hi) -{ - /* The sizeof() is here to force template instantiation. - * I'm sure there are better ways to do this but can't think of - * one right now. Declaring a variable won't work as HB_UNUSED - * is unusable on some platforms and unused types are less likely - * to generate a warning than unused variables. */ - static_assert ((sizeof (hb_assert_unsigned_t) >= 0), ""); - - /* The casts below are important as if T is smaller than int, - * the subtract results will become a signed int! */ - return (T)(u - lo) <= (T)(hi - lo); -} - -template static inline bool -hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2) -{ - return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2); -} - -template static inline bool -hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) -{ - return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3); -} - +/* Flags */ /* Enable bitwise ops on enums marked as flags_t */ /* To my surprise, looks like the function resolver is happy to silently cast @@ -515,7 +402,6 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \ } - /* Useful for set-operations on small enums. * For example, for testing "x ∈ {x1, x2, x3}" use: * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) @@ -575,6 +461,7 @@ _hb_memalign(void **memptr, size_t alignment, size_t size) #include "hb-debug.hh" #include "hb-dsalgs.hh" #include "hb-mutex-private.hh" +#include "hb-null.hh" #include "hb-object-private.hh" #endif /* HB_PRIVATE_HH */ diff --git a/src/hb-shape-plan-private.hh b/src/hb-shape-plan-private.hh index c2c4987e5..7d020ff16 100644 --- a/src/hb-shape-plan-private.hh +++ b/src/hb-shape-plan-private.hh @@ -51,6 +51,7 @@ struct hb_shape_plan_t struct hb_shaper_data_t shaper_data; }; +DECLARE_NULL_INSTANCE (hb_shape_plan_t); #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \ , const hb_feature_t *user_features \ diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index 37ff1a6e6..cc1834c47 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -88,6 +88,31 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, * hb_shape_plan_t */ +DEFINE_NULL_INSTANCE (hb_shape_plan_t) = +{ + HB_OBJECT_HEADER_STATIC, + + true, /* default_shaper_list */ + nullptr, /* face */ + HB_SEGMENT_PROPERTIES_DEFAULT, /* props */ + + nullptr, /* shaper_func */ + nullptr, /* shaper_name */ + + nullptr, /* user_features */ + 0, /* num_user_featurs */ + + nullptr, /* coords */ + 0, /* num_coords */ + + { +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT + } +}; + + /** * hb_shape_plan_create: (Xconstructor) * @face: @@ -188,30 +213,7 @@ hb_shape_plan_create2 (hb_face_t *face, hb_shape_plan_t * hb_shape_plan_get_empty (void) { - static const hb_shape_plan_t _hb_shape_plan_nil = { - HB_OBJECT_HEADER_STATIC, - - true, /* default_shaper_list */ - nullptr, /* face */ - HB_SEGMENT_PROPERTIES_DEFAULT, /* props */ - - nullptr, /* shaper_func */ - nullptr, /* shaper_name */ - - nullptr, /* user_features */ - 0, /* num_user_featurs */ - - nullptr, /* coords */ - 0, /* num_coords */ - - { -#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - } - }; - - return const_cast (&_hb_shape_plan_nil); + return const_cast (&Null(hb_shape_plan_t)); } /** diff --git a/src/hb-static.cc b/src/hb-static.cc index bd0943f53..ddecbba11 100644 --- a/src/hb-static.cc +++ b/src/hb-static.cc @@ -25,8 +25,11 @@ */ #include "hb-private.hh" -#include "hb-face-private.hh" + #include "hb-open-type-private.hh" +#include "hb-ot-layout-common-private.hh" + +#include "hb-face-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" @@ -35,6 +38,11 @@ hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; /*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; +DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF}; +DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00}; +DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00}; + + void hb_face_t::load_num_glyphs (void) const { diff --git a/src/hb-subset.cc b/src/hb-subset.cc index e39ee1eda..3a421ff06 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -84,7 +84,7 @@ _subset (hb_subset_plan_t *plan) hb_tag_t tag = TableType::tableTag; hb_bool_t result = false; - if (table != &Null(TableType)) + if (source_blob->data) { result = table->subset(plan); } else { diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh index b2c203d26..fb16ba437 100644 --- a/src/hb-unicode-private.hh +++ b/src/hb-unicode-private.hh @@ -60,7 +60,8 @@ extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256]; HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \ /* ^--- Add new simple callbacks here */ -struct hb_unicode_funcs_t { +struct hb_unicode_funcs_t +{ hb_object_header_t header; ASSERT_POD (); @@ -263,9 +264,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE #undef HB_UNICODE_FUNC_IMPLEMENT } destroy; }; - - -extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil; +DECLARE_NULL_INSTANCE (hb_unicode_funcs_t); /* Modified combining marks */ diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index 2d16c2e3a..8cb417233 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -185,7 +185,8 @@ hb_unicode_funcs_create (hb_unicode_funcs_t *parent) } -const hb_unicode_funcs_t _hb_unicode_funcs_nil = { +DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) = +{ HB_OBJECT_HEADER_STATIC, nullptr, /* parent */ @@ -209,7 +210,7 @@ const hb_unicode_funcs_t _hb_unicode_funcs_nil = { hb_unicode_funcs_t * hb_unicode_funcs_get_empty (void) { - return const_cast (&_hb_unicode_funcs_nil); + return const_cast (&Null(hb_unicode_funcs_t)); } /** diff --git a/src/hb-vector-private.hh b/src/hb-vector-private.hh new file mode 100644 index 000000000..1ef20d438 --- /dev/null +++ b/src/hb-vector-private.hh @@ -0,0 +1,238 @@ +/* + * Copyright © 2017,2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_VECTOR_PRIVATE_HH +#define HB_VECTOR_PRIVATE_HH + +#include "hb-private.hh" + + +template +struct hb_vector_t +{ + unsigned int len; + unsigned int allocated; /* == 0 means allocation failed. */ + Type *arrayZ; + Type static_array[StaticSize]; + + void init (void) + { + len = 0; + allocated = ARRAY_LENGTH (static_array); + arrayZ = static_array; + } + + inline Type& operator [] (unsigned int i) + { + if (unlikely (i >= len)) + return Crap (Type); + return arrayZ[i]; + } + inline const Type& operator [] (unsigned int i) const + { + if (unlikely (i >= len)) + return Null(Type); + return arrayZ[i]; + } + + inline Type *push (void) + { + if (unlikely (!resize (len + 1))) + return &Crap(Type); + return &arrayZ[len - 1]; + } + inline Type *push (const Type& v) + { + Type *p = push (); + *p = v; + return p; + } + + /* Allocate for size but don't adjust len. */ + inline bool alloc (unsigned int size) + { + if (unlikely (!allocated)) + return false; + + if (likely (size <= allocated)) + return true; + + /* Reallocate */ + + unsigned int new_allocated = allocated; + while (size >= new_allocated) + new_allocated += (new_allocated >> 1) + 8; + + Type *new_array = nullptr; + + if (arrayZ == static_array) + { + new_array = (Type *) calloc (new_allocated, sizeof (Type)); + if (new_array) + memcpy (new_array, arrayZ, len * sizeof (Type)); + } + else + { + bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type)); + if (likely (!overflows)) + new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type)); + } + + if (unlikely (!new_array)) + { + allocated = 0; + return false; + } + + arrayZ = new_array; + allocated = new_allocated; + + return true; + } + + inline bool resize (int size_) + { + unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; + if (!alloc (size)) + return false; + + if (size > len) + memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ)); + + len = size; + return true; + } + + inline void pop (void) + { + if (!len) return; + len--; + } + + inline void remove (unsigned int i) + { + if (unlikely (i >= len)) + return; + memmove (static_cast (&arrayZ[i]), + static_cast (&arrayZ[i + 1]), + (len - i - 1) * sizeof (Type)); + len--; + } + + inline void shrink (int size_) + { + unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; + if (size < len) + len = size; + } + + template + inline Type *find (T v) { + for (unsigned int i = 0; i < len; i++) + if (arrayZ[i] == v) + return &arrayZ[i]; + return nullptr; + } + template + inline const Type *find (T v) const { + for (unsigned int i = 0; i < len; i++) + if (arrayZ[i] == v) + return &arrayZ[i]; + return nullptr; + } + + inline void qsort (int (*cmp)(const void*, const void*)) + { + ::qsort (arrayZ, len, sizeof (Type), cmp); + } + + inline void qsort (void) + { + ::qsort (arrayZ, len, sizeof (Type), Type::cmp); + } + + inline void qsort (unsigned int start, unsigned int end) + { + ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp); + } + + template + inline Type *lsearch (const T &x) + { + for (unsigned int i = 0; i < len; i++) + if (0 == this->arrayZ[i].cmp (&x)) + return &arrayZ[i]; + return nullptr; + } + + template + inline Type *bsearch (const T &x) + { + unsigned int i; + return bfind (x, &i) ? &arrayZ[i] : nullptr; + } + template + inline const Type *bsearch (const T &x) const + { + unsigned int i; + return bfind (x, &i) ? &arrayZ[i] : nullptr; + } + template + inline bool bfind (const T &x, unsigned int *i) const + { + int min = 0, max = (int) this->len - 1; + while (min <= max) + { + int mid = (min + max) / 2; + int c = this->arrayZ[mid].cmp (&x); + if (c < 0) + max = mid - 1; + else if (c > 0) + min = mid + 1; + else + { + *i = mid; + return true; + } + } + if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0)) + max++; + *i = max; + return false; + } + + inline void fini (void) + { + if (arrayZ != static_array) + free (arrayZ); + arrayZ = nullptr; + allocated = len = 0; + } +}; + + +#endif /* HB_VECTOR_PRIVATE_HH */ diff --git a/src/main.cc b/src/main.cc index c6e05fc37..98a1320bf 100644 --- a/src/main.cc +++ b/src/main.cc @@ -53,7 +53,7 @@ main (int argc, char **argv) hb_blob_t *font_blob = hb_sanitize_context_t().sanitize_blob (blob); const OpenTypeFontFile* sanitized = font_blob->as (); - if (sanitized == &Null(OpenTypeFontFile)) + if (!font_blob->data) { printf ("Sanitization of the file wasn't successful. Exit"); return 1;