/src/harfbuzz/src/OT/Layout/GDEF/GDEF.hh
Line  | Count  | Source  | 
1  |  | /*  | 
2  |  |  * Copyright © 2007,2008,2009  Red Hat, Inc.  | 
3  |  |  * Copyright © 2010,2011,2012  Google, Inc.  | 
4  |  |  *  | 
5  |  |  *  This is part of HarfBuzz, a text shaping library.  | 
6  |  |  *  | 
7  |  |  * Permission is hereby granted, without written agreement and without  | 
8  |  |  * license or royalty fees, to use, copy, modify, and distribute this  | 
9  |  |  * software and its documentation for any purpose, provided that the  | 
10  |  |  * above copyright notice and the following two paragraphs appear in  | 
11  |  |  * all copies of this software.  | 
12  |  |  *  | 
13  |  |  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR  | 
14  |  |  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES  | 
15  |  |  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN  | 
16  |  |  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH  | 
17  |  |  * DAMAGE.  | 
18  |  |  *  | 
19  |  |  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,  | 
20  |  |  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  | 
21  |  |  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS  | 
22  |  |  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO  | 
23  |  |  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.  | 
24  |  |  *  | 
25  |  |  * Red Hat Author(s): Behdad Esfahbod  | 
26  |  |  * Google Author(s): Behdad Esfahbod  | 
27  |  |  */  | 
28  |  |  | 
29  |  | #ifndef OT_LAYOUT_GDEF_GDEF_HH  | 
30  |  | #define OT_LAYOUT_GDEF_GDEF_HH  | 
31  |  |  | 
32  |  | #include "../../../hb-ot-var-common.hh"  | 
33  |  |  | 
34  |  | #include "../../../hb-font.hh"  | 
35  |  | #include "../../../hb-cache.hh"  | 
36  |  |  | 
37  |  |  | 
38  |  | namespace OT { | 
39  |  |  | 
40  |  |  | 
41  |  | /*  | 
42  |  |  * Attachment List Table  | 
43  |  |  */  | 
44  |  |  | 
45  |  | /* Array of contour point indices--in increasing numerical order */  | 
46  |  | struct AttachPoint : Array16Of<HBUINT16>  | 
47  |  | { | 
48  |  |   bool subset (hb_subset_context_t *c) const  | 
49  | 0  |   { | 
50  | 0  |     TRACE_SUBSET (this);  | 
51  | 0  |     auto *out = c->serializer->start_embed (*this);  | 
52  | 0  |     return_trace (out->serialize (c->serializer, + iter ()));  | 
53  | 0  |   }  | 
54  |  | };  | 
55  |  |  | 
56  |  | struct AttachList  | 
57  |  | { | 
58  |  |   unsigned int get_attach_points (hb_codepoint_t glyph_id,  | 
59  |  |           unsigned int start_offset,  | 
60  |  |           unsigned int *point_count /* IN/OUT */,  | 
61  |  |           unsigned int *point_array /* OUT */) const  | 
62  | 0  |   { | 
63  | 0  |     unsigned int index = (this+coverage).get_coverage (glyph_id);  | 
64  | 0  |     if (index == NOT_COVERED)  | 
65  | 0  |     { | 
66  | 0  |       if (point_count)  | 
67  | 0  |   *point_count = 0;  | 
68  | 0  |       return 0;  | 
69  | 0  |     }  | 
70  |  |  | 
71  | 0  |     const AttachPoint &points = this+attachPoint[index];  | 
72  |  | 
  | 
73  | 0  |     if (point_count)  | 
74  | 0  |     { | 
75  | 0  |       + points.as_array ().sub_array (start_offset, point_count)  | 
76  | 0  |       | hb_sink (hb_array (point_array, *point_count))  | 
77  | 0  |       ;  | 
78  | 0  |     }  | 
79  |  | 
  | 
80  | 0  |     return points.len;  | 
81  | 0  |   }  | 
82  |  |  | 
83  |  |   bool subset (hb_subset_context_t *c) const  | 
84  | 0  |   { | 
85  | 0  |     TRACE_SUBSET (this);  | 
86  | 0  |     const hb_set_t &glyphset = *c->plan->glyphset_gsub ();  | 
87  | 0  |     const hb_map_t &glyph_map = *c->plan->glyph_map;  | 
88  | 0  | 
  | 
89  | 0  |     auto *out = c->serializer->start_embed (*this);  | 
90  | 0  |     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);  | 
91  | 0  | 
  | 
92  | 0  |     hb_sorted_vector_t<hb_codepoint_t> new_coverage;  | 
93  | 0  |     + hb_zip (this+coverage, attachPoint)  | 
94  | 0  |     | hb_filter (glyphset, hb_first)  | 
95  | 0  |     | hb_filter (subset_offset_array (c, out->attachPoint, this), hb_second)  | 
96  | 0  |     | hb_map (hb_first)  | 
97  | 0  |     | hb_map (glyph_map)  | 
98  | 0  |     | hb_sink (new_coverage)  | 
99  | 0  |     ;  | 
100  | 0  |     out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());  | 
101  | 0  |     return_trace (bool (new_coverage));  | 
102  | 0  |   }  | 
103  |  |  | 
104  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
105  | 0  |   { | 
106  | 0  |     TRACE_SANITIZE (this);  | 
107  | 0  |     return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));  | 
108  | 0  |   }  | 
109  |  |  | 
110  |  |   protected:  | 
111  |  |   Offset16To<Coverage>  | 
112  |  |     coverage;   /* Offset to Coverage table -- from  | 
113  |  |            * beginning of AttachList table */  | 
114  |  |   Array16OfOffset16To<AttachPoint>  | 
115  |  |     attachPoint;    /* Array of AttachPoint tables  | 
116  |  |            * in Coverage Index order */  | 
117  |  |   public:  | 
118  |  |   DEFINE_SIZE_ARRAY (4, attachPoint);  | 
119  |  | };  | 
120  |  |  | 
121  |  | /*  | 
122  |  |  * Ligature Caret Table  | 
123  |  |  */  | 
124  |  |  | 
125  |  | struct CaretValueFormat1  | 
126  |  | { | 
127  |  |   friend struct CaretValue;  | 
128  |  |   bool subset (hb_subset_context_t *c) const  | 
129  | 0  |   { | 
130  | 0  |     TRACE_SUBSET (this);  | 
131  | 0  |     auto *out = c->serializer->embed (this);  | 
132  | 0  |     if (unlikely (!out)) return_trace (false);  | 
133  | 0  |     return_trace (true);  | 
134  | 0  |   }  | 
135  |  |  | 
136  |  |   private:  | 
137  |  |   hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const  | 
138  | 0  |   { | 
139  | 0  |     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);  | 
140  | 0  |   }  | 
141  |  |  | 
142  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
143  | 0  |   { | 
144  | 0  |     TRACE_SANITIZE (this);  | 
145  | 0  |     return_trace (c->check_struct (this));  | 
146  | 0  |   }  | 
147  |  |  | 
148  |  |   protected:  | 
149  |  |   HBUINT16  caretValueFormat; /* Format identifier--format = 1 */  | 
150  |  |   FWORD   coordinate;   /* X or Y value, in design units */  | 
151  |  |   public:  | 
152  |  |   DEFINE_SIZE_STATIC (4);  | 
153  |  | };  | 
154  |  |  | 
155  |  | struct CaretValueFormat2  | 
156  |  | { | 
157  |  |   friend struct CaretValue;  | 
158  |  |   bool subset (hb_subset_context_t *c) const  | 
159  | 0  |   { | 
160  | 0  |     TRACE_SUBSET (this);  | 
161  | 0  |     auto *out = c->serializer->embed (this);  | 
162  | 0  |     if (unlikely (!out)) return_trace (false);  | 
163  | 0  |     return_trace (true);  | 
164  | 0  |   }  | 
165  |  |  | 
166  |  |   private:  | 
167  |  |   hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const  | 
168  | 0  |   { | 
169  | 0  |     hb_position_t x, y;  | 
170  | 0  |     font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y);  | 
171  | 0  |     return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;  | 
172  | 0  |   }  | 
173  |  |  | 
174  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
175  | 0  |   { | 
176  | 0  |     TRACE_SANITIZE (this);  | 
177  | 0  |     return_trace (c->check_struct (this));  | 
178  | 0  |   }  | 
179  |  |  | 
180  |  |   protected:  | 
181  |  |   HBUINT16  caretValueFormat; /* Format identifier--format = 2 */  | 
182  |  |   HBUINT16  caretValuePoint;  /* Contour point index on glyph */  | 
183  |  |   public:  | 
184  |  |   DEFINE_SIZE_STATIC (4);  | 
185  |  | };  | 
186  |  |  | 
187  |  | struct CaretValueFormat3  | 
188  |  | { | 
189  |  |   friend struct CaretValue;  | 
190  |  |  | 
191  |  |   hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,  | 
192  |  |          const ItemVariationStore &var_store) const  | 
193  | 0  |   { | 
194  | 0  |     return HB_DIRECTION_IS_HORIZONTAL (direction) ?  | 
195  | 0  |      font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :  | 
196  | 0  |      font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);  | 
197  | 0  |   }  | 
198  |  |  | 
199  |  |   bool subset (hb_subset_context_t *c) const  | 
200  | 0  |   { | 
201  | 0  |     TRACE_SUBSET (this);  | 
202  | 0  |     auto *out = c->serializer->start_embed (*this);  | 
203  | 0  |     if (!c->serializer->embed (caretValueFormat)) return_trace (false);  | 
204  | 0  |     if (!c->serializer->embed (coordinate)) return_trace (false);  | 
205  | 0  | 
  | 
206  | 0  |     unsigned varidx = (this+deviceTable).get_variation_index ();  | 
207  | 0  |     hb_pair_t<unsigned, int> *new_varidx_delta;  | 
208  | 0  |     if (c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) { | 
209  | 0  |       uint32_t new_varidx = hb_first (*new_varidx_delta);  | 
210  | 0  |       int delta = hb_second (*new_varidx_delta);  | 
211  | 0  |       if (delta != 0)  | 
212  | 0  |       { | 
213  | 0  |         if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))  | 
214  | 0  |           return_trace (false);  | 
215  | 0  |       }  | 
216  | 0  | 
  | 
