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