diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 6e185baff..4acd67b3a 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -52,6 +52,16 @@ struct SingleSubstFormat1 } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + hb_codepoint_t glyph_id = iter.get_glyph (); + c->input.add (glyph_id); + c->output.add ((glyph_id + deltaGlyphID) & 0xFFFF); + } + } + inline const Coverage &get_coverage (void) const { return this+coverage; @@ -116,6 +126,15 @@ struct SingleSubstFormat2 } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + c->input.add (iter.get_glyph ()); + c->output.add (substitute[iter.get_coverage ()]); + } + } + inline const Coverage &get_coverage (void) const { return this+coverage; @@ -182,6 +201,16 @@ struct SingleSubst } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + TRACE_CLOSURE (); + switch (u.format) { + case 1: u.format1.collect_glyphs (c); break; + case 2: u.format2.collect_glyphs (c); break; + default: break; + } + } + inline const Coverage &get_coverage (void) const { switch (u.format) { @@ -261,6 +290,13 @@ struct Sequence c->glyphs->add (substitute[i]); } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + unsigned int count = substitute.len; + for (unsigned int i = 0; i < count; i++) + c->output.add (substitute[i]); + } + inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (); @@ -316,6 +352,14 @@ struct MultipleSubstFormat1 } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + (this+coverage).add_coverage (&c->input); + unsigned int count = sequence.len; + for (unsigned int i = 0; i < count; i++) + (this+sequence[i]).collect_glyphs (c); + } + inline const Coverage &get_coverage (void) const { return this+coverage; @@ -382,6 +426,14 @@ struct MultipleSubst } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + switch (u.format) { + case 1: u.format1.collect_glyphs (c); break; + default: break; + } + } + inline const Coverage &get_coverage (void) const { switch (u.format) { @@ -455,6 +507,18 @@ struct AlternateSubstFormat1 } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + c->input.add (iter.get_glyph ()); + const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; + unsigned int count = alt_set.len; + for (unsigned int i = 0; i < count; i++) + c->output.add (alt_set[i]); + } + } + inline const Coverage &get_coverage (void) const { return this+coverage; @@ -539,6 +603,14 @@ struct AlternateSubst } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + switch (u.format) { + case 1: u.format1.collect_glyphs (c); break; + default: break; + } + } + inline const Coverage &get_coverage (void) const { switch (u.format) { @@ -605,6 +677,14 @@ struct Ligature c->glyphs->add (ligGlyph); } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + unsigned int count = component.len; + for (unsigned int i = 1; i < count; i++) + c->input.add (component[i]); + c->output.add (ligGlyph); + } + inline bool would_apply (hb_would_apply_context_t *c) const { if (c->len != component.len) @@ -693,6 +773,13 @@ struct LigatureSet (this+ligature[i]).closure (c); } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + unsigned int num_ligs = ligature.len; + for (unsigned int i = 0; i < num_ligs; i++) + (this+ligature[i]).collect_glyphs (c); + } + inline bool would_apply (hb_would_apply_context_t *c) const { unsigned int num_ligs = ligature.len; @@ -767,6 +854,15 @@ struct LigatureSubstFormat1 } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + c->input.add (iter.get_glyph ()); + (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c); + } + } + inline const Coverage &get_coverage (void) const { return this+coverage; @@ -844,6 +940,14 @@ struct LigatureSubst } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + switch (u.format) { + case 1: u.format1.collect_glyphs (c); break; + default: break; + } + } + inline const Coverage &get_coverage (void) const { switch (u.format) { @@ -907,6 +1011,7 @@ struct LigatureSubst static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index); static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_index); +static inline void collect_glyphs_lookup (hb_collect_glyphs_context_t *c, unsigned int lookup_index); struct ContextSubst : Context { @@ -920,6 +1025,11 @@ struct ContextSubst : Context return Context::closure (c, closure_lookup); } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + return Context::collect_glyphs (c, collect_glyphs_lookup); + } + inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (); @@ -939,6 +1049,11 @@ struct ChainContextSubst : ChainContext return ChainContext::closure (c, closure_lookup); } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + return ChainContext::collect_glyphs (c, collect_glyphs_lookup); + } + inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (); @@ -962,6 +1077,8 @@ struct ExtensionSubst : Extension inline void closure (hb_closure_context_t *c) const; + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const; + inline const Coverage &get_coverage (void) const; inline bool would_apply (hb_would_apply_context_t *c) const; @@ -1005,6 +1122,28 @@ struct ReverseChainSingleSubstFormat1 } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + const OffsetArrayOf &lookahead = StructAfter > (backtrack); + + unsigned int count; + + (this+coverage).add_coverage (&c->input); + + count = backtrack.len; + for (unsigned int i = 0; i < count; i++) + (this+backtrack[i]).add_coverage (&c->before); + + count = lookahead.len; + for (unsigned int i = 0; i < count; i++) + (this+lookahead[i]).add_coverage (&c->after); + + const ArrayOf &substitute = StructAfter > (lookahead); + count = substitute.len; + for (unsigned int i = 0; i < count; i++) + c->output.add (substitute[i]); + } + inline const Coverage &get_coverage (void) const { return this+coverage; @@ -1084,6 +1223,14 @@ struct ReverseChainSingleSubst } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + switch (u.format) { + case 1: u.format1.collect_glyphs (c); break; + default: break; + } + } + inline const Coverage &get_coverage (void) const { switch (u.format) { @@ -1155,6 +1302,22 @@ struct SubstLookupSubTable } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c, + unsigned int lookup_type) const + { + switch (lookup_type) { + case Single: u.single.collect_glyphs (c); break; + case Multiple: u.multiple.collect_glyphs (c); break; + case Alternate: u.alternate.collect_glyphs (c); break; + case Ligature: u.ligature.collect_glyphs (c); break; + case Context: u.context.collect_glyphs (c); break; + case ChainContext: u.chainContext.collect_glyphs (c); break; + case Extension: u.extension.collect_glyphs (c); break; + case ReverseChainSingle: u.reverseChainContextSingle.collect_glyphs (c); break; + default: break; + } + } + inline const Coverage &get_coverage (unsigned int lookup_type) const { switch (lookup_type) { @@ -1286,6 +1449,14 @@ struct SubstLookup : Lookup } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + unsigned int lookup_type = get_type (); + unsigned int count = get_subtable_count (); + for (unsigned int i = 0; i < count; i++) + get_subtable (i).collect_glyphs (c, lookup_type); + } + inline bool would_apply (hb_would_apply_context_t *c, const hb_set_digest_t *digest) const { if (unlikely (!c->len)) return false; @@ -1506,6 +1677,11 @@ inline void ExtensionSubst::closure (hb_closure_context_t *c) const get_subtable ().closure (c, get_type ()); } +inline void ExtensionSubst::collect_glyphs (hb_collect_glyphs_context_t *c) const +{ + get_subtable ().collect_glyphs (c, get_type ()); +} + inline const Coverage & ExtensionSubst::get_coverage (void) const { return get_subtable ().get_coverage (get_type ()); @@ -1552,6 +1728,15 @@ static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_ c->nesting_level_left++; } +static inline void collect_glyphs_lookup (hb_collect_glyphs_context_t *c, unsigned int lookup_index) +{ + const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); + const SubstLookup &l = gsub.get_lookup (lookup_index); + + /* XXX TODO */ + l.collect_glyphs (c); +} + static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index) { const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 66e37a670..42726811b 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -93,6 +93,40 @@ struct hb_would_apply_context_t }; + +/* TODO Add TRACE_RETURN annotation to gsub. */ +#ifndef HB_DEBUG_COLLECT_GLYPHS +#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0) +#endif + +#define TRACE_COLLECT_GLYPHS() \ + hb_auto_trace_t trace (&c->debug_depth, "COLLECT_GLYPHS", this, HB_FUNC, ""); + + +struct hb_collect_glyphs_context_t +{ + hb_face_t *face; + hb_set_t &before; + hb_set_t &input; + hb_set_t &after; + hb_set_t &output; + unsigned int debug_depth; + + hb_collect_glyphs_context_t (hb_face_t *face_, + hb_set_t *glyphs_before, /* OUT. May be NULL */ + hb_set_t *glyphs_input, /* OUT. May be NULL */ + hb_set_t *glyphs_after, /* OUT. May be NULL */ + hb_set_t *glyphs_output /* OUT. May be NULL */) : + face (face_), + before (glyphs_before ? *glyphs_before : *hb_set_get_empty ()), + input (glyphs_input ? *glyphs_input : *hb_set_get_empty ()), + after (glyphs_after ? *glyphs_after : *hb_set_get_empty ()), + output (glyphs_output ? *glyphs_output : *hb_set_get_empty ()), + debug_depth (0) {}; +}; + + + #ifndef HB_DEBUG_APPLY #define HB_DEBUG_APPLY (HB_DEBUG+0) #endif @@ -341,6 +375,7 @@ struct hb_apply_context_t typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data); typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data); typedef void (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index); +typedef void (*collect_glyphs_lookup_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index); typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index); struct ContextClosureFuncs @@ -1105,6 +1140,17 @@ struct Context } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c, collect_glyphs_lookup_func_t closure_func) const + { + TRACE_CLOSURE (); + switch (u.format) { +// case 1: u.format1.collect_glyphs (c); break; +// case 2: u.format2.collect_glyphs (c); break; +// case 3: u.format2.collect_glyphs (c); break; + default: break; + } + } + inline const Coverage &get_coverage (void) const { switch (u.format) { @@ -1648,6 +1694,17 @@ struct ChainContext } } + inline void collect_glyphs (hb_collect_glyphs_context_t *c, collect_glyphs_lookup_func_t closure_func) const + { + TRACE_CLOSURE (); + switch (u.format) { +// case 1: u.format1.collect_glyphs (c); break; +// case 2: u.format2.collect_glyphs (c); break; +// case 3: u.format2.collect_glyphs (c); break; + default: break; + } + } + inline const Coverage &get_coverage (void) const { switch (u.format) { diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index a0c9fe822..580f95ddd 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -401,6 +401,35 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); } +void +hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, + hb_tag_t table_tag, + unsigned int lookup_index, + hb_set_t *glyphs_before, /* OUT. May be NULL */ + hb_set_t *glyphs_input, /* OUT. May be NULL */ + hb_set_t *glyphs_after, /* OUT. May be NULL */ + hb_set_t *glyphs_output /* OUT. May be NULL */) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return; + + OT::hb_collect_glyphs_context_t c (face, glyphs_before, glyphs_input, glyphs_after, glyphs_output); + + switch (table_tag) { + case HB_OT_TAG_GSUB: + { + const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); + l.collect_glyphs (&c); + return; + } + case HB_OT_TAG_GPOS: + { + const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index); +// l.collect_glyphs (&c); + return; + } + } +} + /* * OT::GSUB diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 4a023c4eb..f97c893eb 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -194,16 +194,14 @@ hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, hb_tag_t table_tag, hb_set_t *lookup_indexes /* OUT */); -#ifdef HB_NOT_IMPLEMENTED void -Xhb_ot_layout_lookup_collect_glyphs (hb_face_t *face, +hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, hb_tag_t table_tag, unsigned int lookup_index, hb_set_t *glyphs_before, /* OUT. May be NULL */ hb_set_t *glyphs_input, /* OUT. May be NULL */ hb_set_t *glyphs_after, /* OUT. May be NULL */ hb_set_t *glyphs_output /* OUT. May be NULL */); -#endif #ifdef HB_NOT_IMPLEMENTED typedef struct