217  | 0  |       if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)  | 
218  | 0  |         return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));  | 
219  | 0  |     }  | 
220  | 0  | 
  | 
221  | 0  |     if (!c->serializer->embed (deviceTable))  | 
222  | 0  |       return_trace (false);  | 
223  | 0  | 
  | 
224  | 0  |     return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out),  | 
225  | 0  |                hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map));  | 
226  | 0  |   }  | 
227  |  |  | 
228  |  |   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const  | 
229  | 0  |   { (this+deviceTable).collect_variation_indices (c); } | 
230  |  |  | 
231  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
232  | 0  |   { | 
233  | 0  |     TRACE_SANITIZE (this);  | 
234  | 0  |     return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));  | 
235  | 0  |   }  | 
236  |  |  | 
237  |  |   protected:  | 
238  |  |   HBUINT16  caretValueFormat; /* Format identifier--format = 3 */  | 
239  |  |   FWORD   coordinate;   /* X or Y value, in design units */  | 
240  |  |   Offset16To<Device>  | 
241  |  |     deviceTable;    /* Offset to Device table for X or Y  | 
242  |  |            * value--from beginning of CaretValue  | 
243  |  |            * table */  | 
244  |  |   public:  | 
245  |  |   DEFINE_SIZE_STATIC (6);  | 
246  |  | };  | 
247  |  |  | 
248  |  | struct CaretValue  | 
249  |  | { | 
250  |  |   hb_position_t get_caret_value (hb_font_t *font,  | 
251  |  |          hb_direction_t direction,  | 
252  |  |          hb_codepoint_t glyph_id,  | 
253  |  |          const ItemVariationStore &var_store) const  | 
254  | 0  |   { | 
255  | 0  |     switch (u.format) { | 
256  | 0  |     case 1: return u.format1.get_caret_value (font, direction);  | 
257  | 0  |     case 2: return u.format2.get_caret_value (font, direction, glyph_id);  | 
258  | 0  |     case 3: return u.format3.get_caret_value (font, direction, var_store);  | 
259  | 0  |     default:return 0;  | 
260  | 0  |     }  | 
261  | 0  |   }  | 
262  |  |  | 
263  |  |   template <typename context_t, typename ...Ts>  | 
264  |  |   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const  | 
265  | 0  |   { | 
266  | 0  |     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();  | 
267  | 0  |     TRACE_DISPATCH (this, u.format);  | 
268  | 0  |     switch (u.format) { | 
269  | 0  |     case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));  | 
270  | 0  |     case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));  | 
271  | 0  |     case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));  | 
272  | 0  |     default:return_trace (c->default_return_value ());  | 
273  | 0  |     }  | 
274  | 0  |   }  | 
275  |  |  | 
276  |  |   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const  | 
277  | 0  |   { | 
278  | 0  |     switch (u.format) { | 
279  | 0  |     case 1:  | 
280  | 0  |     case 2:  | 
281  | 0  |       return;  | 
282  | 0  |     case 3:  | 
283  | 0  |       u.format3.collect_variation_indices (c);  | 
284  | 0  |       return;  | 
285  | 0  |     default: return;  | 
286  | 0  |     }  | 
287  | 0  |   }  | 
288  |  |  | 
289  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
290  | 0  |   { | 
291  | 0  |     TRACE_SANITIZE (this);  | 
292  | 0  |     if (!u.format.sanitize (c)) return_trace (false);  | 
293  | 0  |     hb_barrier ();  | 
294  | 0  |     switch (u.format) { | 
295  | 0  |     case 1: return_trace (u.format1.sanitize (c));  | 
296  | 0  |     case 2: return_trace (u.format2.sanitize (c));  | 
297  | 0  |     case 3: return_trace (u.format3.sanitize (c));  | 
298  | 0  |     default:return_trace (true);  | 
299  | 0  |     }  | 
300  | 0  |   }  | 
301  |  |  | 
302  |  |   protected:  | 
303  |  |   union { | 
304  |  |   HBUINT16    format;   /* Format identifier */  | 
305  |  |   CaretValueFormat1 format1;  | 
306  |  |   CaretValueFormat2 format2;  | 
307  |  |   CaretValueFormat3 format3;  | 
308  |  |   } u;  | 
309  |  |   public:  | 
310  |  |   DEFINE_SIZE_UNION (2, format);  | 
311  |  | };  | 
312  |  |  | 
313  |  | struct LigGlyph  | 
314  |  | { | 
315  |  |   unsigned get_lig_carets (hb_font_t            *font,  | 
316  |  |          hb_direction_t        direction,  | 
317  |  |          hb_codepoint_t        glyph_id,  | 
318  |  |          const ItemVariationStore &var_store,  | 
319  |  |          unsigned              start_offset,  | 
320  |  |          unsigned             *caret_count /* IN/OUT */,  | 
321  |  |          hb_position_t        *caret_array /* OUT */) const  | 
322  | 0  |   { | 
323  | 0  |     if (caret_count)  | 
324  | 0  |     { | 
325  | 0  |       + carets.as_array ().sub_array (start_offset, caret_count)  | 
326  | 0  |       | hb_map (hb_add (this))  | 
327  | 0  |       | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); }) | 
328  | 0  |       | hb_sink (hb_array (caret_array, *caret_count))  | 
329  | 0  |       ;  | 
330  | 0  |     }  | 
331  |  | 
  | 
