/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 | 2.46M | { |
83 | 16.4M | while (record) |
84 | 13.9M | { |
85 | 13.9M | const VarComponent &comp = * (const VarComponent *) (record.arrayZ); |
86 | 13.9M | record = comp.get_path_at (c, |
87 | 13.9M | gid, |
88 | 13.9M | coords, transform, |
89 | 13.9M | record, |
90 | 13.9M | cache); |
91 | 13.9M | } |
92 | 2.46M | } |
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 | 88.8k | { |
117 | 88.8k | hb_varc_context_t c {font, |
118 | 88.8k | &draw_session, |
119 | 88.8k | nullptr, |
120 | 88.8k | hb_decycler_t {}, |
121 | 88.8k | HB_MAX_GRAPH_EDGE_COUNT, |
122 | 88.8k | HB_MAX_NESTING_LEVEL, |
123 | 88.8k | scratch}; |
124 | | |
125 | 88.8k | return get_path_at (c, gid, |
126 | 88.8k | hb_array (font->coords, font->num_coords)); |
127 | 88.8k | } |
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 | 53.0k | { |
135 | 53.0k | hb_varc_context_t c {font, |
136 | 53.0k | nullptr, |
137 | 53.0k | extents, |
138 | 53.0k | hb_decycler_t {}, |
139 | 53.0k | HB_MAX_GRAPH_EDGE_COUNT, |
140 | 53.0k | HB_MAX_NESTING_LEVEL, |
141 | 53.0k | scratch}; |
142 | | |
143 | 53.0k | return get_path_at (c, gid, |
144 | 53.0k | hb_array (font->coords, font->num_coords)); |
145 | 53.0k | } |
146 | | |
147 | | bool sanitize (hb_sanitize_context_t *c) const |
148 | 9.22k | { |
149 | 9.22k | TRACE_SANITIZE (this); |
150 | 9.22k | return_trace (version.sanitize (c) && |
151 | 9.22k | hb_barrier () && |
152 | 9.22k | version.major == 1 && |
153 | 9.22k | coverage.sanitize (c, this) && |
154 | 9.22k | varStore.sanitize (c, this) && |
155 | 9.22k | conditionList.sanitize (c, this) && |
156 | 9.22k | axisIndicesList.sanitize (c, this) && |
157 | 9.22k | glyphRecords.sanitize (c, this)); |
158 | 9.22k | } |
159 | | |
160 | | struct accelerator_t |
161 | | { |
162 | | friend struct VarComponent; |
163 | | |
164 | | accelerator_t (hb_face_t *face) |
165 | 66.0k | { |
166 | 66.0k | table = hb_sanitize_context_t ().reference_table<VARC> (face); |
167 | 66.0k | } |
168 | | ~accelerator_t () |
169 | 66.0k | { |
170 | 66.0k | auto *scratch = cached_scratch.get_relaxed (); |
171 | 66.0k | if (scratch) |
172 | 2.99k | { |
173 | 2.99k | scratch->~hb_varc_scratch_t (); |
174 | 2.99k | hb_free (scratch); |
175 | 2.99k | } |
176 | | |
177 | 66.0k | table.destroy (); |
178 | 66.0k | } |
179 | | |
180 | | bool |
181 | | get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const |
182 | 1.68M | { |
183 | 1.68M | if (!table->has_data ()) return false; |
184 | | |
185 | 88.9k | auto *scratch = acquire_scratch (); |
186 | 88.9k | if (unlikely (!scratch)) return true; |
187 | 88.8k | bool ret = table->get_path (font, gid, draw_session, *scratch); |
188 | 88.8k | release_scratch (scratch); |
189 | 88.8k | return ret; |
190 | 88.9k | } |
191 | | |
192 | | bool |
193 | | get_extents (hb_font_t *font, |
194 | | hb_codepoint_t gid, |
195 | | hb_glyph_extents_t *extents) const |
196 | 1.78M | { |
197 | 1.78M | #ifndef HB_NO_DRAW |
198 | 1.78M | if (!table->has_data ()) return false; |
199 | | |
200 | 53.0k | hb_extents_t<> f_extents; |
201 | | |
202 | 53.0k | auto *scratch = acquire_scratch (); |
203 | 53.0k | if (unlikely (!scratch)) return true; |
204 | 53.0k | bool ret = table->get_extents (font, gid, &f_extents, *scratch); |
205 | 53.0k | release_scratch (scratch); |
206 | | |
207 | 53.0k | if (ret) |
208 | 44.4k | *extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0); |
209 | | |
210 | 53.0k | return ret; |
211 | | #else |
212 | | return false; |
213 | | #endif |
214 | 53.0k | } |
215 | | |
216 | | private: |
217 | | |
218 | | hb_varc_scratch_t *acquire_scratch () const |
219 | 141k | { |
220 | 141k | hb_varc_scratch_t *scratch = cached_scratch.get_acquire (); |
221 | | |
222 | 141k | if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) |
223 | 3.07k | { |
224 | 3.07k | scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t)); |
225 | 3.07k | if (unlikely (!scratch)) |
226 | 77 | return nullptr; |
227 | 3.07k | } |
228 | | |
229 | 141k | return scratch; |
230 | 141k | } |
231 | | void release_scratch (hb_varc_scratch_t *scratch) const |
232 | 141k | { |
233 | 141k | if (!cached_scratch.cmpexch (nullptr, scratch)) |
234 | 0 | { |
235 | 0 | scratch->~hb_varc_scratch_t (); |
236 | 0 | hb_free (scratch); |
237 | 0 | } |
238 | 141k | } |
239 | | |
240 | | private: |
241 | | hb_blob_ptr_t<VARC> table; |
242 | | mutable hb_atomic_t<hb_varc_scratch_t *> cached_scratch; |
243 | | }; |
244 | | |
245 | 3.47M | 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 | 66.0k | 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 */ |