• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
64 struct 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 };
94 DECLARE_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 
105 struct 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 */
dir_multhb_font_t150   int64_t dir_mult (hb_direction_t direction)
151   { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
em_scale_xhb_font_t152   hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
em_scale_yhb_font_t153   hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
em_scalef_xhb_font_t154   hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); }
em_scalef_yhb_font_t155   hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
em_fscale_xhb_font_t156   float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); }
em_fscale_yhb_font_t157   float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); }
em_fscalef_xhb_font_t158   float em_fscalef_x (float v) { return em_fmultf (v, x_multf); }
em_fscalef_yhb_font_t159   float em_fscalef_y (float v) { return em_fmultf (v, y_multf); }
em_scale_dirhb_font_t160   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 */
parent_scale_x_distancehb_font_t164   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   }
parent_scale_y_distancehb_font_t170   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   }
parent_scale_x_positionhb_font_t176   hb_position_t parent_scale_x_position (hb_position_t v)
177   { return parent_scale_x_distance (v); }
parent_scale_y_positionhb_font_t178   hb_position_t parent_scale_y_position (hb_position_t v)
179   { return parent_scale_y_distance (v); }
180 
parent_scale_distancehb_font_t181   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   }
parent_scale_positionhb_font_t186   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 
scale_glyph_extentshb_font_t192   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 
get_font_h_extentshb_font_t253   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   }
get_font_v_extentshb_font_t260   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 
has_glyphhb_font_t268   bool has_glyph (hb_codepoint_t unicode)
269   {
270     hb_codepoint_t glyph;
271     return get_nominal_glyph (unicode, &glyph);
272   }
273 
get_nominal_glyphhb_font_t274   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   }
get_nominal_glyphshb_font_t283   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 
get_variation_glyphhb_font_t296   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 
get_glyph_h_advancehb_font_t306   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 
get_glyph_v_advancehb_font_t313   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 
get_glyph_h_advanceshb_font_t320   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 
get_glyph_v_advanceshb_font_t333   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 
get_glyph_h_originhb_font_t346   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 
get_glyph_v_originhb_font_t355   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 
get_glyph_h_kerninghb_font_t364   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 
get_glyph_v_kerninghb_font_t376   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 
get_glyph_extentshb_font_t388   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 
get_glyph_contour_pointhb_font_t398   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 
get_glyph_namehb_font_t408   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 
get_glyph_from_namehb_font_t418   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 
draw_glyphhb_font_t429   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 
paint_glyphhb_font_t438   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 
get_h_extents_with_fallbackhb_font_t452   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   }
get_v_extents_with_fallbackhb_font_t461   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 
get_extents_for_directionhb_font_t471   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 
get_glyph_advance_for_directionhb_font_t480   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   }
get_glyph_advances_for_directionhb_font_t490   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 
guess_v_origin_minus_h_originhb_font_t503   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 
get_glyph_h_origin_with_fallbackhb_font_t513   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   }
get_glyph_v_origin_with_fallbackhb_font_t524   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 
get_glyph_origin_for_directionhb_font_t536   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 
add_glyph_h_originhb_font_t546   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   }
add_glyph_v_originhb_font_t556   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   }
add_glyph_origin_for_directionhb_font_t566   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 
subtract_glyph_h_originhb_font_t578   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   }
subtract_glyph_v_originhb_font_t588   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   }
subtract_glyph_origin_for_directionhb_font_t598   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 
get_glyph_kerning_for_directionhb_font_t610   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 
get_glyph_extents_for_originhb_font_t623   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 
get_glyph_contour_point_for_originhb_font_t635   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
glyph_to_stringhb_font_t649   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%" PRIu32, glyph) < 0)
655       *s = '\0';
656   }
657 
658   /* Parses gidDDD and uniUUUU strings automatically. */
659   hb_bool_t
glyph_from_stringhb_font_t660   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 
mults_changedhb_font_t689   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 
em_multhb_font_t708   hb_position_t em_mult (int16_t v, int64_t mult)
709   { return (hb_position_t) ((v * mult + 32768) >> 16); }
em_multfhb_font_t710   hb_position_t em_multf (float v, float mult)
711   { return (hb_position_t) roundf (em_fmultf (v, mult)); }
em_fmultfhb_font_t712   float em_fmultf (float v, float mult)
713   { return v * mult; }
em_fmulthb_font_t714   float em_fmult (int16_t v, float mult)
715   { return (float) v * mult; }
716 };
717 DECLARE_NULL_INSTANCE (hb_font_t);
718 
719 
720 #endif /* HB_FONT_HH */
721