332  | 0  |     return carets.len;  | 
333  | 0  |   }  | 
334  |  |  | 
335  |  |   bool subset (hb_subset_context_t *c) const  | 
336  | 0  |   { | 
337  | 0  |     TRACE_SUBSET (this);  | 
338  | 0  |     auto *out = c->serializer->start_embed (*this);  | 
339  | 0  |     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);  | 
340  | 0  | 
  | 
341  | 0  |     + hb_iter (carets)  | 
342  | 0  |     | hb_apply (subset_offset_array (c, out->carets, this))  | 
343  | 0  |     ;  | 
344  | 0  | 
  | 
345  | 0  |     return_trace (bool (out->carets));  | 
346  | 0  |   }  | 
347  |  |  | 
348  |  |   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const  | 
349  | 0  |   { | 
350  | 0  |     for (const Offset16To<CaretValue>& offset : carets.iter ())  | 
351  | 0  |       (this+offset).collect_variation_indices (c);  | 
352  | 0  |   }  | 
353  |  |  | 
354  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
355  | 0  |   { | 
356  | 0  |     TRACE_SANITIZE (this);  | 
357  | 0  |     return_trace (carets.sanitize (c, this));  | 
358  | 0  |   }  | 
359  |  |  | 
360  |  |   protected:  | 
361  |  |   Array16OfOffset16To<CaretValue>  | 
362  |  |     carets;     /* Offset array of CaretValue tables  | 
363  |  |            * --from beginning of LigGlyph table  | 
364  |  |            * --in increasing coordinate order */  | 
365  |  |   public:  | 
366  |  |   DEFINE_SIZE_ARRAY (2, carets);  | 
367  |  | };  | 
368  |  |  | 
369  |  | struct LigCaretList  | 
370  |  | { | 
371  |  |   unsigned int get_lig_carets (hb_font_t *font,  | 
372  |  |              hb_direction_t direction,  | 
373  |  |              hb_codepoint_t glyph_id,  | 
374  |  |              const ItemVariationStore &var_store,  | 
375  |  |              unsigned int start_offset,  | 
376  |  |              unsigned int *caret_count /* IN/OUT */,  | 
377  |  |              hb_position_t *caret_array /* OUT */) const  | 
378  | 0  |   { | 
379  | 0  |     unsigned int index = (this+coverage).get_coverage (glyph_id);  | 
380  | 0  |     if (index == NOT_COVERED)  | 
381  | 0  |     { | 
382  | 0  |       if (caret_count)  | 
383  | 0  |   *caret_count = 0;  | 
384  | 0  |       return 0;  | 
385  | 0  |     }  | 
386  | 0  |     const LigGlyph &lig_glyph = this+ligGlyph[index];  | 
387  | 0  |     return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);  | 
388  | 0  |   }  | 
389  |  |  | 
390  |  |   bool subset (hb_subset_context_t *c) const  | 
391  | 0  |   { | 
392  | 0  |     TRACE_SUBSET (this);  | 
393  | 0  |     const hb_set_t &glyphset = *c->plan->glyphset_gsub ();  | 
394  | 0  |     const hb_map_t &glyph_map = *c->plan->glyph_map;  | 
395  | 0  | 
  | 
396  | 0  |     auto *out = c->serializer->start_embed (*this);  | 
397  | 0  |     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);  | 
398  | 0  | 
  | 
