1 #ifndef OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
2 #define OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
5 #include "SubstLookupSubTable.hh"
11 struct SubstLookup : Lookup
13 using SubTable = SubstLookupSubTable;
15 bool sanitize (hb_sanitize_context_t *c) const
16 { return Lookup::sanitize<SubTable> (c); }
18 const SubTable& get_subtable (unsigned int i) const
19 { return Lookup::get_subtable<SubTable> (i); }
21 static inline bool lookup_type_is_reverse (unsigned int lookup_type)
22 { return lookup_type == SubTable::ReverseChainSingle; }
24 bool is_reverse () const
26 unsigned int type = get_type ();
27 if (unlikely (type == SubTable::Extension))
28 return get_subtable (0).u.extension.is_reverse ();
29 return lookup_type_is_reverse (type);
32 bool may_have_non_1to1 () const
34 hb_have_non_1to1_context_t c;
38 bool apply (hb_ot_apply_context_t *c) const
41 return_trace (dispatch (c));
44 bool intersects (const hb_set_t *glyphs) const
46 hb_intersects_context_t c (glyphs);
50 hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
52 if (!c->should_visit_lookup (this_index))
53 return hb_closure_context_t::default_return_value ();
55 c->set_recurse_func (dispatch_closure_recurse_func);
57 hb_closure_context_t::return_t ret = dispatch (c);
64 hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
66 if (c->is_lookup_visited (this_index))
67 return hb_closure_lookups_context_t::default_return_value ();
69 c->set_lookup_visited (this_index);
70 if (!intersects (c->glyphs))
72 c->set_lookup_inactive (this_index);
73 return hb_closure_lookups_context_t::default_return_value ();
76 hb_closure_lookups_context_t::return_t ret = dispatch (c);
80 hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
82 c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
86 template <typename set_t>
87 void collect_coverage (set_t *glyphs) const
89 hb_collect_coverage_context_t<set_t> c (glyphs);
93 bool would_apply (hb_would_apply_context_t *c,
94 const hb_ot_layout_lookup_accelerator_t *accel) const
96 if (unlikely (!c->len)) return false;
97 if (!accel->may_have (c->glyphs[0])) return false;
101 template<typename Glyphs, typename Substitutes,
102 hb_requires (hb_is_sorted_source_of (Glyphs,
103 const hb_codepoint_t) &&
104 hb_is_source_of (Substitutes,
105 const hb_codepoint_t))>
106 bool serialize_single (hb_serialize_context_t *c,
107 uint32_t lookup_props,
109 Substitutes substitutes)
111 TRACE_SERIALIZE (this);
112 if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
113 if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
115 c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
119 return_trace (false);
122 template<typename Iterator,
123 hb_requires (hb_is_sorted_iterator (Iterator))>
124 bool serialize (hb_serialize_context_t *c,
125 uint32_t lookup_props,
128 TRACE_SERIALIZE (this);
129 if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
130 if (c->push<SubTable> ()->u.multiple.
133 c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
137 return_trace (false);
140 bool serialize_alternate (hb_serialize_context_t *c,
141 uint32_t lookup_props,
142 hb_sorted_array_t<const HBGlyphID16> glyphs,
143 hb_array_t<const unsigned int> alternate_len_list,
144 hb_array_t<const HBGlyphID16> alternate_glyphs_list)
146 TRACE_SERIALIZE (this);
147 if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
149 if (c->push<SubTable> ()->u.alternate.
153 alternate_glyphs_list))
155 c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
159 return_trace (false);
162 bool serialize_ligature (hb_serialize_context_t *c,
163 uint32_t lookup_props,
164 hb_sorted_array_t<const HBGlyphID16> first_glyphs,
165 hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
166 hb_array_t<const HBGlyphID16> ligatures_list,
167 hb_array_t<const unsigned int> component_count_list,
168 hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
170 TRACE_SERIALIZE (this);
171 if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
172 if (c->push<SubTable> ()->u.ligature.
175 ligature_per_first_glyph_count_list,
177 component_count_list,
180 c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
184 return_trace (false);
187 template <typename context_t>
188 static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
190 static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
192 static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
194 if (!c->should_visit_lookup (lookup_index))
195 return hb_empty_t ();
197 hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
199 /* While in theory we should flush here, it will cause timeouts because a recursive
200 * lookup can keep growing the glyph set. Skip, and outer loop will retry up to
201 * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
207 template <typename context_t, typename ...Ts>
208 typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
209 { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
211 bool subset (hb_subset_context_t *c) const
212 { return Lookup::subset<SubTable> (c); }
220 #endif /* OT_LAYOUT_GSUB_SUBSTLOOKUP_HH */