comparison mupdf-source/thirdparty/harfbuzz/src/hb-font.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 /*
2 * Copyright © 2009 Red Hat, Inc.
3 * Copyright © 2011 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 HB_FONT_HH
30 #define HB_FONT_HH
31
32 #include "hb.hh"
33
34 #include "hb-face.hh"
35 #include "hb-shaper.hh"
36
37
38 /*
39 * hb_font_funcs_t
40 */
41
42 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
43 HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
44 HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
45 HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
46 HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \
47 HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
48 HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
49 HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
50 HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
51 HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
52 HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
53 HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
54 HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
55 HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \
56 HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
57 HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
58 HB_FONT_FUNC_IMPLEMENT (glyph_name) \
59 HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
60 HB_FONT_FUNC_IMPLEMENT (glyph_shape) \
61 /* ^--- Add new callbacks here */
62
63 struct hb_font_funcs_t
64 {
65 hb_object_header_t header;
66
67 struct {
68 #define HB_FONT_FUNC_IMPLEMENT(name) void *name;
69 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
70 #undef HB_FONT_FUNC_IMPLEMENT
71 } *user_data;
72
73 struct {
74 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
75 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
76 #undef HB_FONT_FUNC_IMPLEMENT
77 } *destroy;
78
79 /* Don't access these directly. Call font->get_*() instead. */
80 union get_t {
81 struct get_funcs_t {
82 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
83 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
84 #undef HB_FONT_FUNC_IMPLEMENT
85 } f;
86 void (*array[0
87 #define HB_FONT_FUNC_IMPLEMENT(name) +1
88 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
89 #undef HB_FONT_FUNC_IMPLEMENT
90 ]) ();
91 } get;
92 };
93 DECLARE_NULL_INSTANCE (hb_font_funcs_t);
94
95
96 /*
97 * hb_font_t
98 */
99
100 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font);
101 #include "hb-shaper-list.hh"
102 #undef HB_SHAPER_IMPLEMENT
103
104 struct hb_font_t
105 {
106 hb_object_header_t header;
107 unsigned int serial;
108 unsigned int serial_coords;
109
110 hb_font_t *parent;
111 hb_face_t *face;
112
113 int32_t x_scale;
114 int32_t y_scale;
115 float slant;
116 float slant_xy;
117 float x_multf;
118 float y_multf;
119 int64_t x_mult;
120 int64_t y_mult;
121
122 unsigned int x_ppem;
123 unsigned int y_ppem;
124
125 float ptem;
126
127 /* Font variation coordinates. */
128 unsigned int num_coords;
129 int *coords;
130 float *design_coords;
131
132 hb_font_funcs_t *klass;
133 void *user_data;
134 hb_destroy_func_t destroy;
135
136 hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */
137
138
139 /* Convert from font-space to user-space */
140 int64_t dir_mult (hb_direction_t direction)
141 { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
142 hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
143 hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
144 hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); }
145 hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
146 float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); }
147 float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); }
148 float em_fscalef_x (float v) { return em_fmultf (v, x_multf); }
149 float em_fscalef_y (float v) { return em_fmultf (v, y_multf); }
150 hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
151 { return em_mult (v, dir_mult (direction)); }
152
153 /* Convert from parent-font user-space to our user-space */
154 hb_position_t parent_scale_x_distance (hb_position_t v)
155 {
156 if (unlikely (parent && parent->x_scale != x_scale))
157 return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
158 return v;
159 }
160 hb_position_t parent_scale_y_distance (hb_position_t v)
161 {
162 if (unlikely (parent && parent->y_scale != y_scale))
163 return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
164 return v;
165 }
166 hb_position_t parent_scale_x_position (hb_position_t v)
167 { return parent_scale_x_distance (v); }
168 hb_position_t parent_scale_y_position (hb_position_t v)
169 { return parent_scale_y_distance (v); }
170
171 void parent_scale_distance (hb_position_t *x, hb_position_t *y)
172 {
173 *x = parent_scale_x_distance (*x);
174 *y = parent_scale_y_distance (*y);
175 }
176 void parent_scale_position (hb_position_t *x, hb_position_t *y)
177 {
178 *x = parent_scale_x_position (*x);
179 *y = parent_scale_y_position (*y);
180 }
181
182
183 /* Public getters */
184
185 HB_INTERNAL bool has_func (unsigned int i);
186 HB_INTERNAL bool has_func_set (unsigned int i);
187
188 /* has_* ... */
189 #define HB_FONT_FUNC_IMPLEMENT(name) \
190 bool \
191 has_##name##_func () \
192 { \
193 hb_font_funcs_t *funcs = this->klass; \
194 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
195 return has_func (i); \
196 } \
197 bool \
198 has_##name##_func_set () \
199 { \
200 hb_font_funcs_t *funcs = this->klass; \
201 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
202 return has_func_set (i); \
203 }
204 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
205 #undef HB_FONT_FUNC_IMPLEMENT
206
207 hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
208 {
209 hb_memset (extents, 0, sizeof (*extents));
210 return klass->get.f.font_h_extents (this, user_data,
211 extents,
212 !klass->user_data ? nullptr : klass->user_data->font_h_extents);
213 }
214 hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
215 {
216 hb_memset (extents, 0, sizeof (*extents));
217 return klass->get.f.font_v_extents (this, user_data,
218 extents,
219 !klass->user_data ? nullptr : klass->user_data->font_v_extents);
220 }
221
222 bool has_glyph (hb_codepoint_t unicode)
223 {
224 hb_codepoint_t glyph;
225 return get_nominal_glyph (unicode, &glyph);
226 }
227
228 hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
229 hb_codepoint_t *glyph,
230 hb_codepoint_t not_found = 0)
231 {
232 *glyph = not_found;
233 return klass->get.f.nominal_glyph (this, user_data,
234 unicode, glyph,
235 !klass->user_data ? nullptr : klass->user_data->nominal_glyph);
236 }
237 unsigned int get_nominal_glyphs (unsigned int count,
238 const hb_codepoint_t *first_unicode,
239 unsigned int unicode_stride,
240 hb_codepoint_t *first_glyph,
241 unsigned int glyph_stride)
242 {
243 return klass->get.f.nominal_glyphs (this, user_data,
244 count,
245 first_unicode, unicode_stride,
246 first_glyph, glyph_stride,
247 !klass->user_data ? nullptr : klass->user_data->nominal_glyphs);
248 }
249
250 hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
251 hb_codepoint_t *glyph,
252 hb_codepoint_t not_found = 0)
253 {
254 *glyph = not_found;
255 return klass->get.f.variation_glyph (this, user_data,
256 unicode, variation_selector, glyph,
257 !klass->user_data ? nullptr : klass->user_data->variation_glyph);
258 }
259
260 hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
261 {
262 return klass->get.f.glyph_h_advance (this, user_data,
263 glyph,
264 !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
265 }
266
267 hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
268 {
269 return klass->get.f.glyph_v_advance (this, user_data,
270 glyph,
271 !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
272 }
273
274 void get_glyph_h_advances (unsigned int count,
275 const hb_codepoint_t *first_glyph,
276 unsigned int glyph_stride,
277 hb_position_t *first_advance,
278 unsigned int advance_stride)
279 {
280 return klass->get.f.glyph_h_advances (this, user_data,
281 count,
282 first_glyph, glyph_stride,
283 first_advance, advance_stride,
284 !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
285 }
286
287 void get_glyph_v_advances (unsigned int count,
288 const hb_codepoint_t *first_glyph,
289 unsigned int glyph_stride,
290 hb_position_t *first_advance,
291 unsigned int advance_stride)
292 {
293 return klass->get.f.glyph_v_advances (this, user_data,
294 count,
295 first_glyph, glyph_stride,
296 first_advance, advance_stride,
297 !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
298 }
299
300 hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
301 hb_position_t *x, hb_position_t *y)
302 {
303 *x = *y = 0;
304 return klass->get.f.glyph_h_origin (this, user_data,
305 glyph, x, y,
306 !klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
307 }
308
309 hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
310 hb_position_t *x, hb_position_t *y)
311 {
312 *x = *y = 0;
313 return klass->get.f.glyph_v_origin (this, user_data,
314 glyph, x, y,
315 !klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
316 }
317
318 hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
319 hb_codepoint_t right_glyph)
320 {
321 #ifdef HB_DISABLE_DEPRECATED
322 return 0;
323 #else
324 return klass->get.f.glyph_h_kerning (this, user_data,
325 left_glyph, right_glyph,
326 !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning);
327 #endif
328 }
329
330 hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
331 hb_codepoint_t bottom_glyph)
332 {
333 #ifdef HB_DISABLE_DEPRECATED
334 return 0;
335 #else
336 return klass->get.f.glyph_v_kerning (this, user_data,
337 top_glyph, bottom_glyph,
338 !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning);
339 #endif
340 }
341
342 hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
343 hb_glyph_extents_t *extents)
344 {
345 hb_memset (extents, 0, sizeof (*extents));
346 return klass->get.f.glyph_extents (this, user_data,
347 glyph,
348 extents,
349 !klass->user_data ? nullptr : klass->user_data->glyph_extents);
350 }
351
352 hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
353 hb_position_t *x, hb_position_t *y)
354 {
355 *x = *y = 0;
356 return klass->get.f.glyph_contour_point (this, user_data,
357 glyph, point_index,
358 x, y,
359 !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
360 }
361
362 hb_bool_t get_glyph_name (hb_codepoint_t glyph,
363 char *name, unsigned int size)
364 {
365 if (size) *name = '\0';
366 return klass->get.f.glyph_name (this, user_data,
367 glyph,
368 name, size,
369 !klass->user_data ? nullptr : klass->user_data->glyph_name);
370 }
371
372 hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
373 hb_codepoint_t *glyph)
374 {
375 *glyph = 0;
376 if (len == -1) len = strlen (name);
377 return klass->get.f.glyph_from_name (this, user_data,
378 name, len,
379 glyph,
380 !klass->user_data ? nullptr : klass->user_data->glyph_from_name);
381 }
382
383 void get_glyph_shape (hb_codepoint_t glyph,
384 hb_draw_funcs_t *draw_funcs, void *draw_data)
385 {
386 klass->get.f.glyph_shape (this, user_data,
387 glyph,
388 draw_funcs, draw_data,
389 !klass->user_data ? nullptr : klass->user_data->glyph_shape);
390 }
391
392
393 /* A bit higher-level, and with fallback */
394
395 void get_h_extents_with_fallback (hb_font_extents_t *extents)
396 {
397 if (!get_font_h_extents (extents))
398 {
399 extents->ascender = y_scale * .8;
400 extents->descender = extents->ascender - y_scale;
401 extents->line_gap = 0;
402 }
403 }
404 void get_v_extents_with_fallback (hb_font_extents_t *extents)
405 {
406 if (!get_font_v_extents (extents))
407 {
408 extents->ascender = x_scale / 2;
409 extents->descender = extents->ascender - x_scale;
410 extents->line_gap = 0;
411 }
412 }
413
414 void get_extents_for_direction (hb_direction_t direction,
415 hb_font_extents_t *extents)
416 {
417 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
418 get_h_extents_with_fallback (extents);
419 else
420 get_v_extents_with_fallback (extents);
421 }
422
423 void get_glyph_advance_for_direction (hb_codepoint_t glyph,
424 hb_direction_t direction,
425 hb_position_t *x, hb_position_t *y)
426 {
427 *x = *y = 0;
428 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
429 *x = get_glyph_h_advance (glyph);
430 else
431 *y = get_glyph_v_advance (glyph);
432 }
433 void get_glyph_advances_for_direction (hb_direction_t direction,
434 unsigned int count,
435 const hb_codepoint_t *first_glyph,
436 unsigned glyph_stride,
437 hb_position_t *first_advance,
438 unsigned advance_stride)
439 {
440 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
441 get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
442 else
443 get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
444 }
445
446 void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
447 hb_position_t *x, hb_position_t *y)
448 {
449 *x = get_glyph_h_advance (glyph) / 2;
450
451 hb_font_extents_t extents;
452 get_h_extents_with_fallback (&extents);
453 *y = extents.ascender;
454 }
455
456 void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
457 hb_position_t *x, hb_position_t *y)
458 {
459 if (!get_glyph_h_origin (glyph, x, y) &&
460 get_glyph_v_origin (glyph, x, y))
461 {
462 hb_position_t dx, dy;
463 guess_v_origin_minus_h_origin (glyph, &dx, &dy);
464 *x -= dx; *y -= dy;
465 }
466 }
467 void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
468 hb_position_t *x, hb_position_t *y)
469 {
470 if (!get_glyph_v_origin (glyph, x, y) &&
471 get_glyph_h_origin (glyph, x, y))
472 {
473 hb_position_t dx, dy;
474 guess_v_origin_minus_h_origin (glyph, &dx, &dy);
475 *x += dx; *y += dy;
476 }
477 }
478
479 void get_glyph_origin_for_direction (hb_codepoint_t glyph,
480 hb_direction_t direction,
481 hb_position_t *x, hb_position_t *y)
482 {
483 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
484 get_glyph_h_origin_with_fallback (glyph, x, y);
485 else
486 get_glyph_v_origin_with_fallback (glyph, x, y);
487 }
488
489 void add_glyph_h_origin (hb_codepoint_t glyph,
490 hb_position_t *x, hb_position_t *y)
491 {
492 hb_position_t origin_x, origin_y;
493
494 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
495
496 *x += origin_x;
497 *y += origin_y;
498 }
499 void add_glyph_v_origin (hb_codepoint_t glyph,
500 hb_position_t *x, hb_position_t *y)
501 {
502 hb_position_t origin_x, origin_y;
503
504 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
505
506 *x += origin_x;
507 *y += origin_y;
508 }
509 void add_glyph_origin_for_direction (hb_codepoint_t glyph,
510 hb_direction_t direction,
511 hb_position_t *x, hb_position_t *y)
512 {
513 hb_position_t origin_x, origin_y;
514
515 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
516
517 *x += origin_x;
518 *y += origin_y;
519 }
520
521 void subtract_glyph_h_origin (hb_codepoint_t glyph,
522 hb_position_t *x, hb_position_t *y)
523 {
524 hb_position_t origin_x, origin_y;
525
526 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
527
528 *x -= origin_x;
529 *y -= origin_y;
530 }
531 void subtract_glyph_v_origin (hb_codepoint_t glyph,
532 hb_position_t *x, hb_position_t *y)
533 {
534 hb_position_t origin_x, origin_y;
535
536 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
537
538 *x -= origin_x;
539 *y -= origin_y;
540 }
541 void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
542 hb_direction_t direction,
543 hb_position_t *x, hb_position_t *y)
544 {
545 hb_position_t origin_x, origin_y;
546
547 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
548
549 *x -= origin_x;
550 *y -= origin_y;
551 }
552
553 void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
554 hb_direction_t direction,
555 hb_position_t *x, hb_position_t *y)
556 {
557 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
558 *y = 0;
559 *x = get_glyph_h_kerning (first_glyph, second_glyph);
560 } else {
561 *x = 0;
562 *y = get_glyph_v_kerning (first_glyph, second_glyph);
563 }
564 }
565
566 hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
567 hb_direction_t direction,
568 hb_glyph_extents_t *extents)
569 {
570 hb_bool_t ret = get_glyph_extents (glyph, extents);
571
572 if (ret)
573 subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
574
575 return ret;
576 }
577
578 hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
579 hb_direction_t direction,
580 hb_position_t *x, hb_position_t *y)
581 {
582 hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
583
584 if (ret)
585 subtract_glyph_origin_for_direction (glyph, direction, x, y);
586
587 return ret;
588 }
589
590 /* Generates gidDDD if glyph has no name. */
591 void
592 glyph_to_string (hb_codepoint_t glyph,
593 char *s, unsigned int size)
594 {
595 if (get_glyph_name (glyph, s, size)) return;
596
597 if (size && snprintf (s, size, "gid%u", glyph) < 0)
598 *s = '\0';
599 }
600
601 /* Parses gidDDD and uniUUUU strings automatically. */
602 hb_bool_t
603 glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
604 hb_codepoint_t *glyph)
605 {
606 if (get_glyph_from_name (s, len, glyph)) return true;
607
608 if (len == -1) len = strlen (s);
609
610 /* Straight glyph index. */
611 if (hb_codepoint_parse (s, len, 10, glyph))
612 return true;
613
614 if (len > 3)
615 {
616 /* gidDDD syntax for glyph indices. */
617 if (0 == strncmp (s, "gid", 3) &&
618 hb_codepoint_parse (s + 3, len - 3, 10, glyph))
619 return true;
620
621 /* uniUUUU and other Unicode character indices. */
622 hb_codepoint_t unichar;
623 if (0 == strncmp (s, "uni", 3) &&
624 hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
625 get_nominal_glyph (unichar, glyph))
626 return true;
627 }
628
629 return false;
630 }
631
632 void mults_changed ()
633 {
634 float upem = face->get_upem ();
635 x_multf = x_scale / upem;
636 y_multf = y_scale / upem;
637 bool x_neg = x_scale < 0;
638 x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem;
639 bool y_neg = y_scale < 0;
640 y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
641 slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
642
643 data.fini ();
644 }
645
646 hb_position_t em_mult (int16_t v, int64_t mult)
647 { return (hb_position_t) ((v * mult + 32768) >> 16); }
648 hb_position_t em_multf (float v, float mult)
649 { return (hb_position_t) roundf (em_fmultf (v, mult)); }
650 float em_fmultf (float v, float mult)
651 { return v * mult; }
652 float em_fmult (int16_t v, float mult)
653 { return (float) v * mult; }
654 };
655 DECLARE_NULL_INSTANCE (hb_font_t);
656
657
658 #endif /* HB_FONT_HH */