399  | 0  |     hb_sorted_vector_t<hb_codepoint_t> new_coverage;  | 
400  | 0  |     + hb_zip (this+coverage, ligGlyph)  | 
401  | 0  |     | hb_filter (glyphset, hb_first)  | 
402  | 0  |     | hb_filter (subset_offset_array (c, out->ligGlyph, this), hb_second)  | 
403  | 0  |     | hb_map (hb_first)  | 
404  | 0  |     | hb_map (glyph_map)  | 
405  | 0  |     | hb_sink (new_coverage)  | 
406  | 0  |     ;  | 
407  | 0  |     out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());  | 
408  | 0  |     return_trace (bool (new_coverage));  | 
409  | 0  |   }  | 
410  |  |  | 
411  |  |   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const  | 
412  | 0  |   { | 
413  | 0  |     + hb_zip (this+coverage, ligGlyph)  | 
414  | 0  |     | hb_filter (c->glyph_set, hb_first)  | 
415  | 0  |     | hb_map (hb_second)  | 
416  | 0  |     | hb_map (hb_add (this))  | 
417  | 0  |     | hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); }) | 
418  | 0  |     ;  | 
419  | 0  |   }  | 
420  |  |  | 
421  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
422  | 22  |   { | 
423  | 22  |     TRACE_SANITIZE (this);  | 
424  | 22  |     return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));  | 
425  | 22  |   }  | 
426  |  |  | 
427  |  |   protected:  | 
428  |  |   Offset16To<Coverage>  | 
429  |  |     coverage;   /* Offset to Coverage table--from  | 
430  |  |            * beginning of LigCaretList table */  | 
431  |  |   Array16OfOffset16To<LigGlyph>  | 
432  |  |     ligGlyph;   /* Array of LigGlyph tables  | 
433  |  |            * in Coverage Index order */  | 
434  |  |   public:  | 
435  |  |   DEFINE_SIZE_ARRAY (4, ligGlyph);  | 
436  |  | };  | 
437  |  |  | 
438  |  |  | 
439  |  | struct MarkGlyphSetsFormat1  | 
440  |  | { | 
441  |  |   bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const  | 
442  | 0  |   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } | 
443  |  |  | 
444  |  |   void collect_used_mark_sets (const hb_set_t& glyph_set,  | 
445  |  |                                hb_set_t& used_mark_sets /* OUT */) const  | 
446  | 0  |   { | 
447  | 0  |     unsigned i = 0;  | 
448  | 0  |     for (const auto &offset : coverage)  | 
449  | 0  |      { | 
450  | 0  |        const auto &cov = this+offset;  | 
451  | 0  |        if (cov.intersects (&glyph_set))  | 
452  | 0  |          used_mark_sets.add (i);  | 
453  | 0  | 
  | 
454  | 0  |        i++;  | 
455  | 0  |      }  | 
456  | 0  |   }  | 
457  |  |  | 
458  |  |   template <typename set_t>  | 
459  |  |   void collect_coverage (hb_vector_t<set_t> &sets) const  | 
460  | 0  |   { | 
461  | 0  |      for (const auto &offset : coverage)  | 
462  | 0  |      { | 
463  | 0  |        const auto &cov = this+offset;  | 
464  | 0  |        cov.collect_coverage (sets.push ());  | 
465  | 0  |      }  | 
466  | 0  |   }  | 
467  |  |  | 
468  |  |   bool subset (hb_subset_context_t *c) const  | 
469  | 0  |   { | 
470  | 0  |     TRACE_SUBSET (this);  | 
471  | 0  |     auto *out = c->serializer->start_embed (*this);  | 
472  | 0  |     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);  | 
473  | 0  |     out->format = format;  | 
474  | 0  | 
  | 
475  | 0  |     bool ret = true;  | 
476  | 0  |     for (const Offset32To<Coverage>& offset : coverage.iter ())  | 
477  | 0  |     { | 
478  | 0  |       auto snap = c->serializer->snapshot ();  | 
479  | 0  |       auto *o = out->coverage.serialize_append (c->serializer);  | 
480  | 0  |       if (unlikely (!o))  | 
481  | 0  |       { | 
482  | 0  |   ret = false;  | 
483  | 0  |   break;  | 
484  | 0  |       }  | 
485  | 0  | 
  | 
486  | 0  |       //skip empty coverage  | 
487  | 0  |       c->serializer->push ();  | 
488  | 0  |       bool res = false;  | 
489  | 0  |       if (offset) res = c->dispatch (this+offset);  | 
490  | 0  |       if (!res)  | 
491  | 0  |       { | 
492  | 0  |         c->serializer->pop_discard ();  | 
493  | 0  |         c->serializer->revert (snap);  | 
494  | 0  |         (out->coverage.len)--;  | 
495  | 0  |         continue;  | 
496  | 0  |       }  | 
497  | 0  |       c->serializer->add_link (*o, c->serializer->pop_pack ());  | 
498  | 0  |     }  | 
499  | 0  | 
  | 
