/src/harfbuzz/src/OT/Var/VARC/VARC.hh
Line  | Count  | Source  | 
1  |  | #ifndef OT_VAR_VARC_VARC_HH  | 
2  |  | #define OT_VAR_VARC_VARC_HH  | 
3  |  |  | 
4  |  | #include "../../../hb-decycler.hh"  | 
5  |  | #include "../../../hb-geometry.hh"  | 
6  |  | #include "../../../hb-ot-layout-common.hh"  | 
7  |  | #include "../../../hb-ot-glyf-table.hh"  | 
8  |  | #include "../../../hb-ot-cff2-table.hh"  | 
9  |  | #include "../../../hb-ot-cff1-table.hh"  | 
10  |  |  | 
11  |  | #include "coord-setter.hh"  | 
12  |  |  | 
13  |  | namespace OT { | 
14  |  |  | 
15  |  | //namespace Var { | 
16  |  |  | 
17  |  | /*  | 
18  |  |  * VARC -- Variable Composites  | 
19  |  |  * https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md  | 
20  |  |  */  | 
21  |  |  | 
22  |  | #ifndef HB_NO_VAR_COMPOSITES  | 
23  |  |  | 
24  |  | struct hb_varc_scratch_t  | 
25  |  | { | 
26  |  |   hb_vector_t<unsigned> axisIndices;  | 
27  |  |   hb_vector_t<float> axisValues;  | 
28  |  |   hb_glyf_scratch_t glyf_scratch;  | 
29  |  | };  | 
30  |  |  | 
31  |  | struct hb_varc_context_t  | 
32  |  | { | 
33  |  |   hb_font_t *font;  | 
34  |  |   hb_draw_session_t *draw_session;  | 
35  |  |   hb_extents_t<> *extents;  | 
36  |  |   mutable hb_decycler_t decycler;  | 
37  |  |   mutable signed edges_left;  | 
38  |  |   mutable signed depth_left;  | 
39  |  |   hb_varc_scratch_t &scratch;  | 
40  |  | };  | 
41  |  |  | 
42  |  | struct VarComponent  | 
43  |  | { | 
44  |  |   enum class flags_t : uint32_t  | 
45  |  |   { | 
46  |  |     RESET_UNSPECIFIED_AXES  = 1u << 0,  | 
47  |  |     HAVE_AXES     = 1u << 1,  | 
48  |  |     AXIS_VALUES_HAVE_VARIATION  = 1u << 2,  | 
49  |  |     TRANSFORM_HAS_VARIATION = 1u << 3,  | 
50  |  |     HAVE_TRANSLATE_X    = 1u << 4,  | 
51  |  |     HAVE_TRANSLATE_Y    = 1u << 5,  | 
52  |  |     HAVE_ROTATION   = 1u << 6,  | 
53  |  |     HAVE_CONDITION    = 1u << 7,  | 
54  |  |     HAVE_SCALE_X    = 1u << 8,  | 
55  |  |     HAVE_SCALE_Y    = 1u << 9,  | 
56  |  |     HAVE_TCENTER_X    = 1u << 10,  | 
57  |  |     HAVE_TCENTER_Y    = 1u << 11,  | 
58  |  |     GID_IS_24BIT    = 1u << 12,  | 
59  |  |     HAVE_SKEW_X     = 1u << 13,  | 
60  |  |     HAVE_SKEW_Y     = 1u << 14,  | 
61  |  |     RESERVED_MASK   = ~((1u << 15) - 1),  | 
62  |  |   };  | 
63  |  |  | 
64  |  |   HB_INTERNAL hb_ubytes_t  | 
65  |  |   get_path_at (const hb_varc_context_t &c,  | 
66  |  |          hb_codepoint_t parent_gid,  | 
67  |  |          hb_array_t<const int> coords,  | 
68  |  |          hb_transform_t<> transform,  | 
69  |  |          hb_ubytes_t record,  | 
70  |  |          hb_scalar_cache_t *cache = nullptr) const;  | 
71  |  | };  | 
72  |  |  | 
73  |  | struct VarCompositeGlyph  | 
74  |  | { | 
75  |  |   static void  | 
76  |  |   get_path_at (const hb_varc_context_t &c,  | 
77  |  |          hb_codepoint_t gid,  | 
78  |  |          hb_array_t<const int> coords,  | 
79  |  |          hb_transform_t<> transform,  | 
80  |  |          hb_ubytes_t record,  | 
81  |  |          hb_scalar_cache_t *cache)  | 
82  | 0  |   { | 
83  | 0  |     while (record)  | 
84  | 0  |     { | 
85  | 0  |       const VarComponent &comp = * (const VarComponent *) (record.arrayZ);  | 
86  | 0  |       record = comp.get_path_at (c,  | 
87  | 0  |          gid,  | 
88  | 0  |          coords, transform,  | 
89  | 0  |          record,  | 
90  | 0  |          cache);  | 
91  | 0  |     }  | 
92  | 0  |   }  | 
93  |  | };  | 
94  |  |  | 
95  |  | HB_MARK_AS_FLAG_T (VarComponent::flags_t);  | 
96  |  |  | 
97  |  | struct VARC  | 
98  |  | { | 
99  |  |   friend struct VarComponent;  | 
100  |  |  | 
101  |  |   static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C'); | 
102  |  |  | 
103  |  |   HB_INTERNAL bool  | 
104  |  |   get_path_at (const hb_varc_context_t &c,  | 
105  |  |          hb_codepoint_t gid,  | 
106  |  |          hb_array_t<const int> coords,  | 
107  |  |          hb_transform_t<> transform = HB_TRANSFORM_IDENTITY,  | 
108  |  |          hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID,  | 
109  |  |          hb_scalar_cache_t *parent_cache = nullptr) const;  | 
110  |  |  | 
111  |  |   bool  | 
112  |  |   get_path (hb_font_t *font,  | 
113  |  |       hb_codepoint_t gid,  | 
114  |  |       hb_draw_session_t &draw_session,  | 
115  |  |       hb_varc_scratch_t &scratch) const  | 
116  | 0  |   { | 
117  | 0  |     hb_varc_context_t c {font, | 
118  | 0  |        &draw_session,  | 
119  | 0  |        nullptr,  | 
120  | 0  |        hb_decycler_t {}, | 
121  | 0  |        HB_MAX_GRAPH_EDGE_COUNT,  | 
122  | 0  |        HB_MAX_NESTING_LEVEL,  | 
123  | 0  |        scratch};  | 
124  |  | 
  | 
125  | 0  |     return get_path_at (c, gid,  | 
126  | 0  |       hb_array (font->coords, font->num_coords));  | 
127  | 0  |   }  | 
128  |  |  | 
129  |  |   bool  | 
130  |  |   get_extents (hb_font_t *font,  | 
131  |  |          hb_codepoint_t gid,  | 
132  |  |          hb_extents_t<> *extents,  | 
133  |  |          hb_varc_scratch_t &scratch) const  | 
134  | 0  |   { | 
135  | 0  |     hb_varc_context_t c {font, | 
136  | 0  |        nullptr,  | 
137  | 0  |        extents,  | 
138  | 0  |        hb_decycler_t {}, | 
139  | 0  |        HB_MAX_GRAPH_EDGE_COUNT,  | 
140  | 0  |        HB_MAX_NESTING_LEVEL,  | 
141  | 0  |        scratch};  | 
142  |  | 
  | 
143  | 0  |     return get_path_at (c, gid,  | 
144  | 0  |       hb_array (font->coords, font->num_coords));  | 
145  | 0  |   }  | 
146  |  |  | 
147  |  |   bool sanitize (hb_sanitize_context_t *c) const  | 
148  | 0  |   { | 
149  | 0  |     TRACE_SANITIZE (this);  | 
150  | 0  |     return_trace (version.sanitize (c) &&  | 
151  | 0  |       hb_barrier () &&  | 
152  | 0  |       version.major == 1 &&  | 
153  | 0  |       coverage.sanitize (c, this) &&  | 
154  | 0  |       varStore.sanitize (c, this) &&  | 
155  | 0  |       conditionList.sanitize (c, this) &&  | 
156  | 0  |       axisIndicesList.sanitize (c, this) &&  | 
157  | 0  |       glyphRecords.sanitize (c, this));  | 
158  | 0  |   }  | 
159  |  |  | 
160  |  |   struct accelerator_t  | 
161  |  |   { | 
162  |  |     friend struct VarComponent;  | 
163  |  |  | 
164  |  |     accelerator_t (hb_face_t *face)  | 
165  | 0  |     { | 
166  | 0  |       table = hb_sanitize_context_t ().reference_table<VARC> (face);  | 
167  | 0  |     }  | 
168  |  |     ~accelerator_t ()  | 
169  | 0  |     { | 
170  | 0  |       auto *scratch = cached_scratch.get_relaxed ();  | 
171  | 0  |       if (scratch)  | 
172  | 0  |       { | 
173  | 0  |   scratch->~hb_varc_scratch_t ();  | 
174  | 0  |   hb_free (scratch);  | 
175  | 0  |       }  | 
176  |  | 
  | 
177  | 0  |       table.destroy ();  | 
178  | 0  |     }  | 
179  |  |  | 
180  |  |     bool  | 
181  |  |     get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const  | 
182  | 0  |     { | 
183  | 0  |       if (!table->has_data ()) return false;  | 
184  |  |  | 
185  | 0  |       auto *scratch = acquire_scratch ();  | 
186  | 0  |       if (unlikely (!scratch)) return true;  | 
187  | 0  |       bool ret = table->get_path (font, gid, draw_session, *scratch);  | 
188  | 0  |       release_scratch (scratch);  | 
189  | 0  |       return ret;  | 
190  | 0  |     }  | 
191  |  |  | 
192  |  |     bool  | 
193  |  |     get_extents (hb_font_t *font,  | 
194  |  |      hb_codepoint_t gid,  | 
195  |  |      hb_glyph_extents_t *extents) const  | 
196  | 0  |     { | 
197  | 0  | #ifndef HB_NO_DRAW  | 
198  | 0  |       if (!table->has_data ()) return false;  | 
199  |  |  | 
200  | 0  |       hb_extents_t<> f_extents;  | 
201  |  | 
  | 
202  | 0  |       auto *scratch = acquire_scratch ();  | 
203  | 0  |       if (unlikely (!scratch)) return true;  | 
204  | 0  |       bool ret = table->get_extents (font, gid, &f_extents, *scratch);  | 
205  | 0  |       release_scratch (scratch);  | 
206  |  | 
  | 
207  | 0  |       if (ret)  | 
208  | 0  |   *extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0);  | 
209  |  | 
  | 
210  | 0  |       return ret;  | 
211  |  | #else  | 
212  |  |       return false;  | 
213  |  | #endif  | 
214  | 0  |     }  | 
215  |  |  | 
216  |  |     private:  | 
217  |  |  | 
218  |  |     hb_varc_scratch_t *acquire_scratch () const  | 
219  | 0  |     { | 
220  | 0  |       hb_varc_scratch_t *scratch = cached_scratch.get_acquire ();  | 
221  |  | 
  | 
222  | 0  |       if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))  | 
223  | 0  |       { | 
224  | 0  |   scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t));  | 
225  | 0  |   if (unlikely (!scratch))  | 
226  | 0  |     return nullptr;  | 
227  | 0  |       }  | 
228  |  |  | 
229  | 0  |       return scratch;  | 
230  | 0  |     }  | 
231  |  |     void release_scratch (hb_varc_scratch_t *scratch) const  | 
232  | 0  |     { | 
233  | 0  |       if (!cached_scratch.cmpexch (nullptr, scratch))  | 
234  | 0  |       { | 
235  | 0  |   scratch->~hb_varc_scratch_t ();  | 
236  | 0  |   hb_free (scratch);  | 
237  | 0  |       }  | 
238  | 0  |     }  | 
239  |  |  | 
240  |  |     private:  | 
241  |  |     hb_blob_ptr_t<VARC> table;  | 
242  |  |     mutable hb_atomic_t<hb_varc_scratch_t *> cached_scratch;  | 
243  |  |   };  | 
244  |  |  | 
245  | 0  |   bool has_data () const { return version.major != 0; } | 
246  |  |  | 
247  |  |   protected:  | 
248  |  |   FixedVersion<> version; /* Version identifier */  | 
249  |  |   Offset32To<Coverage> coverage;  | 
250  |  |   Offset32To<MultiItemVariationStore> varStore;  | 
251  |  |   Offset32To<ConditionList> conditionList;  | 
252  |  |   Offset32To<TupleList> axisIndicesList;  | 
253  |  |   Offset32To<CFF2Index/*Of<VarCompositeGlyph>*/> glyphRecords;  | 
254  |  |   public:  | 
255  |  |   DEFINE_SIZE_STATIC (24);  | 
256  |  | };  | 
257  |  |  | 
258  |  | struct VARC_accelerator_t : VARC::accelerator_t { | 
259  | 0  |   VARC_accelerator_t (hb_face_t *face) : VARC::accelerator_t (face) {} | 
260  |  | };  | 
261  |  |  | 
262  |  | #endif  | 
263  |  |  | 
264  |  | //}  | 
265  |  |  | 
266  |  | }  | 
267  |  |  | 
268  |  | #endif  /* OT_VAR_VARC_VARC_HH */  |