diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py index c4e75aa96..b7f6be223 100755 --- a/src/gen-vowel-constraints.py +++ b/src/gen-vowel-constraints.py @@ -211,9 +211,7 @@ print (' }') print (' if (processed)') print (' {') print (' if (buffer->idx < count)') -print (' buffer->next_glyph ();') -print (' if (likely (buffer->successful))') -print (' buffer->swap_buffers ();') +print (' buffer->next_glyph ();') print (' }') print ('}') diff --git a/src/hb-aat-layout-ankr-table.hh b/src/hb-aat-layout-ankr-table.hh index 5f7656d2a..b793245a0 100644 --- a/src/hb-aat-layout-ankr-table.hh +++ b/src/hb-aat-layout-ankr-table.hh @@ -36,6 +36,8 @@ namespace AAT { +using namespace OT; + struct Anchor { diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 51add2213..ee2136ed9 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -671,8 +671,7 @@ struct StateTableDriver { for (; buffer->successful && buffer->idx < buffer->len;) buffer->next_glyph (); - if (likely (buffer->successful)) - buffer->swap_buffers (); + buffer->swap_buffers (); } } @@ -699,36 +698,23 @@ struct hb_aat_apply_context_t : hb_face_t *face; hb_buffer_t *buffer; hb_sanitize_context_t sanitizer; - const ankr &ankr_table; + const ankr *ankr_table; const char *ankr_end; /* Unused. For debug tracing only. */ unsigned int lookup_index; unsigned int debug_depth; - inline hb_aat_apply_context_t (hb_ot_shape_plan_t *plan_, - hb_font_t *font_, - hb_buffer_t *buffer_, - hb_blob_t *blob = const_cast (&Null(hb_blob_t)), - const ankr &ankr_table_ = Null(ankr), - const char *ankr_end_ = nullptr) : - plan (plan_), font (font_), face (font->face), buffer (buffer_), - sanitizer (), - ankr_table (ankr_table_), ankr_end (ankr_end_), - lookup_index (0), debug_depth (0) - { - sanitizer.init (blob); - sanitizer.set_num_glyphs (face->get_num_glyphs ()); - sanitizer.start_processing (); - sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX); - } + HB_INTERNAL hb_aat_apply_context_t (hb_ot_shape_plan_t *plan_, + hb_font_t *font_, + hb_buffer_t *buffer_, + hb_blob_t *blob = const_cast (&Null(hb_blob_t))); + + HB_INTERNAL ~hb_aat_apply_context_t (void); + + HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_, const char *ankr_end_); inline void set_lookup_index (unsigned int i) { lookup_index = i; } - - inline ~hb_aat_apply_context_t (void) - { - sanitizer.end_processing (); - } }; diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 94e0a9b62..d2242c549 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -207,11 +207,18 @@ struct KerxSubTableFormat1 int v = *actions++; if (idx < buffer->len && buffer->info[idx].mask & kern_mask) { - /* XXX Non-forward direction... */ if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) + { buffer->pos[idx].x_advance += c->font->em_scale_x (v); + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + buffer->pos[idx].x_offset += c->font->em_scale_x (v); + } else + { buffer->pos[idx].y_advance += c->font->em_scale_y (v); + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + buffer->pos[idx].y_offset += c->font->em_scale_y (v); + } } } depth = 0; @@ -255,7 +262,7 @@ struct KerxSubTableFormat1 protected: KerxSubTableHeader header; - StateTable machine; + StateTable machine; LOffsetTo, false> kernAction; public: DEFINE_SIZE_STATIC (32); @@ -416,14 +423,14 @@ struct KerxSubTableFormat4 return false; unsigned int markAnchorPoint = *data++; unsigned int currAnchorPoint = *data++; - const Anchor markAnchor = c->ankr_table.get_anchor (c->buffer->info[mark].codepoint, - markAnchorPoint, - c->sanitizer.get_num_glyphs (), - c->ankr_end); - const Anchor currAnchor = c->ankr_table.get_anchor (c->buffer->cur ().codepoint, - currAnchorPoint, - c->sanitizer.get_num_glyphs (), - c->ankr_end); + const Anchor markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint, + markAnchorPoint, + c->sanitizer.get_num_glyphs (), + c->ankr_end); + const Anchor currAnchor = c->ankr_table->get_anchor (c->buffer->cur ().codepoint, + currAnchorPoint, + c->sanitizer.get_num_glyphs (), + c->ankr_end); o.x_offset = c->font->em_scale_x (markAnchor.xCoordinate) - c->font->em_scale_x (currAnchor.xCoordinate); o.y_offset = c->font->em_scale_y (markAnchor.yCoordinate) - c->font->em_scale_y (currAnchor.yCoordinate); diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index d56af7bfe..2bc60182e 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -977,7 +977,7 @@ struct Chain inline void apply (hb_aat_apply_context_t *c, hb_mask_t flags) const { - const ChainSubtable *subtable = &StructAtOffset > (&featureZ, featureZ[0].static_size * featureCount); + const ChainSubtable *subtable = &StructAfter > (featureZ.as_array (featureCount)); unsigned int count = subtableCount; for (unsigned int i = 0; i < count; i++) { @@ -1059,7 +1059,7 @@ struct Chain if (!c->check_array (featureZ.arrayZ, featureCount)) return_trace (false); - const ChainSubtable *subtable = &StructAtOffset > (&featureZ, featureZ[0].static_size * featureCount); + const ChainSubtable *subtable = &StructAfter > (featureZ.as_array (featureCount)); unsigned int count = subtableCount; for (unsigned int i = 0; i < count; i++) { @@ -1121,8 +1121,7 @@ struct mortmorx else buffer->next_glyph (); } - if (likely (buffer->successful)) - buffer->swap_buffers (); + buffer->swap_buffers (); } inline void apply (hb_aat_apply_context_t *c) const diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index de2071ad6..c579c1193 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -55,7 +55,7 @@ struct TrackTableEntry unsigned int index, unsigned int nSizes) const { - return hb_array (base+valuesZ, nSizes)[index]; + return (base+valuesZ).as_array (nSizes)[index]; } public: diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index d917c29c6..80bf2d766 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -130,6 +130,44 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag) } +/* + * hb_aat_apply_context_t + */ + +AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (hb_ot_shape_plan_t *plan_, + hb_font_t *font_, + hb_buffer_t *buffer_, + hb_blob_t *blob) : + plan (plan_), + font (font_), + face (font->face), + buffer (buffer_), + sanitizer (), + ankr_table (&Null(AAT::ankr)), + ankr_end (nullptr), + lookup_index (0), + debug_depth (0) +{ + sanitizer.init (blob); + sanitizer.set_num_glyphs (face->get_num_glyphs ()); + sanitizer.start_processing (); + sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX); +} + +AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t (void) +{ + sanitizer.end_processing (); +} + +void +AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_, + const char *ankr_end_) +{ + ankr_table = ankr_table_; + ankr_end = ankr_end_; +} + + /* * mort/morx/kerx/trak */ @@ -273,8 +311,8 @@ hb_aat_layout_position (hb_ot_shape_plan_t *plan, hb_blob_t *ankr_blob; const AAT::ankr& ankr = _get_ankr (font->face, &ankr_blob); - AAT::hb_aat_apply_context_t c (plan, font, buffer, blob, - ankr, ankr_blob->data + ankr_blob->length); + AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); + c.set_ankr_table (&ankr, ankr_blob->data + ankr_blob->length); kerx.apply (&c); } diff --git a/src/hb-blob.cc b/src/hb-blob.cc index 51f22ce4d..9271200b1 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -57,8 +57,6 @@ DEFINE_NULL_INSTANCE (hb_blob_t) = { HB_OBJECT_HEADER_STATIC, - true, /* immutable */ - nullptr, /* data */ 0, /* length */ HB_MEMORY_MODE_READONLY, /* mode */ @@ -151,7 +149,7 @@ hb_blob_create_sub_blob (hb_blob_t *parent, { hb_blob_t *blob; - if (!length || offset >= parent->length) + if (!length || !parent || offset >= parent->length) return hb_blob_get_empty (); hb_blob_make_immutable (parent); @@ -299,12 +297,10 @@ hb_blob_get_user_data (hb_blob_t *blob, void hb_blob_make_immutable (hb_blob_t *blob) { - if (hb_object_is_inert (blob)) - return; - if (blob->immutable) + if (hb_object_is_immutable (blob)) return; - blob->immutable = true; + hb_object_make_immutable (blob); } /** @@ -320,7 +316,7 @@ hb_blob_make_immutable (hb_blob_t *blob) hb_bool_t hb_blob_is_immutable (hb_blob_t *blob) { - return blob->immutable; + return hb_object_is_immutable (blob); } @@ -454,7 +450,7 @@ hb_blob_t::try_make_writable_inplace (void) bool hb_blob_t::try_make_writable (void) { - if (this->immutable) + if (hb_object_is_immutable (this)) return false; if (this->mode == HB_MEMORY_MODE_WRITABLE) diff --git a/src/hb-blob.hh b/src/hb-blob.hh index 0181e94a4..1f7499fbf 100644 --- a/src/hb-blob.hh +++ b/src/hb-blob.hh @@ -70,8 +70,6 @@ struct hb_blob_t public: hb_object_header_t header; - bool immutable; - const char *data; unsigned int length; hb_memory_mode_t mode; diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 5a8152ed4..1a5547b35 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -217,7 +217,7 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size) void hb_buffer_t::reset (void) { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; hb_unicode_funcs_destroy (unicode); @@ -232,7 +232,7 @@ hb_buffer_t::reset (void) void hb_buffer_t::clear (void) { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; @@ -289,7 +289,7 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info) void hb_buffer_t::remove_output (void) { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; have_output = false; @@ -302,7 +302,7 @@ hb_buffer_t::remove_output (void) void hb_buffer_t::clear_output (void) { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; have_output = true; @@ -315,7 +315,7 @@ hb_buffer_t::clear_output (void) void hb_buffer_t::clear_positions (void) { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; have_output = false; @@ -873,7 +873,7 @@ void hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, hb_unicode_funcs_t *unicode_funcs) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; if (!unicode_funcs) @@ -920,7 +920,7 @@ hb_buffer_set_direction (hb_buffer_t *buffer, hb_direction_t direction) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->props.direction = direction; @@ -964,7 +964,7 @@ void hb_buffer_set_script (hb_buffer_t *buffer, hb_script_t script) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->props.script = script; @@ -1008,7 +1008,7 @@ void hb_buffer_set_language (hb_buffer_t *buffer, hb_language_t language) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->props.language = language; @@ -1046,7 +1046,7 @@ void hb_buffer_set_segment_properties (hb_buffer_t *buffer, const hb_segment_properties_t *props) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->props = *props; @@ -1082,7 +1082,7 @@ void hb_buffer_set_flags (hb_buffer_t *buffer, hb_buffer_flags_t flags) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->flags = flags; @@ -1118,7 +1118,7 @@ void hb_buffer_set_cluster_level (hb_buffer_t *buffer, hb_buffer_cluster_level_t cluster_level) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->cluster_level = cluster_level; @@ -1157,7 +1157,7 @@ void hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, hb_codepoint_t replacement) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->replacement = replacement; @@ -1197,7 +1197,7 @@ void hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, hb_codepoint_t invisible) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->invisible = invisible; @@ -1329,7 +1329,7 @@ hb_bool_t hb_buffer_set_length (hb_buffer_t *buffer, unsigned int length) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return length == 0; if (!buffer->ensure (length)) @@ -1535,7 +1535,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer, assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; if (text_length == -1) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 184db4944..893a8761d 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -353,7 +353,7 @@ hb_coretext_font_create (CTFontRef ct_font) hb_font_t *font = hb_font_create (face); hb_face_destroy (face); - if (unlikely (hb_object_is_inert (font))) + if (unlikely (hb_object_is_immutable (font))) return font; hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font))); diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index 59df860df..f2bff063d 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -539,19 +539,27 @@ struct hb_bytes_t unsigned int len; }; -template +template struct hb_array_t { inline hb_array_t (void) : arrayZ (nullptr), len (0) {} - inline hb_array_t (T *array_, unsigned int len_) : arrayZ (array_), len (len_) {} + inline hb_array_t (Type *array_, unsigned int len_) : arrayZ (array_), len (len_) {} - inline T& operator [] (unsigned int i) const + inline Type& operator [] (unsigned int i) const { - if (unlikely (i >= len)) return Null(T); + if (unlikely (i >= len)) return Null(Type); return arrayZ[i]; } - inline hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const + inline unsigned int get_size (void) const { return len * sizeof (Type); } + + template inline operator T * (void) { return arrayZ; } + template inline operator const T * (void) const { return arrayZ; } + + inline Type * operator & (void) { return arrayZ; } + inline const Type * operator & (void) const { return arrayZ; } + + inline hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const { unsigned int count = len; if (unlikely (start_offset > count)) @@ -559,21 +567,19 @@ struct hb_array_t else count -= start_offset; count = MIN (count, seg_count); - return hb_array_t (arrayZ + start_offset, count); + return hb_array_t (arrayZ + start_offset, count); } inline hb_bytes_t as_bytes (void) const { - return hb_bytes_t (arrayZ, len * sizeof (T)); + return hb_bytes_t (arrayZ, len * sizeof (Type)); } inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } - T *arrayZ; + Type *arrayZ; unsigned int len; }; -template static inline -hb_array_t hb_array (T *array, unsigned int len) { return hb_array_t (array, len); } struct HbOpOr diff --git a/src/hb-face.cc b/src/hb-face.cc index 7ca4b1ba2..50ab10e38 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -82,8 +82,6 @@ DEFINE_NULL_INSTANCE (hb_face_t) = { HB_OBJECT_HEADER_STATIC, - true, /* immutable */ - nullptr, /* reference_table_func */ nullptr, /* user_data */ nullptr, /* destroy */ @@ -336,12 +334,10 @@ hb_face_get_user_data (const hb_face_t *face, void hb_face_make_immutable (hb_face_t *face) { - if (unlikely (hb_object_is_inert (face))) - return; - if (face->immutable) + if (hb_object_is_immutable (face)) return; - face->immutable = true; + hb_object_make_immutable (face); } /** @@ -357,7 +353,7 @@ hb_face_make_immutable (hb_face_t *face) hb_bool_t hb_face_is_immutable (const hb_face_t *face) { - return face->immutable; + return hb_object_is_immutable (face); } @@ -408,7 +404,7 @@ void hb_face_set_index (hb_face_t *face, unsigned int index) { - if (face->immutable) + if (hb_object_is_immutable (face)) return; face->index = index; @@ -443,7 +439,7 @@ void hb_face_set_upem (hb_face_t *face, unsigned int upem) { - if (face->immutable) + if (hb_object_is_immutable (face)) return; face->upem = upem; @@ -478,7 +474,7 @@ void hb_face_set_glyph_count (hb_face_t *face, unsigned int glyph_count) { - if (face->immutable) + if (hb_object_is_immutable (face)) return; face->num_glyphs = glyph_count; diff --git a/src/hb-face.hh b/src/hb-face.hh index 89673ff84..520bdfdf8 100644 --- a/src/hb-face.hh +++ b/src/hb-face.hh @@ -43,8 +43,6 @@ struct hb_face_t { hb_object_header_t header; - hb_bool_t immutable; - hb_reference_table_func_t reference_table_func; void *user_data; hb_destroy_func_t destroy; diff --git a/src/hb-font.cc b/src/hb-font.cc index 86b03f4b6..b24995b12 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -471,8 +471,6 @@ DEFINE_NULL_INSTANCE (hb_font_funcs_t) = { HB_OBJECT_HEADER_STATIC, - true, /* immutable */ - { #define HB_FONT_FUNC_IMPLEMENT(name) nullptr, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS @@ -495,8 +493,6 @@ DEFINE_NULL_INSTANCE (hb_font_funcs_t) = static const hb_font_funcs_t _hb_font_funcs_default = { HB_OBJECT_HEADER_STATIC, - true, /* immutable */ - { #define HB_FONT_FUNC_IMPLEMENT(name) nullptr, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS @@ -645,12 +641,10 @@ hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, void hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) { - if (unlikely (hb_object_is_inert (ffuncs))) - return; - if (ffuncs->immutable) + if (hb_object_is_immutable (ffuncs)) return; - ffuncs->immutable = true; + hb_object_make_immutable (ffuncs); } /** @@ -666,7 +660,7 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) hb_bool_t hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs) { - return ffuncs->immutable; + return hb_object_is_immutable (ffuncs); } @@ -678,7 +672,7 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ void *user_data, \ hb_destroy_func_t destroy) \ { \ - if (ffuncs->immutable) { \ + if (hb_object_is_immutable (ffuncs)) { \ if (destroy) \ destroy (user_data); \ return; \ @@ -1299,8 +1293,6 @@ DEFINE_NULL_INSTANCE (hb_font_t) = { HB_OBJECT_HEADER_STATIC, - true, /* immutable */ - nullptr, /* parent */ const_cast (&_hb_Null_hb_face_t), @@ -1385,7 +1377,7 @@ hb_font_create_sub_font (hb_font_t *parent) hb_font_t *font = _hb_font_create (parent->face); - if (unlikely (hb_object_is_inert (font))) + if (unlikely (hb_object_is_immutable (font))) return font; font->parent = hb_font_reference (parent); @@ -1525,15 +1517,13 @@ hb_font_get_user_data (hb_font_t *font, void hb_font_make_immutable (hb_font_t *font) { - if (unlikely (hb_object_is_inert (font))) - return; - if (font->immutable) + if (hb_object_is_immutable (font)) return; if (font->parent) hb_font_make_immutable (font->parent); - font->immutable = true; + hb_object_make_immutable (font); } /** @@ -1549,7 +1539,7 @@ hb_font_make_immutable (hb_font_t *font) hb_bool_t hb_font_is_immutable (hb_font_t *font) { - return font->immutable; + return hb_object_is_immutable (font); } /** @@ -1565,7 +1555,7 @@ void hb_font_set_parent (hb_font_t *font, hb_font_t *parent) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; if (!parent) @@ -1607,7 +1597,7 @@ void hb_font_set_face (hb_font_t *font, hb_face_t *face) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; if (unlikely (!face)) @@ -1654,7 +1644,8 @@ hb_font_set_funcs (hb_font_t *font, void *font_data, hb_destroy_func_t destroy) { - if (font->immutable) { + if (hb_object_is_immutable (font)) + { if (destroy) destroy (font_data); return; @@ -1689,7 +1680,8 @@ hb_font_set_funcs_data (hb_font_t *font, hb_destroy_func_t destroy) { /* Destroy user_data? */ - if (font->immutable) { + if (hb_object_is_immutable (font)) + { if (destroy) destroy (font_data); return; @@ -1718,7 +1710,7 @@ hb_font_set_scale (hb_font_t *font, int x_scale, int y_scale) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; font->x_scale = x_scale; @@ -1759,7 +1751,7 @@ hb_font_set_ppem (hb_font_t *font, unsigned int x_ppem, unsigned int y_ppem) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; font->x_ppem = x_ppem; @@ -1799,7 +1791,7 @@ hb_font_get_ppem (hb_font_t *font, void hb_font_set_ptem (hb_font_t *font, float ptem) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; font->ptem = ptem; @@ -1846,7 +1838,7 @@ hb_font_set_variations (hb_font_t *font, const hb_variation_t *variations, unsigned int variations_length) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; if (!variations_length) @@ -1877,7 +1869,7 @@ hb_font_set_var_coords_design (hb_font_t *font, const float *coords, unsigned int coords_length) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr; @@ -1898,7 +1890,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font, const int *coords, /* 2.14 normalized */ unsigned int coords_length) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr; diff --git a/src/hb-font.hh b/src/hb-font.hh index 3dce233db..fb29bcc22 100644 --- a/src/hb-font.hh +++ b/src/hb-font.hh @@ -63,8 +63,6 @@ struct hb_font_funcs_t { hb_object_header_t header; - hb_bool_t immutable; - struct { #define HB_FONT_FUNC_IMPLEMENT(name) void *name; HB_FONT_FUNCS_IMPLEMENT_CALLBACKS @@ -102,8 +100,6 @@ struct hb_font_t { hb_object_header_t header; - hb_bool_t immutable; - hb_font_t *parent; hb_face_t *face; diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 5e0511052..8b80b960b 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -135,7 +135,7 @@ _hb_ft_font_destroy (void *data) void hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) diff --git a/src/hb-null.hh b/src/hb-null.hh index 204689bd7..43bba9c1d 100644 --- a/src/hb-null.hh +++ b/src/hb-null.hh @@ -103,4 +103,34 @@ struct CrapOrNull { #define CrapOrNull(Type) CrapOrNull::get () +/* + * hb_nonnull_ptr_t + */ + +template +struct hb_nonnull_ptr_t +{ + typedef typename hb_remove_pointer

::value T; + + inline hb_nonnull_ptr_t (T *v_ = nullptr) : v (v_) {} + inline T * operator = (T *v_) { return v = v_; } + inline T * operator -> (void) { return get (); } + inline const T * operator -> (void) const { return get (); } + inline T & operator * (void) { return *get (); } + inline const T & operator * (void) const { return *get (); } + inline T ** operator & (void) { return &v; } + inline const T ** operator & (void) const { return &v; } + template inline operator C * (void) { return get (); } + template inline operator const C * (void) const { return get (); } + inline operator char * (void) { return (char *) get (); } + inline operator const char * (void) const { return (const char *) get (); } + inline T * get (void) { return v ? v : const_cast (&Null(T)); } + inline const T * get (void) const { return v ? v : const_cast (&Null(T)); } + inline T * get_raw (void) { return v; } + inline const T * get_raw (void) const { return v; } + + T *v; +}; + + #endif /* HB_NULL_HH */ diff --git a/src/hb-object.hh b/src/hb-object.hh index 106f59206..74340c555 100644 --- a/src/hb-object.hh +++ b/src/hb-object.hh @@ -194,9 +194,15 @@ struct hb_user_data_array_t struct hb_object_header_t { hb_reference_count_t ref_count; + hb_atomic_int_t writable; hb_atomic_ptr_t user_data; }; -#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_ATOMIC_PTR_INIT (nullptr)} +#define HB_OBJECT_HEADER_STATIC \ + { \ + HB_REFERENCE_COUNT_INIT, \ + HB_ATOMIC_INT_INIT (false), \ + HB_ATOMIC_PTR_INIT (nullptr) \ + } /* @@ -228,6 +234,7 @@ template static inline void hb_object_init (Type *obj) { obj->header.ref_count.init (); + obj->header.writable.set_relaxed (true); obj->header.user_data.init (); } template @@ -241,6 +248,16 @@ static inline bool hb_object_is_valid (const Type *obj) return likely (obj->header.ref_count.is_valid ()); } template +static inline bool hb_object_is_immutable (const Type *obj) +{ + return !obj->header.writable.get_relaxed (); +} +template +static inline void hb_object_make_immutable (const Type *obj) +{ + obj->header.writable.set_relaxed (false); +} +template static inline Type *hb_object_reference (Type *obj) { hb_object_trace (obj, HB_FUNC); diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh index 80dc5e614..2ef6d775f 100644 --- a/src/hb-open-file.hh +++ b/src/hb-open-file.hh @@ -330,7 +330,7 @@ struct ResourceTypeRecord inline const ResourceRecord& get_resource_record (unsigned int i, const void *type_base) const { - return hb_array (type_base+resourcesZ, get_resource_count ())[i]; + return (type_base+resourcesZ).as_array (get_resource_count ())[i]; } inline bool sanitize (hb_sanitize_context_t *c, diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 00bd134dd..0f6efdc69 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -340,9 +340,15 @@ struct UnsizedArrayOf inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; } inline Type& operator [] (unsigned int i) { return arrayZ[i]; } - template inline operator T * (void) { return arrayZ; } + template inline operator T * (void) { return arrayZ; } template inline operator const T * (void) const { return arrayZ; } + inline unsigned int get_size (unsigned int len) const + { return len * Type::static_size; } + + inline hb_array_t as_array (unsigned int len) { return hb_array_t (arrayZ, len); } + inline hb_array_t as_array (unsigned int len) const { return hb_array_t (arrayZ, len); } + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { TRACE_SANITIZE (this); @@ -390,14 +396,6 @@ struct UnsizedArrayOf public: DEFINE_SIZE_ARRAY (0, arrayZ); }; -} /* namespace OT */ -template static inline -hb_array_t hb_array (OT::UnsizedArrayOf &array, unsigned int len) -{ return hb_array (array.arrayZ, len); } -template static inline -hb_array_t hb_array (const OT::UnsizedArrayOf &array, unsigned int len) -{ return hb_array (array.arrayZ, len); } -namespace OT { /* Unsized array of offset's */ template @@ -454,9 +452,6 @@ struct ArrayOf return arrayZ[i]; } - template inline operator T * (void) { return arrayZ; } - template inline operator const T * (void) const { return arrayZ; } - inline unsigned int get_size (void) const { return len.static_size + len * Type::static_size; } diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh index 614cc80ce..580dc3769 100644 --- a/src/hb-ot-color-cbdt-table.hh +++ b/src/hb-ot-color-cbdt-table.hh @@ -409,9 +409,6 @@ struct CBDT inline bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const { - if (!cblc) - return false; - const void *base; const BitmapSizeTable &strike = this->cblc->choose_strike (font); const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base); @@ -467,9 +464,6 @@ struct CBDT inline hb_blob_t* reference_png (hb_font_t *font, hb_codepoint_t glyph) const { - if (!cblc) - return hb_blob_get_empty (); - const void *base; const BitmapSizeTable &strike = this->cblc->choose_strike (font); const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base); @@ -525,8 +519,8 @@ struct CBDT private: hb_blob_t *cblc_blob; hb_blob_t *cbdt_blob; - const CBLC *cblc; - const CBDT *cbdt; + hb_nonnull_ptr_t cblc; + hb_nonnull_ptr_t cbdt; unsigned int cbdt_len; unsigned int upem; diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index df4d9b4e7..332f0dd74 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -55,7 +55,7 @@ struct CPALV1Tail { if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; return (hb_ot_color_palette_flags_t) (uint32_t) - hb_array (base+paletteFlagsZ, palette_count)[palette_index]; + (base+paletteFlagsZ).as_array (palette_count)[palette_index]; } inline hb_ot_name_id_t @@ -64,7 +64,7 @@ struct CPALV1Tail unsigned int palette_count) const { if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID; - return hb_array (base+paletteLabelsZ, palette_count)[palette_index]; + return (base+paletteLabelsZ).as_array (palette_count)[palette_index]; } inline hb_ot_name_id_t @@ -73,7 +73,7 @@ struct CPALV1Tail unsigned int color_count) const { if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID; - return hb_array (base+colorLabelsZ, color_count)[color_index]; + return (base+colorLabelsZ).as_array (color_count)[color_index]; } public: diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index 065c0dd18..7a01d14ae 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -152,9 +152,6 @@ struct sbix inline bool has_data () const { - /* XXX Fix somehow and remove next line. - * https://github.com/harfbuzz/harfbuzz/issues/1146 */ - if (!num_glyphs) return false; return table->has_data (); } @@ -234,8 +231,8 @@ struct sbix hb_codepoint_t glyph, hb_glyph_extents_t *extents) const { - /* Following code is safe to call even without data (XXX currently - * isn't. See has_data()), but faster to short-circuit. */ + /* Following code is safe to call even without data. + * But faster to short-circuit. */ if (!has_data ()) return false; @@ -262,12 +259,12 @@ struct sbix hb_blob_destroy (blob); - return true; + return strike_ppem; } private: hb_blob_t *sbix_blob; - const sbix *table; + hb_nonnull_ptr_t table; unsigned int num_glyphs; }; diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh index bb4c4f757..069c54788 100644 --- a/src/hb-ot-color-svg-table.hh +++ b/src/hb-ot-color-svg-table.hh @@ -75,12 +75,13 @@ struct SVG { static const hb_tag_t tableTag = HB_OT_TAG_SVG; + inline bool has_data (void) const { return svgDocEntries; } + struct accelerator_t { inline void init (hb_face_t *face) { svg_blob = hb_sanitize_context_t().reference_table (face); - svg_len = hb_blob_get_length (svg_blob); table = svg_blob->as (); } @@ -91,18 +92,14 @@ struct SVG inline hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const { - if (unlikely (!svg_len)) - return hb_blob_get_empty (); return table->get_glyph_entry (glyph_id).reference_blob (svg_blob, table->svgDocEntries); } - inline bool has_data () const { return svg_len; } + inline bool has_data () const { return table->has_data (); } private: hb_blob_t *svg_blob; - const SVG *table; - - unsigned int svg_len; + hb_nonnull_ptr_t table; }; inline const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh index 72e449515..9719ad402 100644 --- a/src/hb-ot-face.hh +++ b/src/hb-ot-face.hh @@ -67,7 +67,7 @@ HB_OT_ACCELERATOR(OT, hmtx) \ HB_OT_ACCELERATOR(OT, vmtx) \ HB_OT_ACCELERATOR(OT, post) \ - HB_OT_ACCELERATOR(OT, kern) \ + HB_OT_TABLE(OT, kern) \ HB_OT_ACCELERATOR(OT, glyf) \ HB_OT_ACCELERATOR(OT, cff1) \ HB_OT_ACCELERATOR(OT, cff2) \ diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh index 7bd175e39..d2a39f230 100644 --- a/src/hb-ot-glyf-table.hh +++ b/src/hb-ot-glyf-table.hh @@ -276,7 +276,7 @@ struct glyf if (!get_offsets (glyph, &start_offset, &end_offset)) return false; /* glyph not found */ - return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset, + return CompositeGlyphHeader::get_iterator ((const char *) this->glyf_table + start_offset, end_offset - start_offset, composite); } @@ -476,8 +476,8 @@ struct glyf private: bool short_offset; unsigned int num_glyphs; - const loca *loca_table; - const glyf *glyf_table; + hb_nonnull_ptr_t loca_table; + hb_nonnull_ptr_t glyf_table; hb_blob_t *loca_blob; hb_blob_t *glyf_blob; unsigned int glyf_len; diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index 1eb6cc68f..f898a0336 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -194,8 +194,8 @@ struct hmtxvmtx bool got_font_extents = false; if (T::os2Tag) { - hb_blob_t *os2_blob = hb_sanitize_context_t().reference_table (face); - const os2 *os2_table = os2_blob->as (); + hb_blob_t *os2_blob = hb_sanitize_context_t().reference_table (face); + const OS2 *os2_table = os2_blob->as (); #define USE_TYPO_METRICS (1u<<7) if (0 != (os2_table->fsSelection & USE_TYPO_METRICS)) { @@ -336,7 +336,7 @@ struct hmtxvmtx struct hmtx : hmtxvmtx { static const hb_tag_t tableTag = HB_OT_TAG_hmtx; static const hb_tag_t variationsTag = HB_OT_TAG_HVAR; - static const hb_tag_t os2Tag = HB_OT_TAG_os2; + static const hb_tag_t os2Tag = HB_OT_TAG_OS2; }; struct vmtx : hmtxvmtx { static const hb_tag_t tableTag = HB_OT_TAG_vmtx; diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh index 63551d313..5bc9e436c 100644 --- a/src/hb-ot-kern-table.hh +++ b/src/hb-ot-kern-table.hh @@ -30,6 +30,7 @@ #include "hb-open-type.hh" #include "hb-ot-shape.hh" #include "hb-ot-layout-gsubgpos.hh" +#include "hb-aat-layout-common.hh" template @@ -165,6 +166,19 @@ struct KernSubTableFormat0 return pairs[i].get_kerning (); } + inline bool apply (AAT::hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + if (!c->plan->requested_kerning) + return false; + + hb_kern_machine_t machine (*this); + machine.kern (c->font, c->buffer, c->plan->kern_mask); + + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -177,6 +191,130 @@ struct KernSubTableFormat0 DEFINE_SIZE_ARRAY (8, pairs); }; +struct KernSubTableFormat1 +{ + typedef void EntryData; + + struct driver_context_t + { + static const bool in_place = true; + enum Flags + { + Push = 0x8000, /* If set, push this glyph on the kerning stack. */ + DontAdvance = 0x4000, /* If set, don't advance to the next glyph + * before going to the new state. */ + Offset = 0x3FFF, /* Byte offset from beginning of subtable to the + * value table for the glyphs on the kerning stack. */ + }; + + inline driver_context_t (const KernSubTableFormat1 *table_, + AAT::hb_aat_apply_context_t *c_) : + c (c_), + table (table_), + /* Apparently the offset kernAction is from the beginning of the state-machine, + * similar to offsets in morx table, NOT from beginning of this table, like + * other subtables in kerx. Discovered via testing. */ + kernAction (&table->machine + table->kernAction), + depth (0) {} + + inline bool is_actionable (AAT::StateTableDriver *driver HB_UNUSED, + const AAT::Entry *entry) + { + return entry->flags & Offset; + } + inline bool transition (AAT::StateTableDriver *driver, + const AAT::Entry *entry) + { + hb_buffer_t *buffer = driver->buffer; + unsigned int flags = entry->flags; + + if (flags & Push) + { + if (likely (depth < ARRAY_LENGTH (stack))) + stack[depth++] = buffer->idx; + else + depth = 0; /* Probably not what CoreText does, but better? */ + } + + if (entry->flags & Offset) + { + unsigned int kernIndex = AAT::MortTypes::offsetToIndex (entry->flags & Offset, &table->machine, kernAction.arrayZ); + const FWORD *actions = &kernAction[kernIndex]; + if (!c->sanitizer.check_array (actions, depth)) + { + depth = 0; + return false; + } + + hb_mask_t kern_mask = c->plan->kern_mask; + for (unsigned int i = 0; i < depth; i++) + { + /* Apparently, when spec says "Each pops one glyph from the kerning stack + * and applies the kerning value to it.", it doesn't mean it in that order. + * The deepest item in the stack corresponds to the first item in the action + * list. Discovered by testing. */ + unsigned int idx = stack[i]; + int v = *actions++; + if (idx < buffer->len && buffer->info[idx].mask & kern_mask) + { + if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) + { + buffer->pos[idx].x_advance += c->font->em_scale_x (v); + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + buffer->pos[idx].x_offset += c->font->em_scale_x (v); + } + else + { + buffer->pos[idx].y_advance += c->font->em_scale_y (v); + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + buffer->pos[idx].y_offset += c->font->em_scale_y (v); + } + } + } + depth = 0; + } + + return true; + } + + private: + AAT::hb_aat_apply_context_t *c; + const KernSubTableFormat1 *table; + const UnsizedArrayOf &kernAction; + unsigned int stack[8]; + unsigned int depth; + }; + + inline bool apply (AAT::hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + if (!c->plan->requested_kerning) + return false; + + driver_context_t dc (this, c); + + AAT::StateTableDriver driver (machine, c->buffer, c->font->face); + driver.drive (&dc); + + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + /* The rest of array sanitizations are done at run-time. */ + return_trace (likely (c->check_struct (this) && + machine.sanitize (c))); + } + + protected: + AAT::StateTable machine; + OffsetTo, HBUINT16, false> kernAction; + public: + DEFINE_SIZE_STATIC (10); +}; + struct KernClassTable { inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; } @@ -184,7 +322,8 @@ struct KernClassTable inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (firstGlyph.sanitize (c) && classes.sanitize (c)); + return_trace (c->check_struct (this) && + classes.sanitize (c)); } protected: @@ -196,29 +335,58 @@ struct KernClassTable struct KernSubTableFormat2 { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, + AAT::hb_aat_apply_context_t *c) const { /* This subtable is disabled. It's not cleaer to me *exactly* where the offests are * based from. I *think* they should be based from beginning of kern subtable wrapper, * *NOT* "this". Since we know of no fonts that use this subtable, we are disabling - * it. Someday fix it and re-enable. Better yet, find fonts that use it... Meh, - * Windows doesn't implement it. Maybe just remove... */ + * it. Someday fix it and re-enable. */ return 0; unsigned int l = (this+leftClassTable).get_class (left); unsigned int r = (this+rightClassTable).get_class (right); unsigned int offset = l + r; const FWORD *v = &StructAtOffset (&(this+array), offset); +#if 0 if (unlikely ((const char *) v < (const char *) &array || (const char *) v > (const char *) end - 2)) +#endif return 0; return *v; } + inline bool apply (AAT::hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + if (!c->plan->requested_kerning) + return false; + + accelerator_t accel (*this, c); + hb_kern_machine_t machine (accel); + machine.kern (c->font, c->buffer, c->plan->kern_mask); + + return_trace (true); + } + + struct accelerator_t + { + const KernSubTableFormat2 &table; + AAT::hb_aat_apply_context_t *c; + + inline accelerator_t (const KernSubTableFormat2 &table_, + AAT::hb_aat_apply_context_t *c_) : + table (table_), c (c_) {} + + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { return table.get_kerning (left, right, c); } + }; + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (true); /* Disabled. See above. */ - return_trace (rowWidth.sanitize (c) && + return_trace (c->check_struct (this) && leftClassTable.sanitize (c, this) && rightClassTable.sanitize (c, this) && array.sanitize (c, this)); @@ -239,23 +407,101 @@ struct KernSubTableFormat2 DEFINE_SIZE_MIN (8); }; +struct KernSubTableFormat3 +{ + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { + hb_array_t kernValue = kernValueZ.as_array (kernValueCount); + hb_array_t leftClass = StructAfter > (kernValue).as_array (glyphCount); + hb_array_t rightClass = StructAfter > (leftClass).as_array (glyphCount); + hb_array_t kernIndex = StructAfter > (rightClass).as_array (leftClassCount * rightClassCount); + + unsigned int leftC = leftClass[left]; + unsigned int rightC = rightClass[right]; + if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount)) + return 0; + unsigned int i = leftC * rightClassCount + rightC; + return kernValue[kernIndex[i]]; + } + + inline bool apply (AAT::hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + if (!c->plan->requested_kerning) + return false; + + hb_kern_machine_t machine (*this); + machine.kern (c->font, c->buffer, c->plan->kern_mask); + + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_range (kernValueZ, + kernValueCount * sizeof (FWORD) + + glyphCount * 2 + + leftClassCount * rightClassCount)); + } + + protected: + HBUINT16 glyphCount; /* The number of glyphs in this font. */ + HBUINT8 kernValueCount; /* The number of kerning values. */ + HBUINT8 leftClassCount; /* The number of left-hand classes. */ + HBUINT8 rightClassCount;/* The number of right-hand classes. */ + HBUINT8 flags; /* Set to zero (reserved for future use). */ + UnsizedArrayOf + kernValueZ; /* The kerning values. + * Length kernValueCount. */ +#if 0 + UnsizedArrayOf + leftClass; /* The left-hand classes. + * Length glyphCount. */ + UnsizedArrayOf + RightClass; /* The right-hand classes. + * Length glyphCount. */ + UnsizedArrayOf + kernIndex; /* The indices into the kernValue array. + * Length leftClassCount * rightClassCount */ +#endif + public: + DEFINE_SIZE_ARRAY (6, kernValueZ); +}; + struct KernSubTable { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int format) const { switch (format) { + /* This method hooks up to hb_font_t's get_h_kerning. Only support Format0. */ case 0: return u.format0.get_kerning (left, right); - case 2: return u.format2.get_kerning (left, right, end); default:return 0; } } + inline void apply (AAT::hb_aat_apply_context_t *c, unsigned int format) const + { + /* TODO Switch to dispatch(). */ + switch (format) { + case 0: u.format0.apply (c); return; + case 1: u.format1.apply (c); return; + case 2: u.format2.apply (c); return; + case 3: u.format3.apply (c); return; + default: return; + } + } + inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const { TRACE_SANITIZE (this); switch (format) { case 0: return_trace (u.format0.sanitize (c)); + case 1: return_trace (u.format1.sanitize (c)); case 2: return_trace (u.format2.sanitize (c)); + case 3: return_trace (u.format3.sanitize (c)); default:return_trace (true); } } @@ -263,7 +509,9 @@ struct KernSubTable protected: union { KernSubTableFormat0 format0; + KernSubTableFormat1 format1; KernSubTableFormat2 format2; + KernSubTableFormat3 format3; } u; public: DEFINE_SIZE_MIN (0); @@ -276,17 +524,23 @@ struct KernSubTableWrapper /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ inline const T* thiz (void) const { return static_cast (this); } + inline bool is_supported (void) const + { return !(thiz()->coverage & T::CheckFlags); } + inline bool is_horizontal (void) const - { return (thiz()->coverage & T::CheckFlags) == T::CheckHorizontal; } + { return (thiz()->coverage & T::Direction) == T::CheckHorizontal; } inline bool is_override (void) const { return bool (thiz()->coverage & T::Override); } - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); } + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { return thiz()->subtable.get_kerning (left, right, thiz()->format); } - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { return is_horizontal () ? get_kerning (left, right, end) : 0; } + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { return is_supported () && is_horizontal () ? get_kerning (left, right) : 0; } + + inline void apply (AAT::hb_aat_apply_context_t *c) const + { thiz()->subtable.apply (c, thiz()->format); } inline unsigned int get_size (void) const { return thiz()->length; } @@ -313,14 +567,53 @@ struct KernTable unsigned int count = thiz()->nTables; for (unsigned int i = 0; i < count; i++) { - if (st->is_override ()) + if (st->is_supported () && st->is_override ()) v = 0; - v += st->get_h_kerning (left, right, st->length + (const char *) st); + v += st->get_h_kerning (left, right); st = &StructAfter (*st); } return v; } + inline void apply (AAT::hb_aat_apply_context_t *c) const + { + c->set_lookup_index (0); + const typename T::SubTableWrapper *st = CastP (&thiz()->dataZ); + unsigned int count = thiz()->nTables; + /* If there's an override subtable, skip subtables before that. */ + unsigned int last_override = 0; + for (unsigned int i = 0; i < count; i++) + { + if (st->is_supported () && st->is_override ()) + last_override = i; + st = &StructAfter (*st); + } + st = CastP (&thiz()->dataZ); + for (unsigned int i = 0; i < count; i++) + { + if (!st->is_supported ()) + goto skip; + + if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->is_horizontal ()) + goto skip; + + if (i < last_override) + goto skip; + + if (!c->buffer->message (c->font, "start kern subtable %d", c->lookup_index)) + goto skip; + + c->sanitizer.set_object (*st); + + st->apply (c); + + (void) c->buffer->message (c->font, "end kern subtable %d", c->lookup_index); + + skip: + st = &StructAfter (*st); + } + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -361,7 +654,7 @@ struct KernOT : KernTable Variation = 0x00u, /* Not supported. */ - CheckFlags = 0x07u, + CheckFlags = 0x06u, CheckHorizontal = 0x01u }; @@ -402,7 +695,7 @@ struct KernAAT : KernTable Override = 0x00u, /* Not supported. */ - CheckFlags = 0xE0u, + CheckFlags = 0x60u, CheckHorizontal = 0x00u }; @@ -441,6 +734,16 @@ struct kern } } + inline void apply (AAT::hb_aat_apply_context_t *c) const + { + /* TODO Switch to dispatch(). */ + switch (u.major) { + case 0: u.ot.apply (c); return; + case 1: u.aat.apply (c); return; + default: return; + } + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -452,45 +755,6 @@ struct kern } } - struct accelerator_t - { - inline void init (hb_face_t *face) - { - blob = hb_sanitize_context_t().reference_table (face); - table = blob->as (); - } - inline void fini (void) - { - hb_blob_destroy (blob); - } - - inline bool has_data (void) const - { return table->has_data (); } - - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const - { return table->get_h_kerning (left, right); } - - inline int get_kerning (hb_codepoint_t first, hb_codepoint_t second) const - { return get_h_kerning (first, second); } - - inline void apply (hb_font_t *font, - hb_buffer_t *buffer, - hb_mask_t kern_mask) const - { - /* We only apply horizontal kerning in this table. */ - if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) - return; - - hb_kern_machine_t machine (*this); - - machine.kern (font, buffer, kern_mask); - } - - private: - hb_blob_t *blob; - const kern *table; - }; - protected: union { HBUINT32 version32; @@ -502,8 +766,6 @@ struct kern DEFINE_SIZE_UNION (4, version32); }; -struct kern_accelerator_t : kern::accelerator_t {}; - } /* namespace OT */ diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index 449e74550..582e60155 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -1,6 +1,7 @@ /* * Copyright © 2016 Elie Roux * Copyright © 2018 Google, Inc. + * Copyright © 2018 Ebrahim Byagowi * * This is part of HarfBuzz, a text shaping library. * @@ -31,6 +32,9 @@ #include "hb-open-type.hh" #include "hb-ot-layout-common.hh" +/* To be removed */ +typedef hb_tag_t hb_ot_layout_baseline_t; + namespace OT { /* @@ -38,19 +42,14 @@ namespace OT { * 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; } + inline hb_position_t get_coord () const { return coordinate; } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); + return_trace (likely (c->check_struct (this))); } protected: @@ -62,7 +61,7 @@ struct BaseCoordFormat1 struct BaseCoordFormat2 { - inline int get_coord (void) const + inline hb_position_t get_coord () const { /* TODO */ return coordinate; @@ -86,37 +85,45 @@ struct BaseCoordFormat2 struct BaseCoordFormat3 { - inline int get_coord (void) const + inline hb_position_t get_coord (hb_font_t *font, + const VariationStore &var_store, + hb_direction_t direction) const { - /* TODO */ - return coordinate; + const Device &device = this+deviceTable; + return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ? + device.get_y_delta (font, var_store) : + device.get_x_delta (font, var_store)); } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && deviceTable.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + deviceTable.sanitize (c, this))); } protected: - HBUINT16 format; /* Format identifier--format = 3 */ - 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). */ + HBUINT16 format; /* Format identifier--format = 3 */ + 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). */ public: DEFINE_SIZE_STATIC (6); }; struct BaseCoord { - inline int get_coord (void) const + inline hb_position_t get_coord (hb_font_t *font, + const VariationStore &var_store, + hb_direction_t direction) const { - /* XXX wire up direction and font. */ switch (u.format) { case 1: return u.format1.get_coord (); case 2: return u.format2.get_coord (); - case 3: return u.format3.get_coord (); + case 3: return u.format3.get_coord (font, var_store, direction); default:return 0; } } @@ -124,7 +131,7 @@ struct BaseCoord inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!u.format.sanitize (c)) return_trace (false); + if (unlikely (!u.format.sanitize (c))) return_trace (false); switch (u.format) { case 1: return_trace (u.format1.sanitize (c)); case 2: return_trace (u.format2.sanitize (c)); @@ -146,28 +153,40 @@ struct BaseCoord struct FeatMinMaxRecord { - inline int get_min_value (void) const { return (this+minCoord).get_coord(); } - inline int get_max_value (void) const { return (this+maxCoord).get_coord(); } + static int cmp (const void *key_, const void *entry_) + { + hb_tag_t key = * (hb_tag_t *) key_; + const FeatMinMaxRecord &entry = * (const FeatMinMaxRecord *) entry_; + return key < (unsigned int) entry.tag ? -1 : + key > (unsigned int) entry.tag ? 1 : + 0; + } - inline const Tag& get_tag () const { return tag; } + inline void get_min_max (const BaseCoord **min, const BaseCoord **max) const + { + if (likely (min)) *min = &(this+minCoord); + if (likely (max)) *max = &(this+maxCoord); + } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - minCoord.sanitize (c, base) && - maxCoord.sanitize (c, base)); + return_trace (likely (c->check_struct (this) && + minCoord.sanitize (c, this) && + maxCoord.sanitize (c, this))); } protected: - Tag tag; /* 4-byte feature identification tag--must - * match feature tag in FeatureList */ - OffsetTo minCoord; /* Offset to BaseCoord table that defines - * the minimum extent value, from beginning - * of MinMax table (may be NULL) */ - OffsetTo maxCoord; /* Offset to BaseCoord table that defines - * the maximum extent value, from beginning - * of MinMax table (may be NULL) */ + Tag tag; /* 4-byte feature identification tag--must + * match feature tag in FeatureList */ + OffsetTo + minCoord; /* Offset to BaseCoord table that defines + * the minimum extent value, from beginning + * of MinMax table (may be NULL) */ + OffsetTo + maxCoord; /* Offset to BaseCoord table that defines + * the maximum extent value, from beginning + * of MinMax table (may be NULL) */ public: DEFINE_SIZE_STATIC (8); @@ -175,257 +194,202 @@ struct FeatMinMaxRecord struct MinMax { - inline unsigned int get_feature_tag_index (Tag featureTableTag) const + inline void get_min_max (hb_tag_t feature_tag, + const BaseCoord **min, + const BaseCoord **max) const { - /* TODO bsearch */ - unsigned int count = featMinMaxRecords.len; - for (unsigned int i = 0; i < count; i++) + const FeatMinMaxRecord *minMaxCoord = (const FeatMinMaxRecord *) + hb_bsearch (&feature_tag, featMinMaxRecords.arrayZ, + featMinMaxRecords.len, + FeatMinMaxRecord::static_size, + FeatMinMaxRecord::cmp); + if (minMaxCoord) + minMaxCoord->get_min_max (min, max); + else { - Tag tag = featMinMaxRecords[i].get_tag (); - int cmp = tag.cmp(featureTableTag); - if (cmp == 0) return i; - if (cmp > 0) return NOT_INDEXED; + if (likely (min)) *min = &(this+minCoord); + if (likely (max)) *max = &(this+maxCoord); } - return NOT_INDEXED; - } - - inline int get_min_value (unsigned int featureTableTagIndex) const - { - if (featureTableTagIndex == NOT_INDEXED) - return (this+minCoord).get_coord(); - return featMinMaxRecords[featureTableTagIndex].get_min_value(); - } - - inline int get_max_value (unsigned int featureTableTagIndex) const - { - if (featureTableTagIndex == NOT_INDEXED) - return (this+maxCoord).get_coord(); - return featMinMaxRecords[featureTableTagIndex].get_max_value(); } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - minCoord.sanitize (c, this) && - maxCoord.sanitize (c, this) && - featMinMaxRecords.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + minCoord.sanitize (c, this) && + maxCoord.sanitize (c, this) && + featMinMaxRecords.sanitize (c, this))); } protected: - OffsetTo minCoord; /* Offset to BaseCoord table that defines - * minimum extent value, from the beginning - * of MinMax table (may be NULL) */ - OffsetTo maxCoord; /* Offset to BaseCoord table that defines - * maximum extent value, from the beginning - * of MinMax table (may be NULL) */ + OffsetTo + minCoord; /* Offset to BaseCoord table that defines + * minimum extent value, from the beginning + * of MinMax table (may be NULL) */ + OffsetTo + maxCoord; /* Offset to BaseCoord table that defines + * maximum extent value, from the beginning + * of MinMax table (may be NULL) */ ArrayOf - featMinMaxRecords; /* Array of FeatMinMaxRecords, in alphabetical - * order by featureTableTag */ + featMinMaxRecords; + /* Array of FeatMinMaxRecords, in alphabetical + * order by featureTableTag */ public: DEFINE_SIZE_ARRAY (6, featMinMaxRecords); }; -/* TODO... */ -struct BaseLangSysRecord -{ - inline const Tag& get_tag(void) const - { return baseLangSysTag; } - - inline unsigned int get_feature_tag_index (Tag featureTableTag) const - { return (this+minMax).get_feature_tag_index( featureTableTag); } - - inline int get_min_value (unsigned int featureTableTagIndex) const - { return (this+minMax).get_min_value( featureTableTagIndex); } - - inline int get_max_value (unsigned int featureTableTagIndex) const - { return (this+minMax).get_max_value (featureTableTagIndex); } - - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - minMax.sanitize (c, base)); - } - - protected: - Tag baseLangSysTag; - OffsetTo minMax; - public: - DEFINE_SIZE_STATIC (6); - -}; - struct BaseValues { - inline unsigned int get_default_base_tag_index (void) const - { return defaultIndex; } - - inline int get_base_coord (unsigned int baselineTagIndex) const + inline const BaseCoord &get_base_coord (int baseline_tag_index) const { - return (this+baseCoords[baselineTagIndex]).get_coord (); + if (baseline_tag_index == -1) baseline_tag_index = defaultIndex; + return this+baseCoords[baseline_tag_index]; } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - baseCoords.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + baseCoords.sanitize (c, this))); } protected: - Index defaultIndex; - OffsetArrayOf baseCoords; + Index defaultIndex; /* Index number of default baseline for this + * script — equals index position of baseline tag + * in baselineTags array of the BaseTagList */ + OffsetArrayOf + baseCoords; /* Number of BaseCoord tables defined — should equal + * baseTagCount in the BaseTagList + * + * Array of offsets to BaseCoord tables, from beginning of + * BaseValues table — order matches baselineTags array in + * the BaseTagList */ public: DEFINE_SIZE_ARRAY (4, baseCoords); }; -struct BaseScript { - - inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const +struct BaseLangSysRecord +{ + static int cmp (const void *key_, const void *entry_) { - /* XXX bsearch */ - Tag tag; - int cmp; - 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; - if (cmp > 0) return NOT_INDEXED; - } - return NOT_INDEXED; + hb_tag_t key = * (hb_tag_t *) key_; + const BaseLangSysRecord &entry = * (const BaseLangSysRecord *) entry_; + return key < (unsigned int) entry.baseLangSysTag ? -1 : + key > (unsigned int) entry.baseLangSysTag ? 1 : + 0; } - inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const - { - if (baseLangSysIndex == NOT_INDEXED) - { - if (unlikely(defaultMinMax)) return NOT_INDEXED; - return (this+defaultMinMax).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); - } - - 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); - } - - inline unsigned int get_default_base_tag_index (void) const - { return (this+baseValues).get_default_base_tag_index (); } - - inline int get_base_coord (unsigned int baselineTagIndex) const - { 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)); - } - - protected: - OffsetTo baseValues; - OffsetTo defaultMinMax; - ArrayOf baseLangSysRecords; - - public: - DEFINE_SIZE_ARRAY (6, baseLangSysRecords); -}; - - -struct BaseScriptRecord { - - inline const Tag& get_tag (void) const - { return baseScriptTag; } - - inline unsigned int get_default_base_tag_index(void) const - { return (this+baseScript).get_default_base_tag_index (); } - - inline int get_base_coord(unsigned int baselineTagIndex) const - { 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); } - - inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const - { 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); } - - inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { return (this+baseScript).get_min_value (baseLangSysIndex, featureTableTagIndex); } + inline const MinMax &get_min_max () const + { return this+minMax; } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - baseScript.sanitize (c, base)); + return_trace (likely (c->check_struct (this) && + minMax.sanitize (c, this))); } protected: - Tag baseScriptTag; - OffsetTo baseScript; - + Tag baseLangSysTag; /* 4-byte language system identification tag */ + OffsetTo + minMax; /* Offset to MinMax table, from beginning + * of BaseScript table */ public: - DEFINE_SIZE_STATIC (6); + DEFINE_SIZE_STATIC (6); }; -struct BaseScriptList { - - inline unsigned int get_base_script_index (Tag baseScriptTag) const +struct BaseScript +{ + inline const MinMax &get_min_max (hb_tag_t language_tag) const { - /* 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; + const BaseLangSysRecord* record = (const BaseLangSysRecord *) + hb_bsearch (&language_tag, baseLangSysRecords.arrayZ, + baseLangSysRecords.len, + BaseLangSysRecord::static_size, + BaseLangSysRecord::cmp); + return record ? record->get_min_max () : this+defaultMinMax; } - inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const + inline const BaseCoord &get_base_coord (int baseline_tag_index) const + { return (this+baseValues).get_base_coord (baseline_tag_index); } + + inline bool is_empty () const + { return !baseValues; } + + inline bool sanitize (hb_sanitize_context_t *c) const { - return baseScriptRecords[baseScriptIndex].get_default_base_tag_index(); + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + baseValues.sanitize (c, this) && + defaultMinMax.sanitize (c, this) && + baseLangSysRecords.sanitize (c, this))); } - inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + protected: + OffsetTo + baseValues; /* Offset to BaseValues table, from beginning + * of BaseScript table (may be NULL) */ + OffsetTo + defaultMinMax; /* Offset to MinMax table, from beginning of + * BaseScript table (may be NULL) */ + ArrayOf + baseLangSysRecords; + /* Number of BaseLangSysRecords + * defined — may be zero (0) */ + + public: + DEFINE_SIZE_ARRAY (6, baseLangSysRecords); +}; + +struct BaseScriptList; +struct BaseScriptRecord +{ + static int cmp (const void *key_, const void *entry_) { - return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex); + hb_tag_t key = * (hb_tag_t *) key_; + const BaseScriptRecord &entry = * (const BaseScriptRecord *) entry_; + return key < (unsigned int) entry.baseScriptTag ? -1 : + key > (unsigned int) entry.baseScriptTag ? 1 : + 0; } - inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const + inline const BaseScript &get_base_script (const BaseScriptList *list) const + { return list+baseScript; } + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { - return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag); + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + baseScript.sanitize (c, base))); } - inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + protected: + Tag baseScriptTag; /* 4-byte script identification tag */ + OffsetTo + baseScript; /* Offset to BaseScript table, from beginning + * of BaseScriptList */ + + public: + DEFINE_SIZE_STATIC (6); +}; + +struct BaseScriptList +{ + inline const BaseScriptRecord *find_record (hb_tag_t script) const { - return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag); + return (const BaseScriptRecord *) hb_bsearch (&script, baseScriptRecords.arrayZ, + baseScriptRecords.len, + BaseScriptRecord::static_size, + BaseScriptRecord::cmp); } - inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + /* TODO: Or client should handle fallback? */ + inline const BaseScript &get_base_script (hb_tag_t script) const { - return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex); - } + const BaseScriptRecord *record = find_record (script); + if (!record) record = find_record ((hb_script_t) HB_TAG ('D','F','L','T')); - inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex); + return record ? record->get_base_script (this) : Null (BaseScript); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -436,86 +400,61 @@ struct BaseScriptList { } protected: - ArrayOf baseScriptRecords; + ArrayOf + baseScriptRecords; public: DEFINE_SIZE_ARRAY (2, baseScriptRecords); }; -struct BaseTagList -{ - inline unsigned int get_tag_index (Tag baselineTag) const - { - /* TODO bsearch? */ - unsigned int count = baselineTags.len; - for (unsigned int i = 0; i < count; i++) - if (baselineTags[i] == baselineTag) - return i; - return NOT_INDEXED; - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); - } - - protected: - SortedArrayOf baselineTags; - - public: - DEFINE_SIZE_ARRAY (2, baselineTags); -}; - struct Axis { - - inline unsigned int get_base_tag_index (Tag baselineTag) const + inline bool get_baseline (hb_ot_layout_baseline_t baseline, + hb_tag_t script_tag, + hb_tag_t language_tag, + const BaseCoord **coord) const { - return (this+baseTagList).get_tag_index(baselineTag); + const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); + if (base_script.is_empty ()) return false; + + if (likely (coord)) *coord = &base_script.get_base_coord ((this+baseTagList).bsearch (baseline)); + + return true; } - inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const + inline bool get_min_max (hb_tag_t script_tag, + hb_tag_t language_tag, + hb_tag_t feature_tag, + const BaseCoord **min_coord, + const BaseCoord **max_coord) const { - return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex); - } + const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); + if (base_script.is_empty ()) return false; - inline int get_base_coord (unsigned int baseScriptIndex, unsigned int baselineTagIndex) const - { - return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex); - } + base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord); - inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const - { - 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 - { - return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); - } - - inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); - } - - inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + return true; } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - baseTagList.sanitize (c, this) && - baseScriptList.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + (this+baseTagList).sanitize (c) && + (this+baseScriptList).sanitize (c))); } protected: - OffsetTo baseTagList; - OffsetTo baseScriptList; + OffsetTo > + baseTagList; /* Offset to BaseTagList table, from beginning + * of Axis table (may be NULL) + * Array of 4-byte baseline identification tags — must + * be in alphabetical order */ + OffsetTo + baseScriptList; /* Offset to BaseScriptList table, from beginning + * of Axis table + * Array of BaseScriptRecords, in alphabetical order + * by baseScriptTag */ public: DEFINE_SIZE_STATIC (4); @@ -525,99 +464,70 @@ struct BASE { static const hb_tag_t tableTag = HB_OT_TAG_BASE; - inline bool has_v_axis(void) { return vAxis != 0; } + inline const Axis &get_axis (hb_direction_t direction) const + { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; } - inline bool has_h_axis(void) { return hAxis != 0; } + inline const VariationStore &get_var_store () const + { return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; } - inline unsigned int get_h_base_tag_index (Tag baselineTag) const + inline bool get_baseline (hb_font_t *font, + hb_ot_layout_baseline_t baseline, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_position_t *base) const { - return (this+hAxis).get_base_tag_index(baselineTag); + const BaseCoord *base_coord; + if (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord)) + return false; + + if (likely (base && base_coord)) *base = base_coord->get_coord (font, + get_var_store (), + direction); + return true; } - inline unsigned int get_h_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const + /* TODO: Expose this separately sometime? */ + inline bool get_min_max (hb_font_t *font, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_tag_t feature_tag, + hb_position_t *min, + hb_position_t *max) { - return (this+hAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); - } + const BaseCoord *min_coord, *max_coord; + if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag, + &min_coord, &max_coord)) + return false; - inline int get_h_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const - { - return (this+hAxis).get_base_coord(baseScriptIndex, baselineTagIndex); - } - - inline unsigned int get_v_base_tag_index(Tag baselineTag) const - { - return (this+vAxis).get_base_tag_index(baselineTag); - } - - inline unsigned int get_v_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const - { - return (this+vAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); - } - - inline int get_v_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const - { - return (this+vAxis).get_base_coord(baseScriptIndex, baselineTagIndex); - } - - inline unsigned int get_h_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const - { - return (this+hAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); - } - - inline unsigned int get_h_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const - { - return (this+hAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); - } - - inline int get_h_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+hAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); - } - - inline int get_h_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+hAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); - } - - inline unsigned int get_v_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const - { - return (this+vAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); - } - - inline unsigned int get_v_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const - { - return (this+vAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); - } - - inline int get_v_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+vAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); - } - - inline int get_v_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+vAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + const VariationStore &var_store = get_var_store (); + if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction); + if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction); + return true; } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - likely (version.major == 1) && - hAxis.sanitize (c, this) && - vAxis.sanitize (c, this) && - (version.to_int () < 0x00010001u || varStore.sanitize (c, this))); + return_trace (likely (c->check_struct (this) && + likely (version.major == 1) && + hAxis.sanitize (c, this) && + vAxis.sanitize (c, this) && + (version.to_int () < 0x00010001u || varStore.sanitize (c, this)))); } protected: - FixedVersion<> version; - OffsetTo hAxis; - OffsetTo vAxis; + FixedVersion<>version; /* Version of the BASE table */ + OffsetTohAxis; /* Offset to horizontal Axis table, from beginning + * of BASE table (may be NULL) */ + OffsetTovAxis; /* Offset to vertical Axis table, from beginning + * of BASE table (may be NULL) */ LOffsetTo - varStore; /* Offset to the table of Item Variation - * Store--from beginning of BASE - * header (may be NULL). Introduced - * in version 0x00010001. */ + varStore; /* Offset to the table of Item Variation + * Store--from beginning of BASE + * header (may be NULL). Introduced + * in version 0x00010001. */ public: DEFINE_SIZE_MIN (8); }; diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index 757090861..5847953d3 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -418,7 +418,7 @@ struct GDEF } hb_blob_t *blob; - const GDEF *table; + hb_nonnull_ptr_t table; }; inline unsigned int get_size (void) const diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index c4af42048..0d9eeae58 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -1308,7 +1308,8 @@ struct Rule inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); - const UnsizedArrayOf &lookupRecord = StructAtOffset > (inputZ.arrayZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); + const UnsizedArrayOf &lookupRecord = StructAfter > + (inputZ.as_array ((inputCount ? inputCount - 1 : 0))); context_closure_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, @@ -1318,7 +1319,8 @@ struct Rule inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const { TRACE_COLLECT_GLYPHS (this); - const UnsizedArrayOf &lookupRecord = StructAtOffset > (inputZ.arrayZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); + const UnsizedArrayOf &lookupRecord = StructAfter > + (inputZ.as_array (inputCount ? inputCount - 1 : 0)); context_collect_glyphs_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, @@ -1328,14 +1330,16 @@ struct Rule inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const { TRACE_WOULD_APPLY (this); - const UnsizedArrayOf &lookupRecord = StructAtOffset > (inputZ.arrayZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); + const UnsizedArrayOf &lookupRecord = StructAfter > + (inputZ.as_array (inputCount ? inputCount - 1 : 0)); return_trace (context_would_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context)); } inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); - const UnsizedArrayOf &lookupRecord = StructAtOffset > (inputZ.arrayZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); + const UnsizedArrayOf &lookupRecord = StructAfter > + (inputZ.as_array (inputCount ? inputCount - 1 : 0)); return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context)); } @@ -1686,7 +1690,7 @@ struct ContextFormat3 if (!(this+coverageZ[0]).intersects (c->glyphs)) return; - const LookupRecord *lookupRecord = &StructAtOffset (coverageZ.arrayZ, coverageZ[0].static_size * glyphCount); + const LookupRecord *lookupRecord = &StructAfter (coverageZ.as_array (glyphCount)); struct ContextClosureLookupContext lookup_context = { {intersects_coverage}, this @@ -1702,7 +1706,7 @@ struct ContextFormat3 TRACE_COLLECT_GLYPHS (this); (this+coverageZ[0]).add_coverage (c->input); - const LookupRecord *lookupRecord = &StructAtOffset (coverageZ.arrayZ, coverageZ[0].static_size * glyphCount); + const LookupRecord *lookupRecord = &StructAfter (coverageZ.as_array (glyphCount)); struct ContextCollectGlyphsLookupContext lookup_context = { {collect_coverage}, this @@ -1718,7 +1722,7 @@ struct ContextFormat3 { TRACE_WOULD_APPLY (this); - const LookupRecord *lookupRecord = &StructAtOffset (coverageZ.arrayZ, coverageZ[0].static_size * glyphCount); + const LookupRecord *lookupRecord = &StructAfter (coverageZ.as_array (glyphCount)); struct ContextApplyLookupContext lookup_context = { {match_coverage}, this @@ -1735,7 +1739,7 @@ struct ContextFormat3 unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const LookupRecord *lookupRecord = &StructAtOffset (coverageZ.arrayZ, coverageZ[0].static_size * glyphCount); + const LookupRecord *lookupRecord = &StructAfter (coverageZ.as_array (glyphCount)); struct ContextApplyLookupContext lookup_context = { {match_coverage}, this @@ -1759,7 +1763,7 @@ struct ContextFormat3 if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false); for (unsigned int i = 0; i < count; i++) if (!coverageZ[i].sanitize (c, this)) return_trace (false); - const LookupRecord *lookupRecord = &StructAtOffset (coverageZ.arrayZ, coverageZ[0].static_size * count); + const LookupRecord *lookupRecord = &StructAfter (coverageZ.as_array (glyphCount)); return_trace (c->check_array (lookupRecord, lookupCount)); } @@ -2770,7 +2774,7 @@ struct GSUBGPOS } hb_blob_t *blob; - const T *table; + hb_nonnull_ptr_t table; unsigned int lookup_count; hb_ot_layout_lookup_accelerator_t *accels; }; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index e1b6b2e30..f1f09c76d 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -37,10 +37,8 @@ #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" - -#include "hb-ot-layout-base-table.hh" // Just so we compile them; unused otherwise -#include "hb-ot-layout-jstf-table.hh" // Just so we compile them; unused otherwise - +#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise +#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise #include "hb-ot-kern-table.hh" #include "hb-ot-name-table.hh" @@ -55,10 +53,19 @@ **/ -static const OT::kern::accelerator_t& _get_kern (hb_face_t *face) +static inline const OT::kern& +_get_kern (hb_face_t *face, hb_blob_t **blob = nullptr) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::kern::accelerator_t); - return *hb_ot_face_data (face)->kern; + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) + { + if (blob) + *blob = hb_blob_get_empty (); + return Null(OT::kern); + } + const OT::kern& kern = *(hb_ot_face_data (face)->kern.get ()); + if (blob) + *blob = hb_ot_face_data (face)->kern.get_blob (); + return kern; } const OT::GDEF& _get_gdef (hb_face_t *face) { @@ -106,11 +113,16 @@ hb_ot_layout_has_kerning (hb_face_t *face) } void -hb_ot_layout_kern (hb_font_t *font, - hb_buffer_t *buffer, - hb_mask_t kern_mask) +hb_ot_layout_kern (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { - _get_kern (font->face).apply (font, buffer, kern_mask); + hb_blob_t *blob; + const AAT::kern& kern = _get_kern (font->face, &blob); + + AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); + + kern.apply (&c); } @@ -1411,3 +1423,62 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, { apply_string (c, lookup, accel); } + +#if 0 +static const OT::BASE& _get_base (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::BASE); + return *hb_ot_face_data (face)->BASE; +} + +hb_bool_t +hb_ot_layout_get_baseline (hb_font_t *font, + hb_ot_layout_baseline_t baseline, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_position_t *coord /* OUT. May be NULL. */) +{ + const OT::BASE &base = _get_base (font->face); + bool result = base.get_baseline (font, baseline, direction, script_tag, + language_tag, coord); + + /* TODO: Simulate https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags#ideographic-em-box */ + if (!result && coord) *coord = 0; + + if (coord) *coord = font->em_scale_dir (*coord, direction); + + return result; +} + +/* To be moved to public header */ +/* + * BASE + */ + +/** + * hb_ot_layout_baseline_t: + * + * https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags + * + * Since: DONTREPLACEME + */ +typedef enum { + HB_OT_LAYOUT_BASELINE_HANG = HB_TAG('h','a','n','g'), + HB_OT_LAYOUT_BASELINE_ICFB = HB_TAG('i','c','f','b'), + HB_OT_LAYOUT_BASELINE_ICFT = HB_TAG('i','c','f','t'), + HB_OT_LAYOUT_BASELINE_IDEO = HB_TAG('i','d','e','o'), + HB_OT_LAYOUT_BASELINE_IDTB = HB_TAG('i','d','t','b'), + HB_OT_LAYOUT_BASELINE_MATH = HB_TAG('m','a','t','h'), + HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n') +} hb_ot_layout_baseline_t; + +HB_EXTERN hb_bool_t +hb_ot_layout_get_baseline (hb_font_t *font, + hb_ot_layout_baseline_t baseline, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_position_t *coord /* OUT. May be NULL. */); + +#endif diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 7a016c390..e47395412 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -391,22 +391,6 @@ hb_ot_layout_feature_get_characters (hb_face_t *face, unsigned int *char_count /* IN/OUT. May be NULL */, hb_codepoint_t *characters /* OUT. May be NULL */); -/* - * BASE - */ -#if 0 - -#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g') -#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b') -#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t') -#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o') -#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b') -#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h') -#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n') - -#endif - - HB_END_DECLS #endif /* HB_OT_LAYOUT_H */ diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh index 64b3d7480..b29f87c5a 100644 --- a/src/hb-ot-layout.hh +++ b/src/hb-ot-layout.hh @@ -34,6 +34,7 @@ #include "hb-font.hh" #include "hb-buffer.hh" #include "hb-open-type.hh" +#include "hb-ot-shape.hh" #include "hb-set-digest.hh" @@ -48,6 +49,7 @@ HB_INTERNAL const OT::GDEF& _get_gdef (hb_face_t *face); HB_INTERNAL const OT::GSUB& _get_gsub_relaxed (hb_face_t *face); HB_INTERNAL const OT::GPOS& _get_gpos_relaxed (hb_face_t *face); +struct hb_ot_shape_plan_t; /* * kern @@ -57,9 +59,9 @@ HB_INTERNAL hb_bool_t hb_ot_layout_has_kerning (hb_face_t *face); HB_INTERNAL void -hb_ot_layout_kern (hb_font_t *font, - hb_buffer_t *buffer, - hb_mask_t kern_mask); +hb_ot_layout_kern (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); /* Private API corresponding to hb-ot-layout.h: */ diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh index 9f67b5745..f1e785f19 100644 --- a/src/hb-ot-name-table.hh +++ b/src/hb-ot-name-table.hh @@ -257,7 +257,7 @@ struct name const void *pool; unsigned int pool_len; public: - const name *table; + hb_nonnull_ptr_t table; hb_vector_t names; }; diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc index e0c971087..f5ac18d79 100644 --- a/src/hb-ot-name.cc +++ b/src/hb-ot-name.cc @@ -52,7 +52,7 @@ _get_name (hb_face_t *face) /** * hb_ot_name_list_names: * @face: font face. - * @num_entries: (out): number of returned entries. + * @num_entries: (out) (allow-none): number of returned entries. * * Enumerates all available name IDs and language combinations. Returned * array is owned by the @face and should not be modified. It can be @@ -66,7 +66,7 @@ hb_ot_name_list_names (hb_face_t *face, unsigned int *num_entries /* OUT */) { const OT::name_accelerator_t &name = _get_name (face); - *num_entries = name.names.len; + if (num_entries) *num_entries = name.names.len; return name.names.arrayZ(); } diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh index 71d2bf59d..b2495128e 100644 --- a/src/hb-ot-os2-table.hh +++ b/src/hb-ot-os2-table.hh @@ -36,11 +36,11 @@ namespace OT { * OS/2 and Windows Metrics * https://docs.microsoft.com/en-us/typography/opentype/spec/os2 */ -#define HB_OT_TAG_os2 HB_TAG('O','S','/','2') +#define HB_OT_TAG_OS2 HB_TAG('O','S','/','2') -struct os2 +struct OS2 { - static const hb_tag_t tableTag = HB_OT_TAG_os2; + static const hb_tag_t tableTag = HB_OT_TAG_OS2; inline bool sanitize (hb_sanitize_context_t *c) const { @@ -50,12 +50,12 @@ struct os2 inline bool subset (hb_subset_plan_t *plan) const { - hb_blob_t *os2_blob = hb_sanitize_context_t().reference_table (plan->source); + hb_blob_t *os2_blob = hb_sanitize_context_t().reference_table (plan->source); hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1); // TODO(grieger): move to hb_blob_copy_writable_or_fail hb_blob_destroy (os2_blob); - os2 *os2_prime = (os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr); + OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr); if (unlikely (!os2_prime)) { hb_blob_destroy (os2_prime_blob); return false; @@ -67,7 +67,7 @@ struct os2 os2_prime->usLastCharIndex.set (max_cp); _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange); - bool result = plan->add_table (HB_OT_TAG_os2, os2_prime_blob); + bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob); hb_blob_destroy (os2_prime_blob); return result; diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh index bd049f9ab..b15a459b1 100644 --- a/src/hb-ot-post-table.hh +++ b/src/hb-ot-post-table.hh @@ -254,7 +254,7 @@ struct post private: hb_blob_t *blob; uint32_t version; - const ArrayOf *glyphNameIndex; + hb_nonnull_ptr_t > glyphNameIndex; hb_vector_t index_to_offset; const uint8_t *pool; hb_atomic_ptr_t gids_sorted_by_name; diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 4f98f7480..8933c1822 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1018,7 +1018,6 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, else buffer->next_glyph (); } - buffer->swap_buffers (); } diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc index 1142da3ec..497891ea0 100644 --- a/src/hb-ot-shape-complex-khmer.cc +++ b/src/hb-ot-shape-complex-khmer.cc @@ -414,7 +414,6 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, else buffer->next_glyph (); } - buffer->swap_buffers (); } diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index dcada261c..ca7b5a9b2 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -343,7 +343,6 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, else buffer->next_glyph (); } - buffer->swap_buffers (); } diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc index b687fe61e..650c9800a 100644 --- a/src/hb-ot-shape-complex-thai.cc +++ b/src/hb-ot-shape-complex-thai.cc @@ -357,8 +357,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan, buffer->merge_out_clusters (start - 1, end); } } - if (likely (buffer->successful)) - buffer->swap_buffers (); + buffer->swap_buffers (); /* If font has Thai GSUB, we are done. */ if (plan->props.script == HB_SCRIPT_THAI && !plan->map.found_script[0]) diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 3ab77fc58..af25b07f8 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -552,7 +552,6 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, else buffer->next_glyph (); } - buffer->swap_buffers (); } diff --git a/src/hb-ot-shape-complex-vowel-constraints.cc b/src/hb-ot-shape-complex-vowel-constraints.cc index 20af8711e..0e532581d 100644 --- a/src/hb-ot-shape-complex-vowel-constraints.cc +++ b/src/hb-ot-shape-complex-vowel-constraints.cc @@ -429,9 +429,8 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, if (processed) { if (buffer->idx < count) - buffer->next_glyph (); - if (likely (buffer->successful)) - buffer->swap_buffers (); + buffer->next_glyph (); + buffer->swap_buffers (); } } diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index c55d8dcb8..8c5e38e06 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -425,7 +425,6 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) buffer->output_info (info); while (buffer->idx < buffer->len && buffer->successful) buffer->next_glyph (); - buffer->swap_buffers (); } @@ -918,7 +917,7 @@ hb_ot_position (const hb_ot_shape_context_t *c) /* Visual fallback goes here. */ if (c->plan->apply_kern) - hb_ot_layout_kern (c->font, c->buffer, c->plan->kern_mask); + hb_ot_layout_kern (c->plan, c->font, c->buffer); else if (c->plan->fallback_kerning) _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); diff --git a/src/hb-set.hh b/src/hb-set.hh index 947e8d9d1..21a22525f 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -225,15 +225,17 @@ struct hb_set_t return true; } - inline void clear (void) { - if (unlikely (hb_object_is_inert (this))) + inline void clear (void) + { + if (unlikely (hb_object_is_immutable (this))) return; successful = true; population = 0; page_map.resize (0); pages.resize (0); } - inline bool is_empty (void) const { + inline bool is_empty (void) const + { unsigned int count = pages.len; for (unsigned int i = 0; i < count; i++) if (!pages[i].is_empty ()) diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index 4648cc757..8d002f8a7 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -343,7 +343,7 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, if (unlikely (!buffer->len)) return true; - assert (!hb_object_is_inert (buffer)); + assert (!hb_object_is_immutable (buffer)); assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); if (unlikely (hb_object_is_inert (shape_plan))) diff --git a/src/hb-static.cc b/src/hb-static.cc index e5507960d..3669e08b7 100644 --- a/src/hb-static.cc +++ b/src/hb-static.cc @@ -28,7 +28,6 @@ #include "hb-open-type.hh" #include "hb-ot-layout-common.hh" -#include "hb-aat-layout-ankr-table.hh" /* I don't even want to know why... */ #include "hb-aat-layout-common.hh" #include "hb-face.hh" diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 990dadf02..ff132f84e 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -174,8 +174,8 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_cmap: result = _subset (plan); break; - case HB_OT_TAG_os2: - result = _subset (plan); + case HB_OT_TAG_OS2: + result = _subset (plan); break; case HB_OT_TAG_post: result = _subset (plan); diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index 8cf7898a1..5accf3643 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -187,7 +187,6 @@ DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) = HB_OBJECT_HEADER_STATIC, nullptr, /* parent */ - true, /* immutable */ { #define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil, HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS @@ -303,12 +302,10 @@ hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, void hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs) { - if (unlikely (hb_object_is_inert (ufuncs))) - return; - if (ufuncs->immutable) + if (hb_object_is_immutable (ufuncs)) return; - ufuncs->immutable = true; + hb_object_make_immutable (ufuncs); } /** @@ -324,7 +321,7 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs) hb_bool_t hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs) { - return ufuncs->immutable; + return hb_object_is_immutable (ufuncs); } /** @@ -352,7 +349,7 @@ hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t *ufuncs, \ void *user_data, \ hb_destroy_func_t destroy) \ { \ - if (ufuncs->immutable) \ + if (hb_object_is_immutable (ufuncs)) \ return; \ \ if (ufuncs->destroy.name) \ diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh index 0b66ce8a1..d3fd5ea4b 100644 --- a/src/hb-unicode.hh +++ b/src/hb-unicode.hh @@ -66,8 +66,6 @@ struct hb_unicode_funcs_t hb_unicode_funcs_t *parent; - bool immutable; - #define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \ inline return_type name (hb_codepoint_t unicode) { return func.name (this, unicode, user_data.name); } HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE diff --git a/src/hb.hh b/src/hb.hh index fa6a7404d..e3faf17c9 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -365,10 +365,10 @@ static_assert ((sizeof (hb_var_int_t) == 4), ""); #else /* __cpluspplus >= 201103L */ #define HB_NO_COPY_ASSIGN(TypeName) -#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) -#define HB_NO_CREATE_COPY_ASSIGN(TypeName) -#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) -#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) +#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "") +#define HB_NO_CREATE_COPY_ASSIGN(TypeName) static_assert (true, "") +#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "") +#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "") #endif /* __cpluspplus >= 201103L */ diff --git a/test/api/Makefile.am b/test/api/Makefile.am index f7d61f3e2..089152781 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -28,6 +28,7 @@ check_PROGRAMS = $(TEST_PROGS) noinst_PROGRAMS = $(TEST_PROGS) TEST_PROGS = \ + test-baseline \ test-blob \ test-buffer \ test-collect-unicodes \ @@ -35,6 +36,7 @@ TEST_PROGS = \ test-font \ test-map \ test-object \ + test-ot-face \ test-set \ test-shape \ test-subset \ diff --git a/test/api/fonts/base.ttf b/test/api/fonts/base.ttf new file mode 100644 index 000000000..d98496683 Binary files /dev/null and b/test/api/fonts/base.ttf differ diff --git a/test/api/test-baseline.c b/test/api/test-baseline.c new file mode 100644 index 000000000..a120e14f3 --- /dev/null +++ b/test/api/test-baseline.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2018 Ebrahim Byagowi + * + * 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. + */ + +#include "hb-test.h" + +#include + +/* Unit tests for hb-ot-layout.h baseline */ + +static void +test_ot_layout_base (void) +{ + hb_face_t *face = hb_test_open_font_file ("fonts/base.ttf"); + hb_font_t *font = hb_font_create (face); + +#if 0 + hb_position_t position; + g_assert (hb_ot_layout_get_baseline (font, HB_OT_LAYOUT_BASELINE_ICFB, HB_DIRECTION_TTB, + HB_TAG ('h','a','n','i'), + HB_TAG ('E','N','G',' '), + &position)); + g_assert_cmpint (46, ==, position); +#endif + + hb_font_destroy (font); + hb_face_destroy (face); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_ot_layout_base); + + return hb_test_run(); +} diff --git a/test/api/test-font.c b/test/api/test-font.c index 3d81cf961..a92d8b26a 100644 --- a/test/api/test-font.c +++ b/test/api/test-font.c @@ -536,6 +536,11 @@ test_font_properties (void) g_assert_cmpint (x_ppem, ==, 17); g_assert_cmpint (y_ppem, ==, 19); + /* Check ptem */ + g_assert_cmpint (hb_font_get_ptem (font), ==, 0); + hb_font_set_ptem (font, 42); + g_assert_cmpint (hb_font_get_ptem (font), ==, 42); + /* Check immutable */ diff --git a/test/api/test-ot-face.c b/test/api/test-ot-face.c new file mode 100644 index 000000000..da23fe593 --- /dev/null +++ b/test/api/test-ot-face.c @@ -0,0 +1,119 @@ +/* + * Copyright © 2011 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 TEST_OT_FACE_NO_MAIN +#include "hb-test.h" +#endif +#include + +/* Unit tests for hb-ot-*.h */ + + +static void +test_face (hb_face_t *face) +{ + hb_font_t *font = hb_font_create (face); + hb_ot_font_set_funcs (font); + + hb_set_t *set = hb_set_create (); + hb_face_collect_unicodes (face, set); + hb_face_collect_variation_selectors (face, set); + hb_face_collect_variation_unicodes (face, 0, set); + + hb_codepoint_t g; + hb_position_t x, y; + hb_glyph_extents_t extents; + char buf[5] = {0}; + hb_font_get_nominal_glyph (font, 0, &g); + hb_font_get_variation_glyph (font, 0, 0, &g); + hb_font_get_glyph_h_advance (font, g); + hb_font_get_glyph_v_advance (font, g); + hb_font_get_glyph_h_origin (font, g, &x, &y); + hb_font_get_glyph_v_origin (font, g, &x, &y); + hb_font_get_glyph_extents (font, g, &extents); + hb_font_get_glyph_contour_point (font, g, 0, &x, &y); + hb_font_get_glyph_name (font, g, buf, sizeof (buf)); + hb_font_get_glyph_from_name (font, buf, strlen (buf), &g); + + hb_ot_color_has_palettes (face); + hb_ot_color_palette_get_count (face); + hb_ot_color_palette_get_name_id (face, 0); + hb_ot_color_palette_color_get_name_id (face, 0); + hb_ot_color_palette_get_flags (face, 0); + hb_ot_color_palette_get_colors (face, 0, 0, NULL, NULL); + hb_ot_color_has_layers (face); + hb_ot_color_glyph_get_layers (face, 0, 0, NULL, NULL); + hb_ot_color_has_svg (face); + hb_blob_destroy (hb_ot_color_glyph_reference_svg (face, 0)); + hb_ot_color_has_png (face); + hb_blob_destroy (hb_ot_color_glyph_reference_png (font, 0)); + + hb_ot_layout_has_glyph_classes (face); + hb_ot_layout_has_substitution (face); + hb_ot_layout_has_positioning (face); + + hb_ot_math_has_data (face); + hb_ot_math_get_constant (font, HB_OT_MATH_CONSTANT_MATH_LEADING); + hb_ot_math_get_glyph_italics_correction (font, 0); + hb_ot_math_get_glyph_top_accent_attachment (font, 0); + hb_ot_math_is_glyph_extended_shape (face, 0); + hb_ot_math_get_glyph_kerning (font, 0, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0); + hb_ot_math_get_glyph_variants (font, 0, HB_DIRECTION_TTB, 0, NULL, NULL); + hb_ot_math_get_min_connector_overlap (font, HB_DIRECTION_RTL); + hb_ot_math_get_glyph_assembly (font, 0, HB_DIRECTION_BTT, 0, NULL, NULL, NULL); + + unsigned int len = sizeof (buf); + hb_ot_name_list_names (face, NULL); + hb_ot_name_get_utf8 (face, 0, NULL, &len, buf); + hb_ot_name_get_utf16 (face, 0, NULL, NULL, NULL); + hb_ot_name_get_utf32 (face, 0, NULL, NULL, NULL); + + hb_ot_var_get_axis_count (face); + hb_ot_var_get_axes (face, 0, NULL, NULL); + hb_ot_var_normalize_variations (face, NULL, 0, NULL, 0); + hb_ot_var_normalize_coords (face, 0, NULL, NULL); + + hb_set_destroy (set); + hb_font_destroy (font); +} + +#ifndef TEST_OT_FACE_NO_MAIN +static void +test_ot_face_empty (void) +{ + test_face (hb_face_get_empty ()); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_ot_face_empty); + + return hb_test_run(); +} +#endif diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5735679418433536 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5735679418433536 new file mode 100644 index 000000000..ff6ef6e2b Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5735679418433536 differ diff --git a/test/fuzzing/hb-shape-fuzzer.cc b/test/fuzzing/hb-shape-fuzzer.cc index e8bc186b1..fedf56e20 100644 --- a/test/fuzzing/hb-shape-fuzzer.cc +++ b/test/fuzzing/hb-shape-fuzzer.cc @@ -3,6 +3,10 @@ #include #include +#define TEST_OT_FACE_NO_MAIN 1 +#include "../api/test-ot-face.c" +#undef TEST_OT_FACE_NO_MAIN + extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { hb_blob_t *blob = hb_blob_create ((const char *)data, size, @@ -48,6 +52,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) hb_buffer_destroy (buffer); } + /* Misc calls on face. */ + test_face (face); hb_font_destroy (font); hb_face_destroy (face);