• 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 (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 */
dir_multhb_font_t140   int64_t dir_mult (hb_direction_t direction)
141   { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
em_scale_xhb_font_t142   hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
em_scale_yhb_font_t143   hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
em_scalef_xhb_font_t144   hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); }
em_scalef_yhb_font_t145   hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
em_fscale_xhb_font_t146   float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); }
em_fscale_yhb_font_t147   float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); }
em_fscalef_xhb_font_t148   float em_fscalef_x (float v) { return em_fmultf (v, x_multf); }
em_fscalef_yhb_font_t149   float em_fscalef_y (float v) { return em_fmultf (v, y_multf); }
em_scale_dirhb_font_t150   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 */
parent_scale_x_distancehb_font_t154   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   }
parent_scale_y_distancehb_font_t160   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   }
parent_scale_x_positionhb_font_t166   hb_position_t parent_scale_x_position (hb_position_t v)
167   { return parent_scale_x_distance (v); }
parent_scale_y_positionhb_font_t168   hb_position_t parent_scale_y_position (hb_position_t v)
169   { return parent_scale_y_distance (v); }
170 
parent_scale_distancehb_font_t171   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   }
parent_scale_positionhb_font_t176   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 
get_font_h_extentshb_font_t207   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   }
get_font_v_extentshb_font_t214   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 
has_glyphhb_font_t222   bool has_glyph (hb_codepoint_t unicode)
223   {
224     hb_codepoint_t glyph;
225     return get_nominal_glyph (unicode, &glyph);
226   }
227 
get_nominal_glyphhb_font_t228   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   }
get_nominal_glyphshb_font_t237   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 
get_variation_glyphhb_font_t250   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 
get_glyph_h_advancehb_font_t260   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 
get_glyph_v_advancehb_font_t267   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 
get_glyph_h_advanceshb_font_t274   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 
get_glyph_v_advanceshb_font_t287   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 
get_glyph_h_originhb_font_t300   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 
get_glyph_v_originhb_font_t309   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 
get_glyph_h_kerninghb_font_t318   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 
get_glyph_v_kerninghb_font_t330   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 
get_glyph_extentshb_font_t342   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 
get_glyph_contour_pointhb_font_t352   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 
get_glyph_namehb_font_t362   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 
get_glyph_from_namehb_font_t372   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 
get_glyph_shapehb_font_t383   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 
get_h_extents_with_fallbackhb_font_t395   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   }
get_v_extents_with_fallbackhb_font_t404   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 
get_extents_for_directionhb_font_t414   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 
get_glyph_advance_for_directionhb_font_t423   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   }
get_glyph_advances_for_directionhb_font_t433   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 
guess_v_origin_minus_h_originhb_font_t446   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 
get_glyph_h_origin_with_fallbackhb_font_t456   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   }
get_glyph_v_origin_with_fallbackhb_font_t467   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 
get_glyph_origin_for_directionhb_font_t479   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 
add_glyph_h_originhb_font_t489   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   }
add_glyph_v_originhb_font_t499   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   }
add_glyph_origin_for_directionhb_font_t509   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 
subtract_glyph_h_originhb_font_t521   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   }
subtract_glyph_v_originhb_font_t531   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   }
subtract_glyph_origin_for_directionhb_font_t541   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 
get_glyph_kerning_for_directionhb_font_t553   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 
get_glyph_extents_for_originhb_font_t566   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 
get_glyph_contour_point_for_originhb_font_t578   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
glyph_to_stringhb_font_t592   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
glyph_from_stringhb_font_t603   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 
mults_changedhb_font_t632   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 
em_multhb_font_t646   hb_position_t em_mult (int16_t v, int64_t mult)
647   { return (hb_position_t) ((v * mult + 32768) >> 16); }
em_multfhb_font_t648   hb_position_t em_multf (float v, float mult)
649   { return (hb_position_t) roundf (em_fmultf (v, mult)); }
em_fmultfhb_font_t650   float em_fmultf (float v, float mult)
651   { return v * mult; }
em_fmulthb_font_t652   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 */
659