diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 2ee14a96410478cdd98eae8ca4a7dd40fa04d5a5..4cb8d42bed3866e84c72dc4577b9a0b4d0dbbc43 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -237,6 +237,7 @@ hb_font_funcs_set_glyph_v_advance_func hb_font_funcs_set_glyph_v_advances_func hb_font_funcs_set_glyph_v_origin_func hb_font_funcs_set_nominal_glyph_func +hb_font_funcs_set_nominal_glyphs_func hb_font_funcs_set_user_data hb_font_funcs_set_variation_glyph_func hb_font_funcs_t @@ -273,6 +274,8 @@ hb_font_get_glyph_v_origin hb_font_get_glyph_v_origin_func_t hb_font_get_nominal_glyph hb_font_get_nominal_glyph_func_t +hb_font_get_nominal_glyphs +hb_font_get_nominal_glyphs_func_t hb_font_get_parent hb_font_get_ppem hb_font_get_ptem diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index d6e597a408fb3e71e9608acf545df1d8d4c7b3f1..5845ab5167765d8191d60409f5f2e50a73b47b46 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -518,6 +518,7 @@ struct hb_aat_apply_context_t : static return_t default_return_value (void) { return false; } bool stop_sublookup_iteration (return_t r) const { return r; } + hb_ot_shape_plan_t *plan; hb_font_t *font; hb_face_t *face; hb_buffer_t *buffer; @@ -527,15 +528,17 @@ struct hb_aat_apply_context_t : unsigned int lookup_index; unsigned int debug_depth; - inline hb_aat_apply_context_t (hb_font_t *font_, + inline hb_aat_apply_context_t (hb_ot_shape_plan_t *plan_, + hb_font_t *font_, hb_buffer_t *buffer_, hb_blob_t *table) : - font (font_), face (font->face), buffer (buffer_), + plan (plan_), font (font_), face (font->face), buffer (buffer_), sanitizer (), lookup_index (0), debug_depth (0) { sanitizer.init (table); sanitizer.set_num_glyphs (face->get_num_glyphs ()); sanitizer.start_processing (); + sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX); } inline void set_lookup_index (unsigned int i) { lookup_index = i; } diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 49d188c3654f34d733dfac4ee48dcd4d53827a8d..e5934c39fe28071fcb83815e9373afba538a6dd9 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -59,7 +59,9 @@ struct KerxSubTableFormat0 { TRACE_APPLY (this); - /* TODO */ + hb_kern_machine_t machine (*this); + + machine.kern (c->font, c->buffer, c->plan->kern_mask); return_trace (true); } @@ -110,11 +112,9 @@ struct KerxSubTableFormat2 unsigned int l = *(this+leftClassTable).get_value (left, num_glyphs); unsigned int r = *(this+rightClassTable).get_value (right, num_glyphs); unsigned int offset = l + r; - const FWORD *arr = &(this+array); - if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end)) - return 0; - const FWORD *v = &StructAtOffset (arr, offset); - if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end)) + const FWORD *v = &StructAtOffset (&(this+array), offset); + if (unlikely ((const char *) v < (const char *) &array || + (const char *) v > (const char *) end - 2)) return 0; return *v; } @@ -123,7 +123,11 @@ struct KerxSubTableFormat2 { TRACE_APPLY (this); - /* TODO */ + accelerator_t accel (*this, + c->sanitizer.end, + c->face->get_num_glyphs ()); + hb_kern_machine_t machine (accel); + machine.kern (c->font, c->buffer, c->plan->kern_mask); return_trace (true); } @@ -138,6 +142,22 @@ struct KerxSubTableFormat2 array.sanitize (c, this))); } + struct accelerator_t + { + const KerxSubTableFormat2 &table; + const char *end; + unsigned int num_glyphs; + + inline accelerator_t (const KerxSubTableFormat2 &table_, + const char *end_, unsigned int num_glyphs_) + : table (table_), end (end_), num_glyphs (num_glyphs_) {} + + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { + return table.get_kerning (left, right, end, num_glyphs); + } + }; + protected: HBUINT32 rowWidth; /* The width, in bytes, of a row in the table. */ LOffsetTo > @@ -222,7 +242,7 @@ struct KerxTable Vertical = 0x80000000, /* Set if table has vertical kerning values. */ CrossStream = 0x40000000, /* Set if table has cross-stream kerning values. */ Variation = 0x20000000, /* Set if table has variation kerning values. */ - ProcessDirection = 0x10000000, /* If clear, process the glyphs forwards, that + Backwards = 0x10000000, /* If clear, process the glyphs forwards, that * is, from first to last in the glyph stream. * If we, process them from last to first. * This flag only applies to state-table based @@ -272,22 +292,6 @@ public: DEFINE_SIZE_MIN (12); }; -struct SubtableXXX -{ - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); - } - - protected: - HBUINT32 length; - HBUINT32 coverage; - HBUINT32 tupleCount; - public: - DEFINE_SIZE_STATIC (12); -}; - /* * The 'kerx' Table @@ -313,9 +317,9 @@ struct kerx goto skip; if (table->coverage & KerxTable::CrossStream) - goto skip; /* We do NOT handle cross-stream kerning. */ + goto skip; /* We do NOT handle cross-stream kerning. None of Apple fonts use it. */ - reverse = bool (table->coverage & KerxTable::ProcessDirection) != + reverse = bool (table->coverage & KerxTable::Backwards) != HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); if (!c->buffer->message (c->font, "start kerx subtable %d", c->lookup_index)) @@ -324,7 +328,12 @@ struct kerx if (reverse) c->buffer->reverse (); - /* XXX Reverse-kern is not working yet... */ + c->sanitizer.set_object (*table); + + /* XXX Reverse-kern is not working yet... + * hb_kern_machine_t would need to know that it's reverse-kerning. + * Or better yet, make it work in reverse as well, so we don't have + * to reverse and reverse back? */ table->dispatch (c); if (reverse) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index cf08d796194410cad516dea0c690044a38b1193b..0020750ce5631734d7284bb5b59142c9228660bb 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -752,7 +752,7 @@ struct ChainSubtable Vertical = 0x80000000, /* If set, this subtable will only be applied * to vertical text. If clear, this subtable * will only be applied to horizontal text. */ - Descending = 0x40000000, /* If set, this subtable will process glyphs + Backwards = 0x40000000, /* If set, this subtable will process glyphs * in descending order. If clear, it will * process the glyphs in ascending order. */ AllDirections = 0x20000000, /* If set, this subtable will be applied to @@ -876,8 +876,8 @@ struct Chain may be right-to-left or left-to-right). */ reverse = subtable->coverage & ChainSubtable::Logical ? - bool (subtable->coverage & ChainSubtable::Descending) : - bool (subtable->coverage & ChainSubtable::Descending) != + bool (subtable->coverage & ChainSubtable::Backwards) : + bool (subtable->coverage & ChainSubtable::Backwards) != HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index)) @@ -886,6 +886,8 @@ struct Chain if (reverse) c->buffer->reverse (); + c->sanitizer.set_object (*subtable); + subtable->dispatch (c); if (reverse) diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index faf418d6ef5ad981bdf937f3a7d30bf7c8dee3d9..71932e7988abb356e58ceaa764c8fd2ece65793c 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -62,17 +62,21 @@ hb_aat_layout_has_substitution (hb_face_t *face) } void -hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer) +hb_aat_layout_substitute (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { hb_blob_t *blob; const AAT::morx& morx = _get_morx (font->face, &blob); - AAT::hb_aat_apply_context_t c (font, buffer, blob); + AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); morx.apply (&c); } void -hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer) +hb_aat_layout_position (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { #if 0 hb_blob_t *blob; diff --git a/src/hb-aat-layout.hh b/src/hb-aat-layout.hh index 553832f1e002ea9ae0c83a3d1e915f565eac7671..8b12833d9cda16551cb48311826204eeb196daa0 100644 --- a/src/hb-aat-layout.hh +++ b/src/hb-aat-layout.hh @@ -29,17 +29,19 @@ #include "hb.hh" -#include "hb-font.hh" -#include "hb-buffer.hh" -#include "hb-open-type.hh" +#include "hb-ot-shape.hh" HB_INTERNAL hb_bool_t hb_aat_layout_has_substitution (hb_face_t *face); HB_INTERNAL void -hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer); +hb_aat_layout_substitute (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); HB_INTERNAL void -hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer); +hb_aat_layout_position (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); #endif /* HB_AAT_LAYOUT_HH */ diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh index 9126822eb77a75c0efd4738476a87ad35573c49e..9628ddae0308f1e48231231d8a90f2429e01d2b9 100644 --- a/src/hb-buffer.hh +++ b/src/hb-buffer.hh @@ -260,7 +260,8 @@ struct hb_buffer_t { if (have_output) { - if (unlikely (out_info != info || out_len != idx)) { + if (out_info != info || out_len != idx) + { if (unlikely (!make_room_for (1, 1))) return; out_info[out_len] = info[idx]; } @@ -269,6 +270,23 @@ struct hb_buffer_t idx++; } + /* Copies n glyphs at idx to output and advance idx. + * If there's no output, just advance idx. */ + inline void + next_glyphs (unsigned int n) + { + if (have_output) + { + if (out_info != info || out_len != idx) + { + if (unlikely (!make_room_for (n, n))) return; + memmove (out_info + out_len, info + idx, n * sizeof (out_info[0])); + } + out_len += n; + } + + idx += n; + } /* Advance idx without copying to output. */ inline void skip_glyph (void) { diff --git a/src/hb-font.cc b/src/hb-font.cc index fa5e6614b57eb29e4a71e9bdf815883c00123110..fd0e097a8dac7dc42cc8c00151663c3b2c00d677 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -31,6 +31,8 @@ #include "hb-font.hh" #include "hb-machinery.hh" +#include "hb-ot.h" + /* * hb_font_funcs_t @@ -101,9 +103,42 @@ hb_font_get_nominal_glyph_default (hb_font_t *font, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { + if (font->has_nominal_glyphs_func ()) + { + return font->get_nominal_glyphs (1, &unicode, 0, glyph, 0); + } return font->parent->get_nominal_glyph (unicode, glyph); } +#define hb_font_get_nominal_glyphs_nil hb_font_get_nominal_glyphs_default +static unsigned int +hb_font_get_nominal_glyphs_default (hb_font_t *font, + void *font_data HB_UNUSED, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + void *user_data HB_UNUSED) +{ + if (font->has_nominal_glyph_func ()) + { + for (unsigned int i = 0; i < count; i++) + { + if (!font->get_nominal_glyph (*first_unicode, first_glyph)) + return i; + + first_unicode = &StructAtOffset (first_unicode, unicode_stride); + first_glyph = &StructAtOffset (first_glyph, glyph_stride); + } + return count; + } + + return font->parent->get_nominal_glyphs (count, + first_unicode, unicode_stride, + first_glyph, glyph_stride); +} + static hb_bool_t hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, @@ -807,7 +842,7 @@ hb_font_get_glyph_v_advance (hb_font_t *font, **/ void hb_font_get_glyph_h_advances (hb_font_t* font, - unsigned count, + unsigned int count, const hb_codepoint_t *first_glyph, unsigned glyph_stride, hb_position_t *first_advance, @@ -825,7 +860,7 @@ hb_font_get_glyph_h_advances (hb_font_t* font, **/ void hb_font_get_glyph_v_advances (hb_font_t* font, - unsigned count, + unsigned int count, const hb_codepoint_t *first_glyph, unsigned glyph_stride, hb_position_t *first_advance, @@ -1052,7 +1087,7 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font, HB_EXTERN void hb_font_get_glyph_advances_for_direction (hb_font_t* font, hb_direction_t direction, - unsigned count, + unsigned int count, const hb_codepoint_t *first_glyph, unsigned glyph_stride, hb_position_t *first_advance, @@ -1271,18 +1306,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) = }; -/** - * hb_font_create: (Xconstructor) - * @face: a face. - * - * - * - * Return value: (transfer full): - * - * Since: 0.9.2 - **/ -hb_font_t * -hb_font_create (hb_face_t *face) +static hb_font_t * +_hb_font_create (hb_face_t *face) { hb_font_t *font; @@ -1301,6 +1326,27 @@ hb_font_create (hb_face_t *face) return font; } +/** + * hb_font_create: (Xconstructor) + * @face: a face. + * + * + * + * Return value: (transfer full): + * + * Since: 0.9.2 + **/ +hb_font_t * +hb_font_create (hb_face_t *face) +{ + hb_font_t *font = _hb_font_create (face); + + /* Install our in-house, very lightweight, funcs. */ + hb_ot_font_set_funcs (font); + + return font; +} + /** * hb_font_create_sub_font: * @parent: parent font. @@ -1317,7 +1363,7 @@ hb_font_create_sub_font (hb_font_t *parent) if (unlikely (!parent)) parent = hb_font_get_empty (); - hb_font_t *font = hb_font_create (parent->face); + hb_font_t *font = _hb_font_create (parent->face); if (unlikely (hb_object_is_inert (font))) return font; diff --git a/src/hb-font.h b/src/hb-font.h index 48450e99dfdd13a105c3bbe0c2a3cad1fbe7ba39..dc88f26c3e0f5c2f6e6b42dd1b91f81d7a9c4c86 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -125,6 +125,14 @@ typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void * hb_codepoint_t *glyph, void *user_data); +typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void *font_data, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + void *user_data); + typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t glyph, @@ -133,7 +141,7 @@ typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t; typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t; typedef void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data, - unsigned count, + unsigned int count, const hb_codepoint_t *first_glyph, unsigned glyph_stride, hb_position_t *first_advance, @@ -220,6 +228,22 @@ hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs, hb_font_get_nominal_glyph_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_nominal_glyphs_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: REPLACEME + **/ +HB_EXTERN void +hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs, + hb_font_get_nominal_glyphs_func_t func, + void *user_data, hb_destroy_func_t destroy); + /** * hb_font_funcs_set_variation_glyph_func: * @ffuncs: font functions. @@ -423,14 +447,14 @@ hb_font_get_glyph_v_advance (hb_font_t *font, HB_EXTERN void hb_font_get_glyph_h_advances (hb_font_t* font, - unsigned count, + unsigned int count, const hb_codepoint_t *first_glyph, unsigned glyph_stride, hb_position_t *first_advance, unsigned advance_stride); HB_EXTERN void hb_font_get_glyph_v_advances (hb_font_t* font, - unsigned count, + unsigned int count, const hb_codepoint_t *first_glyph, unsigned glyph_stride, hb_position_t *first_advance, @@ -486,7 +510,7 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font, HB_EXTERN void hb_font_get_glyph_advances_for_direction (hb_font_t* font, hb_direction_t direction, - unsigned count, + unsigned int count, const hb_codepoint_t *first_glyph, unsigned glyph_stride, hb_position_t *first_advance, diff --git a/src/hb-font.hh b/src/hb-font.hh index 47f5261e81ef3af89c0eb3b6bf0436f9f08009e6..e10d56745fc9437f87dc54f631d5c8245b827032 100644 --- a/src/hb-font.hh +++ b/src/hb-font.hh @@ -43,6 +43,7 @@ HB_FONT_FUNC_IMPLEMENT (font_h_extents) \ HB_FONT_FUNC_IMPLEMENT (font_v_extents) \ HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \ + HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \ HB_FONT_FUNC_IMPLEMENT (variation_glyph) \ HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ @@ -212,6 +213,18 @@ struct hb_font_t unicode, glyph, klass->user_data.nominal_glyph); } + inline unsigned int get_nominal_glyphs (unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride) + { + return klass->get.f.nominal_glyphs (this, user_data, + count, + first_unicode, unicode_stride, + first_glyph, glyph_stride, + klass->user_data.nominal_glyphs); + } inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph) @@ -377,7 +390,7 @@ struct hb_font_t *y = get_glyph_v_advance (glyph); } inline void get_glyph_advances_for_direction (hb_direction_t direction, - unsigned count, + unsigned int count, const hb_codepoint_t *first_glyph, unsigned glyph_stride, hb_position_t *first_advance, diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 79ce8f49ad978a71327aad07966188f765477107..18fb72a73cf64ecf87b2645b371f914931a039c2 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -45,26 +45,22 @@ * In general, this file does a fine job of what it's supposed to do. * There are, however, things that need more work: * - * - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy. - * Have not investigated. - * * - FreeType works in 26.6 mode. Clients can decide to use that mode, and everything * would work fine. However, we also abuse this API for performing in font-space, * but don't pass the correct flags to FreeType. We just abuse the no-hinting mode * for that, such that no rounding etc happens. As such, we don't set ppem, and * pass NO_HINTING as load_flags. Would be much better to use NO_SCALE, and scale - * ourselves, like we do in uniscribe, etc. + * ourselves. * * - We don't handle / allow for emboldening / obliqueing. * * - In the future, we should add constructors to create fonts in font space? - * - * - FT_Load_Glyph() is extremely costly. Do something about it? */ struct hb_ft_font_t { + mutable hb_mutex_t lock; FT_Face ft_face; int load_flags; bool symbol; /* Whether selected cmap is symbol cmap. */ @@ -82,6 +78,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) if (unlikely (!ft_font)) return nullptr; + ft_font->lock.init (); ft_font->ft_face = ft_face; ft_font->symbol = symbol; ft_font->unref = unref; @@ -110,6 +107,8 @@ _hb_ft_font_destroy (void *data) if (ft_font->unref) _hb_ft_face_destroy (ft_font->ft_face); + ft_font->lock.fini (); + free (ft_font); } @@ -177,6 +176,7 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode); if (unlikely (!g)) @@ -200,6 +200,32 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, return true; } +static unsigned int +hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED, + void *font_data, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + void *user_data HB_UNUSED) +{ + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); + unsigned int done; + for (done = 0; + done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode)); + done++) + { + first_unicode = &StructAtOffset (first_unicode, unicode_stride); + first_glyph = &StructAtOffset (first_glyph, glyph_stride); + } + /* We don't need to do ft_font->symbol dance here, since HB calls the singular + * nominal_glyph() for what we don't handle here. */ + return done; +} + + static hb_bool_t hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED, void *font_data, @@ -209,6 +235,7 @@ hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector); if (unlikely (!g)) @@ -228,6 +255,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; int load_flags = ft_font->load_flags; int mult = font->x_scale < 0 ? -1 : +1; @@ -265,6 +293,7 @@ hb_ft_get_glyph_v_advance (hb_font_t *font, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Fixed v; if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v))) @@ -287,6 +316,7 @@ hb_ft_get_glyph_v_origin (hb_font_t *font, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) @@ -313,6 +343,7 @@ hb_ft_get_glyph_extents (hb_font_t *font, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) @@ -345,6 +376,7 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) @@ -370,8 +402,10 @@ hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); + FT_Face ft_face = ft_font->ft_face; - hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size); + hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size); if (ret && (size && !*name)) ret = false; @@ -386,6 +420,7 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (len < 0) @@ -418,6 +453,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; metrics->ascender = ft_face->size->metrics.ascender; metrics->descender = ft_face->size->metrics.descender; @@ -444,6 +480,7 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t @@ -252,6 +255,16 @@ struct hb_sanitize_context_t : } inline unsigned int get_num_glyphs (void) { return num_glyphs; } + inline void set_max_ops (int max_ops_) { max_ops = max_ops_; } + + template + inline void set_object (const T& obj) + { + this->start = (const char *) &obj; + this->end = (const char *) &obj + obj.get_size (); + assert (this->start <= this->end); /* Must not overflow. */ + } + inline void start_processing (void) { this->start = this->blob->data; diff --git a/src/hb-mutex.hh b/src/hb-mutex.hh index d8cdf4b64ac6f3db24e6d88ae8646355cb1f7f39..75b89addb9a993c8ba3d67902f59e0833c3126cc 100644 --- a/src/hb-mutex.hh +++ b/src/hb-mutex.hh @@ -137,5 +137,13 @@ struct hb_mutex_t inline void fini (void) { hb_mutex_impl_finish (&m); } }; +struct hb_lock_t +{ + inline hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); } + inline ~hb_lock_t (void) { mutex.unlock (); } + private: + hb_mutex_t &mutex; +}; + #endif /* HB_MUTEX_HH */ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index d1da822ae212a5eac85e4a6bd771b32cf693e1f7..5fa9d3f7e5d35d020ef794082c90a0dc842cee36 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -50,7 +50,30 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; - return ot_face->cmap.get_relaxed()->get_nominal_glyph (unicode, glyph); + return ot_face->cmap.get ()->get_nominal_glyph (unicode, glyph); +} + +static unsigned int +hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED, + void *font_data, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + void *user_data HB_UNUSED) +{ + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + const OT::cmap_accelerator_t &cmap = *ot_face->cmap.get (); + unsigned int done; + for (done = 0; + done < count && cmap.get_nominal_glyph (*first_unicode, first_glyph); + done++) + { + first_unicode = &StructAtOffset (first_unicode, unicode_stride); + first_glyph = &StructAtOffset (first_glyph, glyph_stride); + } + return done; } static hb_bool_t @@ -62,7 +85,7 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; - return ot_face->cmap.get_relaxed ()->get_variation_glyph (unicode, variation_selector, glyph); + return ot_face->cmap.get ()->get_variation_glyph (unicode, variation_selector, glyph); } static void @@ -195,6 +218,7 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_tface))) return; hb_ot_face_data_t *ot_face = hb_ot_face_data (font->face); - /* Load them lazy. We access it with get_relaxed() for performance. */ - ot_face->cmap.get (); - hb_font_set_funcs (font, _hb_ot_get_font_funcs (), ot_face, diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh index 0ab9322f50ebb9e10e0504553d1181535ea2c778..ccb666e8c7a9779488dd9e91f944adda9418a787 100644 --- a/src/hb-ot-kern-table.hh +++ b/src/hb-ot-kern-table.hh @@ -194,11 +194,9 @@ struct KernSubTableFormat2 unsigned int l = (this+leftClassTable).get_class (left); unsigned int r = (this+rightClassTable).get_class (right); unsigned int offset = l + r; - const FWORD *arr = &(this+array); - if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end)) - return 0; - const FWORD *v = &StructAtOffset (arr, offset); - if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end)) + const FWORD *v = &StructAtOffset (&(this+array), offset); + if (unlikely ((const char *) v < (const char *) &array || + (const char *) v > (const char *) end - 2)) return 0; return *v; } @@ -283,7 +281,7 @@ struct KernSubTableWrapper TRACE_SANITIZE (this); return_trace (c->check_struct (thiz()) && thiz()->length >= T::min_size && - c->check_array (thiz(), thiz()->length, 1) && + c->check_range (thiz(), thiz()->length) && thiz()->subtable.sanitize (c, thiz()->format)); } }; @@ -294,7 +292,7 @@ struct KernTable /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ inline const T* thiz (void) const { return static_cast (this); } - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const { int v = 0; const typename T::SubTableWrapper *st = CastP (&thiz()->dataZ); @@ -303,7 +301,7 @@ struct KernTable { if (st->is_override ()) v = 0; - v += st->get_h_kerning (left, right, table_length + (const char *) this); + v += st->get_h_kerning (left, right, st->length + (const char *) st); st = &StructAfter (*st); } return v; @@ -337,6 +335,7 @@ struct KernOT : KernTable struct SubTableWrapper : KernSubTableWrapper { + friend struct KernTable; friend struct KernSubTableWrapper; enum Coverage @@ -378,6 +377,7 @@ struct KernAAT : KernTable struct SubTableWrapper : KernSubTableWrapper { + friend struct KernTable; friend struct KernSubTableWrapper; enum Coverage @@ -418,11 +418,11 @@ struct kern inline bool has_data (void) const { return u.version32 != 0; } - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const { switch (u.major) { - case 0: return u.ot.get_h_kerning (left, right, table_length); - case 1: return u.aat.get_h_kerning (left, right, table_length); + case 0: return u.ot.get_h_kerning (left, right); + case 1: return u.aat.get_h_kerning (left, right); default:return 0; } } @@ -430,7 +430,7 @@ struct kern inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!u.major.sanitize (c)) return_trace (false); + if (!u.version32.sanitize (c)) return_trace (false); switch (u.major) { case 0: return_trace (u.ot.sanitize (c)); case 1: return_trace (u.aat.sanitize (c)); @@ -444,7 +444,6 @@ struct kern { blob = hb_sanitize_context_t().reference_table (face); table = blob->as (); - table_length = blob->length; } inline void fini (void) { @@ -455,7 +454,7 @@ struct kern { 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, table_length); } + { 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); } @@ -464,6 +463,7 @@ struct kern 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; @@ -475,18 +475,17 @@ struct kern private: hb_blob_t *blob; const kern *table; - unsigned int table_length; }; protected: union { - HBUINT16 major; HBUINT32 version32; + HBUINT16 major; KernOT ot; KernAAT aat; } u; public: - DEFINE_SIZE_UNION (2, major); + DEFINE_SIZE_UNION (4, version32); }; struct kern_accelerator_t : kern::accelerator_t {}; diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 2cdd7ba8aad2d25f001cb340fb492be96428ad5c..0e011e252326f075a252eabfe17c4d000d433ca4 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -599,7 +599,7 @@ postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); } -/* https://unicode.org/reports/tr53/tr53-1.pdf */ +/* http://www.unicode.org/reports/tr53/ */ static hb_codepoint_t modifier_combining_marks[] = diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 0e13707ed13c9f2018608aabb968a9c3c11fc3a7..a8229a98d944bf7c246aa1a80afdeb072b0b5b74 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -264,15 +264,6 @@ decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned decompose_current_character (c, short_circuit); } -static inline void -decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit) -{ - if (likely (c->buffer->idx + 1 == end)) - decompose_current_character (c, might_short_circuit); - else - decompose_multi_char_cluster (c, end, always_short_circuit); -} - static int compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) @@ -328,45 +319,80 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, /* First round, decompose */ - buffer->clear_output (); - count = buffer->len; - for (buffer->idx = 0; buffer->idx < count && buffer->successful;) + bool all_simple = true; { - unsigned int end; - for (end = buffer->idx + 1; end < count; end++) - if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))) - break; + buffer->clear_output (); + count = buffer->len; + buffer->idx = 0; + do + { + unsigned int end; + for (end = buffer->idx + 1; end < count; end++) + if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))) + break; + + if (end < count) + end--; /* Leave one base for the marks to cluster with. */ + + /* From idx to end are simple clusters. */ + if (might_short_circuit) + { + unsigned int done = font->get_nominal_glyphs (end - buffer->idx, + &buffer->cur().codepoint, + sizeof (buffer->info[0]), + &buffer->cur().glyph_index(), + sizeof (buffer->info[0])); + buffer->next_glyphs (done); + } + while (buffer->idx < end && buffer->successful) + decompose_current_character (&c, might_short_circuit); + + if (buffer->idx == count || !buffer->successful) + break; - decompose_cluster (&c, end, might_short_circuit, always_short_circuit); + all_simple = false; + + /* Find all the marks now. */ + for (end = buffer->idx + 1; end < count; end++) + if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))) + break; + + /* idx to end is one non-simple cluster. */ + decompose_multi_char_cluster (&c, end, always_short_circuit); + } + while (buffer->idx < count && buffer->successful); + buffer->swap_buffers (); } - buffer->swap_buffers (); /* Second round, reorder (inplace) */ - count = buffer->len; - for (unsigned int i = 0; i < count; i++) + if (!all_simple) { - if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) - continue; + count = buffer->len; + for (unsigned int i = 0; i < count; i++) + { + if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) + continue; + + unsigned int end; + for (end = i + 1; end < count; end++) + if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) + break; + + /* We are going to do a O(n^2). Only do this if the sequence is short. */ + if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) { + i = end; + continue; + } + + buffer->sort (i, end, compare_combining_class); - unsigned int end; - for (end = i + 1; end < count; end++) - if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) - break; + if (plan->shaper->reorder_marks) + plan->shaper->reorder_marks (plan, buffer, i, end); - /* We are going to do a O(n^2). Only do this if the sequence is short. */ - if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) { i = end; - continue; } - - buffer->sort (i, end, compare_combining_class); - - if (plan->shaper->reorder_marks) - plan->shaper->reorder_marks (plan, buffer, i, end); - - i = end; } if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ) { @@ -385,8 +411,9 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, /* Third round, recompose */ - if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS || - mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT) + if (!all_simple && + (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS || + mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT)) { /* As noted in the comment earlier, we don't try to combine * ccc=0 chars with their previous Starter. */ diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index a9c0844e8e77dd604329f9d81d0149f8484deb66..6753ceb29418d86d7348042bd99eef6de29adeb4 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -668,7 +668,7 @@ hb_ot_substitute_complex (const hb_ot_shape_context_t *c) hb_synthesize_glyph_classes (c); if (unlikely (c->plan->apply_morx)) - hb_aat_layout_substitute (c->font, c->buffer); + hb_aat_layout_substitute (c->plan, c->font, c->buffer); else c->plan->substitute (c->font, buffer); } diff --git a/test/api/test-multithread.c b/test/api/test-multithread.c index 58a637cae3c86d6b7341fa10aeec33b8cda4805b..779b762dc93b4994696a1a650cc1c035a0186dce 100644 --- a/test/api/test-multithread.c +++ b/test/api/test-multithread.c @@ -34,8 +34,8 @@ #include #include -static char *font_path = "fonts/Inconsolata-Regular.abc.ttf"; -static char *text = "abc"; +static const char *font_path = "fonts/Inconsolata-Regular.abc.ttf"; +static const char *text = "abc"; static int num_threads = 30; static int num_iters = 200; @@ -164,11 +164,8 @@ main (int argc, char **argv) test_body (); - /* hb-font backed by FreeType functions can only be used from - * one thread at a time, because that's FT_Face's MT guarantee. - * So, disable this, even though it works "most of the time". */ - //hb_ft_font_set_funcs (font); - //test_body (); + hb_ft_font_set_funcs (font); + test_body (); hb_buffer_destroy (ref_buffer);