comparison mupdf-source/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 #ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
2 #define OT_LAYOUT_GPOS_VALUEFORMAT_HH
3
4 #include "../../../hb-ot-layout-gsubgpos.hh"
5
6 namespace OT {
7 namespace Layout {
8 namespace GPOS_impl {
9
10 typedef HBUINT16 Value;
11
12 typedef UnsizedArrayOf<Value> ValueRecord;
13
14 struct ValueFormat : HBUINT16
15 {
16 enum Flags {
17 xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
18 yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
19 xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
20 yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
21 xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
22 yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
23 xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
24 yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
25 ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
26 reserved = 0xF000u, /* For future use */
27
28 devices = 0x00F0u /* Mask for having any Device table */
29 };
30
31 /* All fields are options. Only those available advance the value pointer. */
32 #if 0
33 HBINT16 xPlacement; /* Horizontal adjustment for
34 * placement--in design units */
35 HBINT16 yPlacement; /* Vertical adjustment for
36 * placement--in design units */
37 HBINT16 xAdvance; /* Horizontal adjustment for
38 * advance--in design units (only used
39 * for horizontal writing) */
40 HBINT16 yAdvance; /* Vertical adjustment for advance--in
41 * design units (only used for vertical
42 * writing) */
43 Offset16To<Device> xPlaDevice; /* Offset to Device table for
44 * horizontal placement--measured from
45 * beginning of PosTable (may be NULL) */
46 Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
47 * placement--measured from beginning
48 * of PosTable (may be NULL) */
49 Offset16To<Device> xAdvDevice; /* Offset to Device table for
50 * horizontal advance--measured from
51 * beginning of PosTable (may be NULL) */
52 Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
53 * advance--measured from beginning of
54 * PosTable (may be NULL) */
55 #endif
56
57 IntType& operator = (uint16_t i) { v = i; return *this; }
58
59 unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
60 unsigned int get_size () const { return get_len () * Value::static_size; }
61
62 hb_vector_t<unsigned> get_device_table_indices () const {
63 unsigned i = 0;
64 hb_vector_t<unsigned> result;
65 unsigned format = *this;
66
67 if (format & xPlacement) i++;
68 if (format & yPlacement) i++;
69 if (format & xAdvance) i++;
70 if (format & yAdvance) i++;
71
72 if (format & xPlaDevice) result.push (i++);
73 if (format & yPlaDevice) result.push (i++);
74 if (format & xAdvDevice) result.push (i++);
75 if (format & yAdvDevice) result.push (i++);
76
77 return result;
78 }
79
80 bool apply_value (hb_ot_apply_context_t *c,
81 const void *base,
82 const Value *values,
83 hb_glyph_position_t &glyph_pos) const
84 {
85 bool ret = false;
86 unsigned int format = *this;
87 if (!format) return ret;
88
89 hb_font_t *font = c->font;
90 bool horizontal =
91 #ifndef HB_NO_VERTICAL
92 HB_DIRECTION_IS_HORIZONTAL (c->direction)
93 #else
94 true
95 #endif
96 ;
97
98 if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
99 if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
100 if (format & xAdvance) {
101 if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
102 values++;
103 }
104 /* y_advance values grow downward but font-space grows upward, hence negation */
105 if (format & yAdvance) {
106 if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
107 values++;
108 }
109
110 if (!has_device ()) return ret;
111
112 bool use_x_device = font->x_ppem || font->num_coords;
113 bool use_y_device = font->y_ppem || font->num_coords;
114
115 if (!use_x_device && !use_y_device) return ret;
116
117 const VariationStore &store = c->var_store;
118 auto *cache = c->var_store_cache;
119
120 /* pixel -> fractional pixel */
121 if (format & xPlaDevice) {
122 if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
123 values++;
124 }
125 if (format & yPlaDevice) {
126 if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store, cache);
127 values++;
128 }
129 if (format & xAdvDevice) {
130 if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
131 values++;
132 }
133 if (format & yAdvDevice) {
134 /* y_advance values grow downward but font-space grows upward, hence negation */
135 if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache);
136 values++;
137 }
138 return ret;
139 }
140
141 unsigned int get_effective_format (const Value *values) const
142 {
143 unsigned int format = *this;
144 for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
145 if (format & flag) should_drop (*values++, (Flags) flag, &format);
146 }
147
148 return format;
149 }
150
151 template<typename Iterator,
152 hb_requires (hb_is_iterator (Iterator))>
153 unsigned int get_effective_format (Iterator it) const {
154 unsigned int new_format = 0;
155
156 for (const hb_array_t<const Value>& values : it)
157 new_format = new_format | get_effective_format (&values);
158
159 return new_format;
160 }
161
162 void copy_values (hb_serialize_context_t *c,
163 unsigned int new_format,
164 const void *base,
165 const Value *values,
166 const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
167 {
168 unsigned int format = *this;
169 if (!format) return;
170
171 HBINT16 *x_placement = nullptr, *y_placement = nullptr, *x_adv = nullptr, *y_adv = nullptr;
172 if (format & xPlacement) x_placement = copy_value (c, new_format, xPlacement, *values++);
173 if (format & yPlacement) y_placement = copy_value (c, new_format, yPlacement, *values++);
174 if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++);
175 if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++);
176
177 if (format & xPlaDevice)
178 {
179 add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map);
180 copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xPlaDevice);
181 }
182
183 if (format & yPlaDevice)
184 {
185 add_delta_to_value (y_placement, base, values, layout_variation_idx_delta_map);
186 copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yPlaDevice);
187 }
188
189 if (format & xAdvDevice)
190 {
191 add_delta_to_value (x_adv, base, values, layout_variation_idx_delta_map);
192 copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xAdvDevice);
193 }
194
195 if (format & yAdvDevice)
196 {
197 add_delta_to_value (y_adv, base, values, layout_variation_idx_delta_map);
198 copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yAdvDevice);
199 }
200 }
201
202 HBINT16* copy_value (hb_serialize_context_t *c,
203 unsigned int new_format,
204 Flags flag,
205 Value value) const
206 {
207 // Filter by new format.
208 if (!(new_format & flag)) return nullptr;
209 return reinterpret_cast<HBINT16 *> (c->copy (value));
210 }
211
212 void collect_variation_indices (hb_collect_variation_indices_context_t *c,
213 const void *base,
214 const hb_array_t<const Value>& values) const
215 {
216 unsigned format = *this;
217 unsigned i = 0;
218 if (format & xPlacement) i++;
219 if (format & yPlacement) i++;
220 if (format & xAdvance) i++;
221 if (format & yAdvance) i++;
222 if (format & xPlaDevice)
223 {
224 (base + get_device (&(values[i]))).collect_variation_indices (c);
225 i++;
226 }
227
228 if (format & ValueFormat::yPlaDevice)
229 {
230 (base + get_device (&(values[i]))).collect_variation_indices (c);
231 i++;
232 }
233
234 if (format & ValueFormat::xAdvDevice)
235 {
236
237 (base + get_device (&(values[i]))).collect_variation_indices (c);
238 i++;
239 }
240
241 if (format & ValueFormat::yAdvDevice)
242 {
243
244 (base + get_device (&(values[i]))).collect_variation_indices (c);
245 i++;
246 }
247 }
248
249 unsigned drop_device_table_flags () const
250 {
251 unsigned format = *this;
252 for (unsigned flag = xPlaDevice; flag <= yAdvDevice; flag = flag << 1)
253 format = format & ~flag;
254
255 return format;
256 }
257
258 private:
259 bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
260 {
261 unsigned int format = *this;
262
263 if (format & xPlacement) values++;
264 if (format & yPlacement) values++;
265 if (format & xAdvance) values++;
266 if (format & yAdvance) values++;
267
268 if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
269 if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
270 if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
271 if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
272
273 return true;
274 }
275
276 static inline Offset16To<Device>& get_device (Value* value)
277 {
278 return *static_cast<Offset16To<Device> *> (value);
279 }
280 static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
281 {
282 if (worked) *worked |= bool (*value);
283 return *static_cast<const Offset16To<Device> *> (value);
284 }
285
286 void add_delta_to_value (HBINT16 *value,
287 const void *base,
288 const Value *src_value,
289 const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
290 {
291 if (!value) return;
292 unsigned varidx = (base + get_device (src_value)).get_variation_index ();
293 hb_pair_t<unsigned, int> *varidx_delta;
294 if (!layout_variation_idx_delta_map->has (varidx, &varidx_delta)) return;
295
296 *value += hb_second (*varidx_delta);
297 }
298
299 bool copy_device (hb_serialize_context_t *c, const void *base,
300 const Value *src_value,
301 const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
302 unsigned int new_format, Flags flag) const
303 {
304 // Filter by new format.
305 if (!(new_format & flag)) return true;
306
307 Value *dst_value = c->copy (*src_value);
308
309 if (!dst_value) return false;
310 if (*dst_value == 0) return true;
311
312 *dst_value = 0;
313 c->push ();
314 if ((base + get_device (src_value)).copy (c, layout_variation_idx_delta_map))
315 {
316 c->add_link (*dst_value, c->pop_pack ());
317 return true;
318 }
319 else
320 {
321 c->pop_discard ();
322 return false;
323 }
324 }
325
326 static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
327 {
328 if (worked) *worked |= bool (*value);
329 return *reinterpret_cast<const HBINT16 *> (value);
330 }
331
332 public:
333
334 bool has_device () const
335 {
336 unsigned int format = *this;
337 return (format & devices) != 0;
338 }
339
340 bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
341 {
342 TRACE_SANITIZE (this);
343 return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
344 }
345
346 bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
347 {
348 TRACE_SANITIZE (this);
349 unsigned int len = get_len ();
350
351 if (!c->check_range (values, count, get_size ())) return_trace (false);
352
353 if (!has_device ()) return_trace (true);
354
355 for (unsigned int i = 0; i < count; i++) {
356 if (!sanitize_value_devices (c, base, values))
357 return_trace (false);
358 values += len;
359 }
360
361 return_trace (true);
362 }
363
364 /* Just sanitize referenced Device tables. Doesn't check the values themselves. */
365 bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
366 {
367 TRACE_SANITIZE (this);
368
369 if (!has_device ()) return_trace (true);
370
371 for (unsigned int i = 0; i < count; i++) {
372 if (!sanitize_value_devices (c, base, values))
373 return_trace (false);
374 values += stride;
375 }
376
377 return_trace (true);
378 }
379
380 private:
381
382 void should_drop (Value value, Flags flag, unsigned int* format) const
383 {
384 if (value) return;
385 *format = *format & ~flag;
386 }
387
388 };
389
390 }
391 }
392 }
393
394 #endif // #ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH