diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 5f10ecb7e..178ba6546 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -46,14 +46,28 @@ struct SingleSubstFormat1 bool intersects (const hb_set_t *glyphs) const { return (this+coverage).intersects (glyphs); } + bool may_have_non_1to1 () const + { return false; } + void closure (hb_closure_context_t *c) const { unsigned d = deltaGlyphID; + hb_set_t *active_parent_glyphs; + + if (c->active_glyphs_stack.length >= 1) + { + active_parent_glyphs = c->parent_active_glyphs (); + } else + { + active_parent_glyphs = c->glyphs; + } + + hb_iter (this+coverage) - | hb_filter (*c->glyphs) + | hb_filter (active_parent_glyphs) | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) | hb_sink (c->output) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -147,13 +161,27 @@ struct SingleSubstFormat2 bool intersects (const hb_set_t *glyphs) const { return (this+coverage).intersects (glyphs); } + bool may_have_non_1to1 () const + { return false; } + void closure (hb_closure_context_t *c) const { + hb_set_t *active_parent_glyphs; + + if (c->active_glyphs_stack.length >= 1) + { + active_parent_glyphs = c->parent_active_glyphs (); + } else + { + active_parent_glyphs = c->glyphs; + } + + hb_zip (this+coverage, substitute) - | hb_filter (*c->glyphs, hb_first) + | hb_filter (active_parent_glyphs, hb_first) | hb_map (hb_second) | hb_sink (c->output) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -388,14 +416,28 @@ struct MultipleSubstFormat1 bool intersects (const hb_set_t *glyphs) const { return (this+coverage).intersects (glyphs); } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { + hb_set_t *active_parent_glyphs; + + if (c->active_glyphs_stack.length >= 1) + { + active_parent_glyphs = c->parent_active_glyphs (); + } else + { + active_parent_glyphs = c->glyphs; + } + + hb_zip (this+coverage, sequence) - | hb_filter (*c->glyphs, hb_first) + | hb_filter (active_parent_glyphs, hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) | hb_apply ([c] (const Sequence &_) { _.closure (c); }) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -615,14 +657,28 @@ struct AlternateSubstFormat1 bool intersects (const hb_set_t *glyphs) const { return (this+coverage).intersects (glyphs); } + bool may_have_non_1to1 () const + { return false; } + void closure (hb_closure_context_t *c) const { + hb_set_t *active_parent_glyphs; + + if (c->active_glyphs_stack.length >= 1) + { + active_parent_glyphs = c->parent_active_glyphs (); + } else + { + active_parent_glyphs = c->glyphs; + } + + hb_zip (this+coverage, alternateSet) - | hb_filter (c->glyphs, hb_first) + | hb_filter (active_parent_glyphs, hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) | hb_apply ([c] (const AlternateSet &_) { _.closure (c); }) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -986,14 +1042,28 @@ struct LigatureSubstFormat1 ; } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { + hb_set_t *active_parent_glyphs; + + if (c->active_glyphs_stack.length >= 1) + { + active_parent_glyphs = c->parent_active_glyphs (); + } else + { + active_parent_glyphs = c->glyphs; + } + + hb_zip (this+coverage, ligatureSet) - | hb_filter (*c->glyphs, hb_first) + | hb_filter (active_parent_glyphs, hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) | hb_apply ([c] (const LigatureSet &_) { _.closure (c); }) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -1174,15 +1244,27 @@ struct ReverseChainSingleSubstFormat1 return true; } + bool may_have_non_1to1 () const + { return false; } + void closure (hb_closure_context_t *c) const { if (!intersects (c->glyphs)) return; + hb_set_t *active_parent_glyphs; + if (c->active_glyphs_stack.length >= 1) + { + active_parent_glyphs = c->parent_active_glyphs (); + } else + { + active_parent_glyphs = c->glyphs; + } + const OffsetArrayOf &lookahead = StructAfter> (backtrack); const ArrayOf &substitute = StructAfter> (lookahead); + hb_zip (this+coverage, substitute) - | hb_filter (*c->glyphs, hb_first) + | hb_filter (active_parent_glyphs, hb_first) | hb_map (hb_second) | hb_sink (c->output) ; @@ -1388,6 +1470,12 @@ struct SubstLookup : Lookup return lookup_type_is_reverse (type); } + bool may_have_non_1to1 () const + { + hb_have_non_1to1_context_t c; + return dispatch (&c); + } + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 36a95ead1..c8f0ff107 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -55,6 +55,15 @@ struct hb_intersects_context_t : glyphs (glyphs_) {} }; +struct hb_have_non_1to1_context_t : + hb_dispatch_context_t +{ + template + return_t dispatch (const T &obj) { return obj.may_have_non_1to1 (); } + static return_t default_return_value () { return false; } + bool stop_sublookup_iteration (return_t r) const { return r; } +}; + struct hb_closure_context_t : hb_dispatch_context_t { @@ -96,9 +105,29 @@ struct hb_closure_context_t : return done_lookups->get (lookup_index) == glyphs->get_population (); } + hb_set_t* parent_active_glyphs () + { + return active_glyphs_stack.tail (); + } + + void push_cur_active_glyphs (hb_set_t* cur_active_glyph_set) + { + active_glyphs_stack.push (cur_active_glyph_set); + } + + bool pop_cur_done_glyphs () + { + if (active_glyphs_stack.length < 1) + return false; + + active_glyphs_stack.pop (); + return true; + } + hb_face_t *face; hb_set_t *glyphs; hb_set_t output[1]; + hb_vector_t active_glyphs_stack; recurse_func_t recurse_func; unsigned int nesting_level_left; @@ -112,7 +141,9 @@ struct hb_closure_context_t : nesting_level_left (nesting_level_left_), done_lookups (done_lookups_), lookup_count (0) - {} + { + push_cur_active_glyphs (glyphs_); + } ~hb_closure_context_t () { flush (); } @@ -123,6 +154,8 @@ struct hb_closure_context_t : hb_set_del_range (output, face->get_num_glyphs (), hb_set_get_max (output)); /* Remove invalid glyphs. */ hb_set_union (glyphs, output); hb_set_clear (output); + active_glyphs_stack.pop (); + active_glyphs_stack.fini (); } private: @@ -1151,8 +1184,11 @@ static inline void recurse_lookups (context_t *c, unsigned int lookupCount, const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */) { + hb_set_t *chaos = hb_set_create (); for (unsigned int i = 0; i < lookupCount; i++) c->recurse (lookupRecord[i].lookupListIndex); + + hb_set_destroy (chaos); } static inline bool apply_lookup (hb_ot_apply_context_t *c, @@ -1631,6 +1667,9 @@ struct ContextFormat1 ; } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { struct ContextClosureLookupContext lookup_context = { @@ -1774,6 +1813,9 @@ struct ContextFormat2 ; } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { if (!(this+coverage).intersects (c->glyphs)) @@ -1949,6 +1991,9 @@ struct ContextFormat3 lookup_context); } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { if (!(this+coverageZ[0]).intersects (c->glyphs)) @@ -2565,6 +2610,9 @@ struct ChainContextFormat1 ; } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { struct ChainContextClosureLookupContext lookup_context = { @@ -2709,6 +2757,10 @@ struct ChainContextFormat2 | hb_any ; } + + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { if (!(this+coverage).intersects (c->glyphs)) @@ -2941,6 +2993,9 @@ struct ChainContextFormat3 lookup_context); } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { const OffsetArrayOf &input = StructAfter> (backtrack);