/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 | | /* Work budget shared by all leaf glyphs loaded from glyf/CFF/CFF2, |
40 | | * so their per-glyph work limits cannot multiply with our own |
41 | | * composite-graph limits. */ |
42 | | mutable int64_t budget_left; |
43 | | hb_varc_scratch_t &scratch; |
44 | | }; |
45 | | |
46 | | struct VarComponent |
47 | | { |
48 | | enum class flags_t : uint32_t |
49 | | { |
50 | | RESET_UNSPECIFIED_AXES = 1u << 0, |
51 | | HAVE_AXES = 1u << 1, |
52 | | AXIS_VALUES_HAVE_VARIATION = 1u << 2, |
53 | | TRANSFORM_HAS_VARIATION = 1u << 3, |
54 | | HAVE_TRANSLATE_X = 1u << 4, |
55 | | HAVE_TRANSLATE_Y = 1u << 5, |
56 | | HAVE_ROTATION = 1u << 6, |
57 | | HAVE_CONDITION = 1u << 7, |
58 | | HAVE_SCALE_X = 1u << 8, |
59 | | HAVE_SCALE_Y = 1u << 9, |
60 | | HAVE_TCENTER_X = 1u << 10, |
61 | | HAVE_TCENTER_Y = 1u << 11, |
62 | | GID_IS_24BIT = 1u << 12, |
63 | | HAVE_SKEW_X = 1u << 13, |
64 | | HAVE_SKEW_Y = 1u << 14, |
65 | | RESERVED_MASK = ~((1u << 15) - 1), |
66 | | }; |
67 | | |
68 | | HB_INTERNAL hb_ubytes_t |
69 | | get_path_at (const hb_varc_context_t &c, |
70 | | hb_codepoint_t parent_gid, |
71 | | hb_array_t<const int> coords, |
72 | | hb_transform_t<> transform, |
73 | | hb_ubytes_t record, |
74 | | hb_scalar_cache_t *cache = nullptr) const; |
75 | | }; |
76 | | |
77 | | struct VarCompositeGlyph |
78 | | { |
79 | | static void |
80 | | get_path_at (const hb_varc_context_t &c, |
81 | | hb_codepoint_t gid, |
82 | | hb_array_t<const int> coords, |
83 | | hb_transform_t<> transform, |
84 | | hb_ubytes_t record, |
85 | | hb_scalar_cache_t *cache) |
86 | 0 | { |
87 | 0 | while (record) |
88 | 0 | { |
89 | 0 | const VarComponent &comp = * (const VarComponent *) (record.arrayZ); |
90 | 0 | record = comp.get_path_at (c, |
91 | 0 | gid, |
92 | 0 | coords, transform, |
93 | 0 | record, |
94 | 0 | cache); |
95 | 0 | } |
96 | 0 | } |
97 | | }; |
98 | | |
99 | | HB_MARK_AS_FLAG_T (VarComponent::flags_t); |
100 | | |
101 | | struct VARC |
102 | | { |
103 | | friend struct VarComponent; |
104 | | |
105 | | static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C'); |
106 | | |
107 | | HB_INTERNAL bool |
108 | | get_path_at (const hb_varc_context_t &c, |
109 | | hb_codepoint_t gid, |
110 | | hb_array_t<const int> coords, |
111 | | hb_transform_t<> transform = HB_TRANSFORM_IDENTITY, |
112 | | hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID, |
113 | | hb_scalar_cache_t *parent_cache = nullptr) const; |
114 | | |
115 | | bool |
116 | | get_path (hb_font_t *font, |
117 | | hb_codepoint_t gid, |
118 | | hb_draw_session_t &draw_session, |
119 | | hb_varc_scratch_t &scratch) const |
120 | 0 | { |
121 | 0 | hb_varc_context_t c {font, |
122 | 0 | &draw_session, |
123 | 0 | nullptr, |
124 | 0 | hb_decycler_t {}, |
125 | 0 | HB_MAX_GRAPH_EDGE_COUNT, |
126 | 0 | HB_MAX_NESTING_LEVEL, |
127 | 0 | HB_VARC_MAX_WORK, |
128 | 0 | scratch}; |
129 | |
|
130 | 0 | return get_path_at (c, gid, |
131 | 0 | hb_array (font->coords, font->num_coords)); |
132 | 0 | } |
133 | | |
134 | | bool |
135 | | get_extents (hb_font_t *font, |
136 | | hb_codepoint_t gid, |
137 | | hb_extents_t<> *extents, |
138 | | hb_varc_scratch_t &scratch) const |
139 | 0 | { |
140 | 0 | hb_varc_context_t c {font, |
141 | 0 | nullptr, |
142 | 0 | extents, |
143 | 0 | hb_decycler_t {}, |
144 | 0 | HB_MAX_GRAPH_EDGE_COUNT, |
145 | 0 | HB_MAX_NESTING_LEVEL, |
146 | 0 | HB_VARC_MAX_WORK, |
147 | 0 | scratch}; |
148 | |
|
149 | 0 | return get_path_at (c, gid, |
150 | 0 | hb_array (font->coords, font->num_coords)); |
151 | 0 | } |
152 | | |
153 | | bool sanitize (hb_sanitize_context_t *c) const |
154 | 0 | { |
155 | 0 | TRACE_SANITIZE (this); |
156 | 0 | return_trace (version.sanitize (c) && |
157 | 0 | hb_barrier () && |
158 | 0 | version.major == 1 && |
159 | 0 | coverage.sanitize (c, this) && |
160 | 0 | varStore.sanitize (c, this) && |
161 | 0 | conditionList.sanitize (c, this) && |
162 | 0 | axisIndicesList.sanitize (c, this) && |
163 | 0 | glyphRecords.sanitize (c, this)); |
164 | 0 | } |
165 | | |
166 | | struct accelerator_t |
167 | | { |
168 | | friend struct VarComponent; |
169 | | |
170 | | accelerator_t (hb_face_t *face) |
171 | 0 | { |
172 | 0 | table = hb_sanitize_context_t ().reference_table<VARC> (face); |
173 | 0 | } |
174 | | ~accelerator_t () |
175 | 0 | { |
176 | 0 | auto *scratch = cached_scratch.get_relaxed (); |
177 | 0 | if (scratch) |
178 | 0 | { |
179 | 0 | scratch->~hb_varc_scratch_t (); |
180 | 0 | hb_free (scratch); |
181 | 0 | } |
182 | |
|
183 | 0 | table.destroy (); |
184 | 0 | } |
185 | | |
186 | | bool |
187 | | get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const |
188 | 0 | { |
189 | 0 | if (!table->has_data ()) return false; |
190 | | |
191 | 0 | auto *scratch = acquire_scratch (); |
192 | 0 | if (unlikely (!scratch)) return true; |
193 | 0 | bool ret = table->get_path (font, gid, draw_session, *scratch); |
194 | 0 | release_scratch (scratch); |
195 | 0 | return ret; |
196 | 0 | } |
197 | | |
198 | | bool |
199 | | get_extents (hb_font_t *font, |
200 | | hb_codepoint_t gid, |
201 | | hb_glyph_extents_t *extents) const |
202 | 0 | { |
203 | 0 | #ifndef HB_NO_DRAW |
204 | 0 | if (!table->has_data ()) return false; |
205 | | |
206 | 0 | hb_extents_t<> f_extents; |
207 | |
|
208 | 0 | auto *scratch = acquire_scratch (); |
209 | 0 | if (unlikely (!scratch)) return true; |
210 | 0 | bool ret = table->get_extents (font, gid, &f_extents, *scratch); |
211 | 0 | release_scratch (scratch); |
212 | |
|
213 | 0 | if (ret) |
214 | 0 | *extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0); |
215 | |
|
216 | 0 | return ret; |
217 | | #else |
218 | | return false; |
219 | | #endif |
220 | 0 | } |
221 | | |
222 | | private: |
223 | | |
224 | | hb_varc_scratch_t *acquire_scratch () const |
225 | 0 | { |
226 | 0 | hb_varc_scratch_t *scratch = cached_scratch.get_acquire (); |
227 | |
|
228 | 0 | if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) |
229 | 0 | { |
230 | 0 | scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t)); |
231 | 0 | if (unlikely (!scratch)) |
232 | 0 | return nullptr; |
233 | 0 | } |
234 | | |
235 | 0 | return scratch; |
236 | 0 | } |
237 | | void release_scratch (hb_varc_scratch_t *scratch) const |
238 | 0 | { |
239 | 0 | if (!cached_scratch.cmpexch (nullptr, scratch)) |
240 | 0 | { |
241 | 0 | scratch->~hb_varc_scratch_t (); |
242 | 0 | hb_free (scratch); |
243 | 0 | } |
244 | 0 | } |
245 | | |
246 | | private: |
247 | | hb_blob_ptr_t<VARC> table; |
248 | | mutable hb_atomic_t<hb_varc_scratch_t *> cached_scratch; |
249 | | }; |
250 | | |
251 | 0 | bool has_data () const { return version.major != 0; } |
252 | | |
253 | | protected: |
254 | | FixedVersion<> version; /* Version identifier */ |
255 | | Offset32To<Coverage> coverage; |
256 | | Offset32To<MultiItemVariationStore> varStore; |
257 | | Offset32To<ConditionList> conditionList; |
258 | | Offset32To<TupleList> axisIndicesList; |
259 | | Offset32To<CFF2Index/*Of<VarCompositeGlyph>*/> glyphRecords; |
260 | | public: |
261 | | DEFINE_SIZE_STATIC (24); |
262 | | }; |
263 | | |
264 | | struct VARC_accelerator_t : VARC::accelerator_t { |
265 | 0 | VARC_accelerator_t (hb_face_t *face) : VARC::accelerator_t (face) {} |
266 | | }; |
267 | | |
268 | | #endif |
269 | | |
270 | | //} |
271 | | |
272 | | } |
273 | | |
274 | | #endif /* OT_VAR_VARC_VARC_HH */ |