500  | 0  |     return_trace (ret && out->coverage.len);  | 
501  | 0  |   }  | 
502  |  |  | 
503  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
504  | 0  |   { | 
505  | 0  |     TRACE_SANITIZE (this);  | 
506  | 0  |     return_trace (coverage.sanitize (c, this));  | 
507  | 0  |   }  | 
508  |  |  | 
509  |  |   protected:  | 
510  |  |   HBUINT16  format;     /* Format identifier--format = 1 */  | 
511  |  |   Array16Of<Offset32To<Coverage>>  | 
512  |  |     coverage;   /* Array of long offsets to mark set  | 
513  |  |            * coverage tables */  | 
514  |  |   public:  | 
515  |  |   DEFINE_SIZE_ARRAY (4, coverage);  | 
516  |  | };  | 
517  |  |  | 
518  |  | struct MarkGlyphSets  | 
519  |  | { | 
520  |  |   bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const  | 
521  | 0  |   { | 
522  | 0  |     switch (u.format) { | 
523  | 0  |     case 1: return u.format1.covers (set_index, glyph_id);  | 
524  | 0  |     default:return false;  | 
525  | 0  |     }  | 
526  | 0  |   }  | 
527  |  |  | 
528  |  |   template <typename set_t>  | 
529  |  |   void collect_coverage (hb_vector_t<set_t> &sets) const  | 
530  | 1.79k  |   { | 
531  | 1.79k  |     switch (u.format) { | 
532  | 0  |     case 1: u.format1.collect_coverage (sets); return;  | 
533  | 1.79k  |     default:return;  | 
534  | 1.79k  |     }  | 
535  | 1.79k  |   }  | 
536  |  |  | 
537  |  |   void collect_used_mark_sets (const hb_set_t& glyph_set,  | 
538  |  |                                hb_set_t& used_mark_sets /* OUT */) const  | 
539  | 0  |   { | 
540  | 0  |     switch (u.format) { | 
541  | 0  |     case 1: u.format1.collect_used_mark_sets (glyph_set, used_mark_sets); return;  | 
542  | 0  |     default:return;  | 
543  | 0  |     }  | 
544  | 0  |   }  | 
545  |  |  | 
546  |  |   bool subset (hb_subset_context_t *c) const  | 
547  | 0  |   { | 
548  | 0  |     TRACE_SUBSET (this);  | 
549  | 0  |     switch (u.format) { | 
550  | 0  |     case 1: return_trace (u.format1.subset (c));  | 
551  | 0  |     default:return_trace (false);  | 
552  | 0  |     }  | 
553  | 0  |   }  | 
554  |  |  | 
555  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
556  | 0  |   { | 
557  | 0  |     TRACE_SANITIZE (this);  | 
558  | 0  |     if (!u.format.sanitize (c)) return_trace (false);  | 
559  | 0  |     hb_barrier ();  | 
560  | 0  |     switch (u.format) { | 
561  | 0  |     case 1: return_trace (u.format1.sanitize (c));  | 
562  | 0  |     default:return_trace (true);  | 
563  | 0  |     }  | 
564  | 0  |   }  | 
565  |  |  | 
566  |  |   protected:  | 
567  |  |   union { | 
568  |  |   HBUINT16    format;   /* Format identifier */  | 
569  |  |   MarkGlyphSetsFormat1  format1;  | 
570  |  |   } u;  | 
571  |  |   public:  | 
572  |  |   DEFINE_SIZE_UNION (2, format);  | 
573  |  | };  | 
574  |  |  | 
575  |  |  | 
576  |  | /*  | 
577  |  |  * GDEF -- Glyph Definition  | 
578  |  |  * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef  | 
579  |  |  */  | 
580  |  |  | 
581  |  |  | 
582  |  | template <typename Types>  | 
583  |  | struct GDEFVersion1_2  | 
584  |  | { | 
585  |  |   friend struct GDEF;  | 
586  |  |  | 
587  |  |   protected:  | 
588  |  |   FixedVersion<>version;    /* Version of the GDEF table--currently  | 
589  |  |            * 0x00010003u */  | 
590  |  |   typename Types::template OffsetTo<ClassDef>  | 
591  |  |     glyphClassDef;    /* Offset to class definition table  | 
592  |  |            * for glyph type--from beginning of  | 
593  |  |            * GDEF header (may be Null) */  | 
594  |  |   typename Types::template OffsetTo<AttachList>  | 
595  |  |     attachList;   /* Offset to list of glyphs with  | 
596  |  |            * attachment points--from beginning  | 
597  |  |            * of GDEF header (may be Null) */  | 
598  |  |   typename Types::template OffsetTo<LigCaretList>  | 
599  |  |     ligCaretList;   /* Offset to list of positioning points  | 
600  |  |            * for ligature carets--from beginning  | 
601  |  |            * of GDEF header (may be Null) */  | 
602  |  |   typename Types::template OffsetTo<ClassDef>  | 
603  |  |     markAttachClassDef; /* Offset to class definition table for  | 
604  |  |            * mark attachment type--from beginning  | 
605  |  |            * of GDEF header (may be Null) */  | 
606  |  |   typename Types::template OffsetTo<MarkGlyphSets>  | 
607  |  |     markGlyphSetsDef; /* Offset to the table of mark set  | 
608  |  |            * definitions--from beginning of GDEF  | 
609  |  |            * header (may be NULL).  Introduced  | 
610  |  |            * in version 0x00010002. */  | 
611  |  |   Offset32To<ItemVariationStore>  | 
612  |  |     varStore;   /* Offset to the table of Item Variation  | 
613  |  |            * Store--from beginning of GDEF  | 
614  |  |            * header (may be NULL).  Introduced  | 
615  |  |            * in version 0x00010003. */  | 
616  |  |   public:  | 
617  |  |   DEFINE_SIZE_MIN (4 + 4 * Types::size);  | 
618  |  |  | 
619  |  |   unsigned int get_size () const  | 
620  | 0  |   { | 
621  | 0  |     return min_size +  | 
622  | 0  |      (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +  | 
623  | 0  |      (version.to_int () >= 0x00010003u ? varStore.static_size : 0);  | 
624  | 0  |   }  | 
625  |  |  | 
626  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
627  | 22  |   { | 
628  | 22  |     TRACE_SANITIZE (this);  | 
629  | 22  |     return_trace (version.sanitize (c) &&  | 
630  | 22  |       glyphClassDef.sanitize (c, this) &&  | 
631  | 22  |       attachList.sanitize (c, this) &&  | 
632  | 22  |       ligCaretList.sanitize (c, this) &&  | 
633  | 22  |       markAttachClassDef.sanitize (c, this) &&  | 
634  | 22  |       hb_barrier () &&  | 
635  | 22  |       ((version.to_int () < 0x00010002u && hb_barrier ()) || markGlyphSetsDef.sanitize (c, this)) &&  | 
636  | 22  |       ((version.to_int () < 0x00010003u && hb_barrier ()) || varStore.sanitize (c, this)));  | 
637  | 22  |   }  | 
638  |  |  | 
639  |  |   static void remap_varidx_after_instantiation (const hb_map_t& varidx_map,  | 
640  |  |                                                 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>>& layout_variation_idx_delta_map /* IN/OUT */)  | 
641  | 0  |   { | 
642  | 0  |     /* varidx_map is empty which means varstore is empty after instantiation,  | 
643  | 0  |      * no variations, map all varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX.  | 
644  | 0  |      * varidx_map doesn't have original varidx, indicating delta row is all  | 
645  | 0  |      * zeros, map varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX */  | 
646  | 0  |     for (auto _ : layout_variation_idx_delta_map.iter_ref ())  | 
647  | 0  |     { | 
648  | 0  |       /* old_varidx->(varidx, delta) mapping generated for subsetting, then this  | 
649  | 0  |        * varidx is used as key of varidx_map during instantiation */  | 
650  | 0  |       uint32_t varidx = _.second.first;  | 
651  | 0  |       uint32_t *new_varidx;  | 
652  | 0  |       if (varidx_map.has (varidx, &new_varidx))  | 
653  | 0  |         _.second.first = *new_varidx;  | 
654  | 0  |       else  | 
655  | 0  |         _.second.first = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;  | 
656  | 0  |     }  | 
657  | 0  |   }  | 
658  |  |  | 
659  |  |   bool subset (hb_subset_context_t *c) const  | 
660  | 0  |   { | 
661  | 0  |     TRACE_SUBSET (this);  | 
662  | 0  |     auto *out = c->serializer->start_embed (*this);  | 
663  | 0  |     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);  | 
664  | 0  | 
  | 
665  | 0  |     // Push var store first (if it's needed) so that it's last in the  | 
666  | 0  |     // serialization order. Some font consumers assume that varstore runs to  | 
667  | 0  |     // the end of the GDEF table.  | 
668  | 0  |     // See: https://github.com/harfbuzz/harfbuzz/issues/4636  | 
669  | 0  |     auto snapshot_version0 = c->serializer->snapshot ();  | 
670  | 0  |     if (unlikely (version.to_int () >= 0x00010002u && hb_barrier () && !c->serializer->embed (markGlyphSetsDef)))  | 
671  | 0  |       return_trace (false);  | 
672  | 0  | 
  | 
673  | 0  |     bool subset_varstore = false;  | 
674  | 0  |     unsigned varstore_index = (unsigned) -1;  | 
675  | 0  |     auto snapshot_version2 = c->serializer->snapshot ();  | 
676  | 0  |     if (version.to_int () >= 0x00010003u && hb_barrier ())  | 
677  | 0  |     { | 
678  | 0  |       if (unlikely (!c->serializer->embed (varStore))) return_trace (false);  | 
679  | 0  |       if (c->plan->all_axes_pinned)  | 
680  | 0  |         out->varStore = 0;  | 
681  | 0  |       else if (c->plan->normalized_coords)  | 
682  | 0  |       { | 
683  | 0  |         if (varStore)  | 
684  | 0  |         { | 
685  | 0  |           item_variations_t item_vars;  | 
686  | 0  |           if (item_vars.instantiate (this+varStore, c->plan, true, true,  | 
687  | 0  |                                      c->plan->gdef_varstore_inner_maps.as_array ())) { | 
688  | 0  |             subset_varstore = out->varStore.serialize_serialize (c->serializer,  | 
689  | 0  |                                                                  item_vars.has_long_word (),  | 
690  | 0  |                                                                  c->plan->axis_tags,  | 
691  | 0  |                                                                  item_vars.get_region_list (),  | 
692  | 0  |                                                                  item_vars.get_vardata_encodings ());  | 
693  | 0  |             varstore_index = c->serializer->last_added_child_index();  | 
694  | 0  |           }  | 
695  | 0  |           remap_varidx_after_instantiation (item_vars.get_varidx_map (),  | 
696  | 0  |                                             c->plan->layout_variation_idx_delta_map);  | 
697  | 0  |         }  | 
698  | 0  |       }  | 
699  | 0  |       else  | 
700  | 0  |       { | 
701  | 0  |         subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ());  | 
702  | 0  |         varstore_index = c->serializer->last_added_child_index();  | 
703  | 0  |       }  | 
704  | 0  |     }  | 
705  | 0  | 
  | 
706  | 0  |     out->version.major = version.major;  | 
707  | 0  |     out->version.minor = version.minor;  | 
708  | 0  | 
  | 
709  | 0  |     if (!subset_varstore && version.to_int () >= 0x00010002u) { | 
710  | 0  |       c->serializer->revert (snapshot_version2);  | 
711  | 0  |     }  | 
712  | 0  | 
  | 
713  | 0  |     bool subset_markglyphsetsdef = false;  | 
714  | 0  |     if (version.to_int () >= 0x00010002u && hb_barrier ())  | 
715  | 0  |     { | 
716  | 0  |       subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);  | 
717  | 0  |     }  | 
718  | 0  | 
  | 
