Imported Upstream version 8.2.2
[platform/upstream/harfbuzz.git] / src / OT / Layout / GSUB / SubstLookup.hh
1 #ifndef OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
2 #define OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
3
4 #include "Common.hh"
5 #include "SubstLookupSubTable.hh"
6
7 namespace OT {
8 namespace Layout {
9 namespace GSUB_impl {
10
11 struct SubstLookup : Lookup
12 {
13   using SubTable = SubstLookupSubTable;
14
15   bool sanitize (hb_sanitize_context_t *c) const
16   { return Lookup::sanitize<SubTable> (c); }
17
18   const SubTable& get_subtable (unsigned int i) const
19   { return Lookup::get_subtable<SubTable> (i); }
20
21   static inline bool lookup_type_is_reverse (unsigned int lookup_type)
22   { return lookup_type == SubTable::ReverseChainSingle; }
23
24   bool is_reverse () const
25   {
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);
30   }
31
32   bool may_have_non_1to1 () const
33   {
34     hb_have_non_1to1_context_t c;
35     return dispatch (&c);
36   }
37
38   bool apply (hb_ot_apply_context_t *c) const
39   {
40     TRACE_APPLY (this);
41     return_trace (dispatch (c));
42   }
43
44   bool intersects (const hb_set_t *glyphs) const
45   {
46     hb_intersects_context_t c (glyphs);
47     return dispatch (&c);
48   }
49
50   hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
51   {
52     if (!c->should_visit_lookup (this_index))
53       return hb_closure_context_t::default_return_value ();
54
55     c->set_recurse_func (dispatch_closure_recurse_func);
56
57     hb_closure_context_t::return_t ret = dispatch (c);
58
59     c->flush ();
60
61     return ret;
62   }
63
64   hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
65   {
66     if (c->is_lookup_visited (this_index))
67       return hb_closure_lookups_context_t::default_return_value ();
68
69     c->set_lookup_visited (this_index);
70     if (!intersects (c->glyphs))
71     {
72       c->set_lookup_inactive (this_index);
73       return hb_closure_lookups_context_t::default_return_value ();
74     }
75
76     hb_closure_lookups_context_t::return_t ret = dispatch (c);
77     return ret;
78   }
79
80   hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
81   {
82     c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
83     return dispatch (c);
84   }
85
86   template <typename set_t>
87   void collect_coverage (set_t *glyphs) const
88   {
89     hb_collect_coverage_context_t<set_t> c (glyphs);
90     dispatch (&c);
91   }
92
93   bool would_apply (hb_would_apply_context_t *c,
94                     const hb_ot_layout_lookup_accelerator_t *accel) const
95   {
96     if (unlikely (!c->len)) return false;
97     if (!accel->may_have (c->glyphs[0])) return false;
98       return dispatch (c);
99   }
100
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,
108                          Glyphs glyphs,
109                          Substitutes substitutes)
110   {
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)))
114     {
115       c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
116       return_trace (true);
117     }
118     c->pop_discard ();
119     return_trace (false);
120   }
121
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,
126                   Iterator it)
127   {
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.
131         serialize (c, it))
132     {
133       c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
134       return_trace (true);
135     }
136     c->pop_discard ();
137     return_trace (false);
138   }
139
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)
145   {
146     TRACE_SERIALIZE (this);
147     if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
148
149     if (c->push<SubTable> ()->u.alternate.
150         serialize (c,
151                    glyphs,
152                    alternate_len_list,
153                    alternate_glyphs_list))
154     {
155       c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
156       return_trace (true);
157     }
158     c->pop_discard ();
159     return_trace (false);
160   }
161
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 */)
169   {
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.
173         serialize (c,
174                    first_glyphs,
175                    ligature_per_first_glyph_count_list,
176                    ligatures_list,
177                    component_count_list,
178                    component_list))
179     {
180       c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
181       return_trace (true);
182     }
183     c->pop_discard ();
184     return_trace (false);
185   }
186
187   template <typename context_t>
188   static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
189
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);
191
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)
193   {
194     if (!c->should_visit_lookup (lookup_index))
195       return hb_empty_t ();
196
197     hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
198
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. */
202     //c->flush ();
203
204     return ret;
205   }
206
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)...); }
210
211   bool subset (hb_subset_context_t *c) const
212   { return Lookup::subset<SubTable> (c); }
213 };
214
215
216 }
217 }
218 }
219
220 #endif  /* OT_LAYOUT_GSUB_SUBSTLOOKUP_HH */