719  | 0  |     if (subset_varstore)  | 
720  | 0  |     { | 
721  | 0  |       out->version.minor = 3;  | 
722  | 0  |       c->plan->has_gdef_varstore = true;  | 
723  | 0  |     } else if (subset_markglyphsetsdef) { | 
724  | 0  |       out->version.minor = 2;        | 
725  | 0  |     } else  { | 
726  | 0  |       out->version.minor = 0;  | 
727  | 0  |       c->serializer->revert (snapshot_version0);  | 
728  | 0  |     }  | 
729  | 0  | 
  | 
730  | 0  |     bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);  | 
731  | 0  |     bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);  | 
732  | 0  |     bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);  | 
733  | 0  |     bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);  | 
734  | 0  | 
  | 
735  | 0  |     if (subset_varstore && varstore_index != (unsigned) -1) { | 
736  | 0  |       c->serializer->repack_last(varstore_index);  | 
737  | 0  |     }  | 
738  | 0  | 
  | 
739  | 0  |     return_trace (subset_glyphclassdef || subset_attachlist ||  | 
740  | 0  |       subset_ligcaretlist || subset_markattachclassdef ||  | 
741  | 0  |       (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||  | 
742  | 0  |       (out->version.to_int () >= 0x00010003u && subset_varstore));  | 
743  | 0  |   }  | 
744  |  | };  | 
745  |  |  | 
746  |  | struct GDEF  | 
747  |  | { | 
748  |  |   static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;  | 
749  |  |  | 
750  |  |   enum GlyphClasses { | 
751  |  |     UnclassifiedGlyph = 0,  | 
752  |  |     BaseGlyph   = 1,  | 
753  |  |     LigatureGlyph = 2,  | 
754  |  |     MarkGlyph   = 3,  | 
755  |  |     ComponentGlyph  = 4  | 
756  |  |   };  | 
757  |  |  | 
758  |  |   unsigned int get_size () const  | 
759  | 0  |   { | 
760  | 0  |     switch (u.version.major) { | 
761  | 0  |     case 1: return u.version1.get_size ();  | 
762  | 0  | #ifndef HB_NO_BEYOND_64K  | 
763  | 0  |     case 2: return u.version2.get_size ();  | 
764  | 0  | #endif  | 
765  | 0  |     default: return u.version.static_size;  | 
766  | 0  |     }  | 
767  | 0  |   }  | 
768  |  |  | 
769  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
770  | 22  |   { | 
771  | 22  |     TRACE_SANITIZE (this);  | 
772  | 22  |     if (unlikely (!u.version.sanitize (c))) return_trace (false);  | 
773  | 22  |     hb_barrier ();  | 
774  | 22  |     switch (u.version.major) { | 
775  | 22  |     case 1: return_trace (u.version1.sanitize (c));  | 
776  |  | #ifndef HB_NO_BEYOND_64K  | 
777  |  |     case 2: return_trace (u.version2.sanitize (c));  | 
778  |  | #endif  | 
779  | 0  |     default: return_trace (true);  | 
780  | 22  |     }  | 
781  | 22  |   }  | 
782  |  |  | 
783  |  |   bool subset (hb_subset_context_t *c) const  | 
784  | 0  |   { | 
785  | 0  |     switch (u.version.major) { | 
786  | 0  |     case 1: return u.version1.subset (c);  | 
787  | 0  | #ifndef HB_NO_BEYOND_64K  | 
788  | 0  |     case 2: return u.version2.subset (c);  | 
789  | 0  | #endif  | 
790  | 0  |     default: return false;  | 
791  | 0  |     }  | 
792  | 0  |   }  | 
793  |  |  | 
794  |  |   bool has_glyph_classes () const  | 
795  | 240k  |   { | 
796  | 240k  |     switch (u.version.major) { | 
797  | 4.61k  |     case 1: return u.version1.glyphClassDef != 0;  | 
798  |  | #ifndef HB_NO_BEYOND_64K  | 
799  |  |     case 2: return u.version2.glyphClassDef != 0;  | 
800  |  | #endif  | 
801  | 235k  |     default: return false;  | 
802  | 240k  |     }  | 
803  | 240k  |   }  | 
804  |  |   const ClassDef &get_glyph_class_def () const  | 
805  | 9.54k  |   { | 
806  | 9.54k  |     switch (u.version.major) { | 
807  | 23  |     case 1: return this+u.version1.glyphClassDef;  | 
808  |  | #ifndef HB_NO_BEYOND_64K  | 
809  |  |     case 2: return this+u.version2.glyphClassDef;  | 
810  |  | #endif  | 
811  | 9.52k  |     default: return Null(ClassDef);  | 
812  | 9.54k  |     }  | 
813  | 9.54k  |   }  | 
814  |  |   bool has_attach_list () const  | 
815  | 0  |   { | 
816  | 0  |     switch (u.version.major) { | 
817  | 0  |     case 1: return u.version1.attachList != 0;  | 
818  | 0  | #ifndef HB_NO_BEYOND_64K  | 
819  | 0  |     case 2: return u.version2.attachList != 0;  | 
820  | 0  | #endif  | 
821  | 0  |     default: return false;  | 
822  | 0  |     }  | 
823  | 0  |   }  | 
824  |  |   const AttachList &get_attach_list () const  | 
825  | 0  |   { | 
826  | 0  |     switch (u.version.major) { | 
827  | 0  |     case 1: return this+u.version1.attachList;  | 
828  |  | #ifndef HB_NO_BEYOND_64K  | 
829  |  |     case 2: return this+u.version2.attachList;  | 
830  |  | #endif  | 
831  | 0  |     default: return Null(AttachList);  | 
832  | 0  |     }  | 
833  | 0  |   }  | 
834  |  |   bool has_lig_carets () const  | 
835  | 0  |   { | 
836  | 0  |     switch (u.version.major) { | 
837  | 0  |     case 1: return u.version1.ligCaretList != 0;  | 
838  | 0  | #ifndef HB_NO_BEYOND_64K  | 
839  | 0  |     case 2: return u.version2.ligCaretList != 0;  | 
840  | 0  | #endif  | 
841  | 0  |     default: return false;  | 
842  | 0  |     }  | 
843  | 0  |   }  | 
844  |  |   const LigCaretList &get_lig_caret_list () const  | 
845  | 0  |   { | 
846  | 0  |     switch (u.version.major) { | 
847  | 0  |     case 1: return this+u.version1.ligCaretList;  | 
848  |  | #ifndef HB_NO_BEYOND_64K  | 
849  |  |     case 2: return this+u.version2.ligCaretList;  | 
850  |  | #endif  | 
851  | 0  |     default: return Null(LigCaretList);  | 
852  | 0  |     }  | 
853  | 0  |   }  | 
854  |  |   bool has_mark_attachment_types () const  | 
855  | 0  |   { | 
856  | 0  |     switch (u.version.major) { | 
857  | 0  |     case 1: return u.version1.markAttachClassDef != 0;  | 
858  | 0  | #ifndef HB_NO_BEYOND_64K  | 
859  | 0  |     case 2: return u.version2.markAttachClassDef != 0;  | 
860  | 0  | #endif  | 
861  | 0  |     default: return false;  | 
862  | 0  |     }  | 
863  | 0  |   }  | 
864  |  |   const ClassDef &get_mark_attach_class_def () const  | 
865  | 0  |   { | 
866  | 0  |     switch (u.version.major) { | 
867  | 0  |     case 1: return this+u.version1.markAttachClassDef;  | 
868  |  | #ifndef HB_NO_BEYOND_64K  | 
869  |  |     case 2: return this+u.version2.markAttachClassDef;  | 
870  |  | #endif  | 
871  | 0  |     default: return Null(ClassDef);  | 
872  | 0  |     }  | 
873  | 0  |   }  | 
874  |  |   bool has_mark_glyph_sets () const  | 
875  | 0  |   { | 
876  | 0  |     switch (u.version.major) { | 
877  | 0  |     case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () && u.version1.markGlyphSetsDef != 0;  | 
878  | 0  | #ifndef HB_NO_BEYOND_64K  | 
879  | 0  |     case 2: return u.version2.markGlyphSetsDef != 0;  | 
880  | 0  | #endif  | 
881  | 0  |     default: return false;  | 
882  | 0  |     }  | 
883  | 0  |   }  | 
884  |  |   const MarkGlyphSets &get_mark_glyph_sets () const  | 
885  | 1.79k  |   { | 
886  | 1.79k  |     switch (u.version.major) { | 
887  | 22  |     case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);  | 
888  |  | #ifndef HB_NO_BEYOND_64K  | 
889  |  |     case 2: return this+u.version2.markGlyphSetsDef;  | 
890  |  | #endif  | 
891  | 1.76k  |     default: return Null(MarkGlyphSets);  | 
892  | 1.79k  |     }  | 
893  | 1.79k  |   }  | 
894  |  |   bool has_var_store () const  | 
895  | 0  |   { | 
896  | 0  |     switch (u.version.major) { | 
897  | 0  |     case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () && u.version1.varStore != 0;  | 
898  | 0  | #ifndef HB_NO_BEYOND_64K  | 
899  | 0  |     case 2: return u.version2.varStore != 0;  | 
900  | 0  | #endif  | 
901  | 0  |     default: return false;  | 
902  | 0  |     }  | 
903  | 0  |   }  | 
904  |  |   const ItemVariationStore &get_var_store () const  | 
905  | 596k  |   { | 
906  | 596k  |     switch (u.version.major) { | 
907  | 7.70k  |     case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () ? this+u.version1.varStore : Null(ItemVariationStore);  | 
908  |  | #ifndef HB_NO_BEYOND_64K  | 
909  |  |     case 2: return this+u.version2.varStore;  | 
910  |  | #endif  | 
911  | 588k  |     default: return Null(ItemVariationStore);  | 
912  | 596k  |     }  | 
913  | 596k  |   }  | 
914  |  |  | 
915  |  |  | 
916  | 0  |   bool has_data () const { return u.version.to_int (); } | 
917  |  |   unsigned int get_glyph_class (hb_codepoint_t glyph) const  | 
918  | 9.54k  |   { return get_glyph_class_def ().get_class (glyph); } | 
919  |  |   void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const  | 
920  | 0  |   { get_glyph_class_def ().collect_class (glyphs, klass); } | 
921  |  |  | 
922  |  |   unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const  | 
923  | 0  |   { return get_mark_attach_class_def ().get_class (glyph); } | 
924  |  |  | 
925  |  |   unsigned int get_attach_points (hb_codepoint_t glyph_id,  | 
926  |  |           unsigned int start_offset,  | 
927  |  |           unsigned int *point_count /* IN/OUT */,  | 
928  |  |           unsigned int *point_array /* OUT */) const  | 
929  | 0  |   { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); } | 
930  |  |  | 
931  |  |   unsigned int get_lig_carets (hb_font_t *font,  | 
932  |  |              hb_direction_t direction,  | 
933  |  |              hb_codepoint_t glyph_id,  | 
934  |  |              unsigned int start_offset,  | 
935  |  |              unsigned int *caret_count /* IN/OUT */,  | 
936  |  |              hb_position_t *caret_array /* OUT */) const  | 
937  | 0  |   { return get_lig_caret_list ().get_lig_carets (font, | 
938  | 0  |              direction, glyph_id, get_var_store(),  | 
939  | 0  |              start_offset, caret_count, caret_array); }  | 
940  |  |  | 
941  |  |   bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const  | 
942  | 0  |   { return get_mark_glyph_sets ().covers (set_index, glyph_id); } | 
943  |  |  | 
944  |  |   /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing  | 
945  |  |    * glyph class and other bits, and high 8-bit the mark attachment type (if any).  | 
946  |  |    * Not to be confused with lookup_props which is very similar. */  | 
947  |  |   unsigned int get_glyph_props (hb_codepoint_t glyph) const  | 
948  | 9.54k  |   { | 
949  | 9.54k  |     unsigned int klass = get_glyph_class (glyph);  | 
950  |  |  | 
951  | 9.54k  |     static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), "");  | 
952  | 9.54k  |     static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), "");  | 
953  | 9.54k  |     static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), "");  | 
954  |  |  | 
955  | 9.54k  |     switch (klass) { | 
956  | 9.52k  |     default:      return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;  | 
957  | 23  |     case BaseGlyph:   return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;  | 
958  | 0  |     case LigatureGlyph:   return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;  | 
959  | 0  |     case MarkGlyph:  | 
960  | 0  |     klass = get_mark_attachment_type (glyph);  | 
961  | 0  |     return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8);  | 
962  | 9.54k  |     }  | 
963  | 9.54k  |   }  | 
964  |  |  | 
965  |  |   HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,  | 
966  |  |            hb_face_t *face) const;  | 
967  |  |  | 
968  |  |   struct accelerator_t  | 
969  |  |   { | 
970  |  |     accelerator_t (hb_face_t *face)  | 
971  | 1.79k  |     { | 
972  | 1.79k  |       table = hb_sanitize_context_t ().reference_table<GDEF> (face);  | 
973  | 1.79k  |       if (unlikely (table->is_blocklisted (table.get_blob (), face)))  | 
974  | 0  |       { | 
975  | 0  |   hb_blob_destroy (table.get_blob ());  | 
976  | 0  |   table = hb_blob_get_empty ();  | 
977  | 0  |       }  | 
978  |  |  | 
979  | 1.79k  | #ifndef HB_NO_GDEF_CACHE  | 
980  | 1.79k  |       table->get_mark_glyph_sets ().collect_coverage (mark_glyph_sets);  | 
981  | 1.79k  | #endif  | 
982  | 1.79k  |     }  | 
983  | 1.79k  |     ~accelerator_t () { table.destroy (); } | 
984  |  |  | 
985  |  |     unsigned int get_glyph_props (hb_codepoint_t glyph) const  | 
986  | 956k  |     { | 
987  | 956k  |       unsigned v;  | 
988  |  |  | 
989  | 956k  | #ifndef HB_NO_GDEF_CACHE  | 
990  | 956k  |       if (glyph_props_cache.get (glyph, &v))  | 
991  | 946k  |         return v;  | 
992  | 9.54k  | #endif  | 
993  |  |  | 
994  | 9.54k  |       v = table->get_glyph_props (glyph);  | 
995  |  |  | 
996  | 9.54k  | #ifndef HB_NO_GDEF_CACHE  | 
997  | 9.54k  |       if (likely (table.get_blob ())) // Don't try setting if we are the null instance!  | 
998  | 9.54k  |   glyph_props_cache.set (glyph, v);  | 
999  | 9.54k  | #endif  | 
1000  |  |  | 
1001  | 9.54k  |       return v;  | 
1002  |  |  | 
1003  | 956k  |     }  | 
1004  |  |  | 
1005  |  |     bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const  | 
1006  | 0  |     { | 
1007  | 0  |       return  | 
1008  | 0  | #ifndef HB_NO_GDEF_CACHE  | 
1009  | 0  |        mark_glyph_sets[set_index].may_have (glyph_id)  | 
1010  |  | #else  | 
1011  |  |        table->mark_set_covers (set_index, glyph_id)  | 
1012  |  | #endif  | 
1013  | 0  |       ;  | 
1014  | 0  |     }  | 
1015  |  |  | 
1016  |  |     hb_blob_ptr_t<GDEF> table;  | 
1017  |  | #ifndef HB_NO_GDEF_CACHE  | 
1018  |  |     hb_vector_t<hb_bit_set_t> mark_glyph_sets;  | 
1019  |  |     mutable hb_cache_t<21, 3> glyph_props_cache;  | 
1020  |  |     static_assert (sizeof (glyph_props_cache) == 512, "");  | 
1021  |  | #endif  | 
1022  |  |   };  | 
1023  |  |  | 
1024  |  |   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const  | 
1025  | 0  |   { get_lig_caret_list ().collect_variation_indices (c); } | 
1026  |  |  | 
1027  |  |   protected:  | 
1028  |  |   union { | 
1029  |  |   FixedVersion<>    version;  /* Version identifier */  | 
1030  |  |   GDEFVersion1_2<SmallTypes>  version1;  | 
1031  |  | #ifndef HB_NO_BEYOND_64K  | 
1032  |  |   GDEFVersion1_2<MediumTypes> version2;  | 
1033  |  | #endif  | 
1034  |  |   } u;  | 
1035  |  |   public:  | 
1036  |  |   DEFINE_SIZE_MIN (4);  | 
1037  |  | };  | 
1038  |  |  | 
1039  |  | struct GDEF_accelerator_t : GDEF::accelerator_t { | 
1040  | 1.79k  |   GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {} | 
1041  |  | };  | 
1042  |  |  | 
1043  |  | } /* namespace OT */  | 
1044  |  |  | 
1045  |  |  | 
1046  |  | #endif /* OT_LAYOUT_GDEF_GDEF_HH */  |