• 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_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   /* ^--- Add new callbacks here */
61 
62 struct hb_font_funcs_t
63 {
64   hb_object_header_t header;
65 
66   struct {
67 #define HB_FONT_FUNC_IMPLEMENT(name) void *name;
68     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
69 #undef HB_FONT_FUNC_IMPLEMENT
70   } user_data;
71 
72   struct {
73 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
74     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
75 #undef HB_FONT_FUNC_IMPLEMENT
76   } destroy;
77 
78   /* Don't access these directly.  Call font->get_*() instead. */
79   union get_t {
80     struct get_funcs_t {
81 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
82       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
83 #undef HB_FONT_FUNC_IMPLEMENT
84     } f;
85     void (*array[0
86 #define HB_FONT_FUNC_IMPLEMENT(name) +1
87       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
88 #undef HB_FONT_FUNC_IMPLEMENT
89 		]) ();
90   } get;
91 };
92 DECLARE_NULL_INSTANCE (hb_font_funcs_t);
93 
94 
95 /*
96  * hb_font_t
97  */
98 
99 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font);
100 #include "hb-shaper-list.hh"
101 #undef HB_SHAPER_IMPLEMENT
102 
103 struct hb_font_t
104 {
105   hb_object_header_t header;
106 
107   hb_font_t *parent;
108   hb_face_t *face;
109 
110   int x_scale;
111   int y_scale;
112 
113   unsigned int x_ppem;
114   unsigned int y_ppem;
115 
116   float ptem;
117 
118   /* Font variation coordinates. */
119   unsigned int num_coords;
120   int *coords;
121 
122   hb_font_funcs_t   *klass;
123   void              *user_data;
124   hb_destroy_func_t  destroy;
125 
126   hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */
127 
128 
129   /* Convert from font-space to user-space */
dir_scalehb_font_t130   int dir_scale (hb_direction_t direction)
131   { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
em_scale_xhb_font_t132   hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
em_scale_yhb_font_t133   hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
em_scalef_xhb_font_t134   hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
em_scalef_yhb_font_t135   hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
em_fscale_xhb_font_t136   float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
em_fscale_yhb_font_t137   float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
em_scale_dirhb_font_t138   hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
139   { return em_scale (v, dir_scale (direction)); }
140 
141   /* Convert from parent-font user-space to our user-space */
parent_scale_x_distancehb_font_t142   hb_position_t parent_scale_x_distance (hb_position_t v)
143   {
144     if (unlikely (parent && parent->x_scale != x_scale))
145       return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
146     return v;
147   }
parent_scale_y_distancehb_font_t148   hb_position_t parent_scale_y_distance (hb_position_t v)
149   {
150     if (unlikely (parent && parent->y_scale != y_scale))
151       return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
152     return v;
153   }
parent_scale_x_positionhb_font_t154   hb_position_t parent_scale_x_position (hb_position_t v)
155   { return parent_scale_x_distance (v); }
parent_scale_y_positionhb_font_t156   hb_position_t parent_scale_y_position (hb_position_t v)
157   { return parent_scale_y_distance (v); }
158 
parent_scale_distancehb_font_t159   void parent_scale_distance (hb_position_t *x, hb_position_t *y)
160   {
161     *x = parent_scale_x_distance (*x);
162     *y = parent_scale_y_distance (*y);
163   }
parent_scale_positionhb_font_t164   void parent_scale_position (hb_position_t *x, hb_position_t *y)
165   {
166     *x = parent_scale_x_position (*x);
167     *y = parent_scale_y_position (*y);
168   }
169 
170 
171   /* Public getters */
172 
173   HB_INTERNAL bool has_func (unsigned int i);
174   HB_INTERNAL bool has_func_set (unsigned int i);
175 
176   /* has_* ... */
177 #define HB_FONT_FUNC_IMPLEMENT(name) \
178   bool \
179   has_##name##_func () \
180   { \
181     hb_font_funcs_t *funcs = this->klass; \
182     unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
183     return has_func (i); \
184   } \
185   bool \
186   has_##name##_func_set () \
187   { \
188     hb_font_funcs_t *funcs = this->klass; \
189     unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
190     return has_func_set (i); \
191   }
192   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
193 #undef HB_FONT_FUNC_IMPLEMENT
194 
get_font_h_extentshb_font_t195   hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
196   {
197     memset (extents, 0, sizeof (*extents));
198     return klass->get.f.font_h_extents (this, user_data,
199 					extents,
200 					klass->user_data.font_h_extents);
201   }
get_font_v_extentshb_font_t202   hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
203   {
204     memset (extents, 0, sizeof (*extents));
205     return klass->get.f.font_v_extents (this, user_data,
206 					extents,
207 					klass->user_data.font_v_extents);
208   }
209 
has_glyphhb_font_t210   bool has_glyph (hb_codepoint_t unicode)
211   {
212     hb_codepoint_t glyph;
213     return get_nominal_glyph (unicode, &glyph);
214   }
215 
get_nominal_glyphhb_font_t216   hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
217 				      hb_codepoint_t *glyph)
218   {
219     *glyph = 0;
220     return klass->get.f.nominal_glyph (this, user_data,
221 				       unicode, glyph,
222 				       klass->user_data.nominal_glyph);
223   }
get_nominal_glyphshb_font_t224   unsigned int get_nominal_glyphs (unsigned int count,
225 				   const hb_codepoint_t *first_unicode,
226 				   unsigned int unicode_stride,
227 				   hb_codepoint_t *first_glyph,
228 				   unsigned int glyph_stride)
229   {
230     return klass->get.f.nominal_glyphs (this, user_data,
231 					count,
232 					first_unicode, unicode_stride,
233 					first_glyph, glyph_stride,
234 					klass->user_data.nominal_glyphs);
235   }
236 
get_variation_glyphhb_font_t237   hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
238 				 hb_codepoint_t *glyph)
239   {
240     *glyph = 0;
241     return klass->get.f.variation_glyph (this, user_data,
242 					 unicode, variation_selector, glyph,
243 					 klass->user_data.variation_glyph);
244   }
245 
get_glyph_h_advancehb_font_t246   hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
247   {
248     return klass->get.f.glyph_h_advance (this, user_data,
249 					 glyph,
250 					 klass->user_data.glyph_h_advance);
251   }
252 
get_glyph_v_advancehb_font_t253   hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
254   {
255     return klass->get.f.glyph_v_advance (this, user_data,
256 					 glyph,
257 					 klass->user_data.glyph_v_advance);
258   }
259 
get_glyph_h_advanceshb_font_t260   void get_glyph_h_advances (unsigned int count,
261 			     const hb_codepoint_t *first_glyph,
262 			     unsigned int glyph_stride,
263 			     hb_position_t *first_advance,
264 			     unsigned int advance_stride)
265   {
266     return klass->get.f.glyph_h_advances (this, user_data,
267 					  count,
268 					  first_glyph, glyph_stride,
269 					  first_advance, advance_stride,
270 					  klass->user_data.glyph_h_advances);
271   }
272 
get_glyph_v_advanceshb_font_t273   void get_glyph_v_advances (unsigned int count,
274 			     const hb_codepoint_t *first_glyph,
275 			     unsigned int glyph_stride,
276 			     hb_position_t *first_advance,
277 			     unsigned int advance_stride)
278   {
279     return klass->get.f.glyph_v_advances (this, user_data,
280 					  count,
281 					  first_glyph, glyph_stride,
282 					  first_advance, advance_stride,
283 					  klass->user_data.glyph_v_advances);
284   }
285 
get_glyph_h_originhb_font_t286   hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
287 				       hb_position_t *x, hb_position_t *y)
288   {
289     *x = *y = 0;
290     return klass->get.f.glyph_h_origin (this, user_data,
291 					glyph, x, y,
292 					klass->user_data.glyph_h_origin);
293   }
294 
get_glyph_v_originhb_font_t295   hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
296 				hb_position_t *x, hb_position_t *y)
297   {
298     *x = *y = 0;
299     return klass->get.f.glyph_v_origin (this, user_data,
300 					glyph, x, y,
301 					klass->user_data.glyph_v_origin);
302   }
303 
get_glyph_h_kerninghb_font_t304   hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
305 				     hb_codepoint_t right_glyph)
306   {
307     return klass->get.f.glyph_h_kerning (this, user_data,
308 					 left_glyph, right_glyph,
309 					 klass->user_data.glyph_h_kerning);
310   }
311 
get_glyph_v_kerninghb_font_t312   hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
313 				     hb_codepoint_t bottom_glyph)
314   {
315     return klass->get.f.glyph_v_kerning (this, user_data,
316 					 top_glyph, bottom_glyph,
317 					 klass->user_data.glyph_v_kerning);
318   }
319 
get_glyph_extentshb_font_t320   hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
321 				      hb_glyph_extents_t *extents)
322   {
323     memset (extents, 0, sizeof (*extents));
324     return klass->get.f.glyph_extents (this, user_data,
325 				       glyph,
326 				       extents,
327 				       klass->user_data.glyph_extents);
328   }
329 
get_glyph_contour_pointhb_font_t330   hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
331 					    hb_position_t *x, hb_position_t *y)
332   {
333     *x = *y = 0;
334     return klass->get.f.glyph_contour_point (this, user_data,
335 					     glyph, point_index,
336 					     x, y,
337 					     klass->user_data.glyph_contour_point);
338   }
339 
get_glyph_namehb_font_t340   hb_bool_t get_glyph_name (hb_codepoint_t glyph,
341 			    char *name, unsigned int size)
342   {
343     if (size) *name = '\0';
344     return klass->get.f.glyph_name (this, user_data,
345 				    glyph,
346 				    name, size,
347 				    klass->user_data.glyph_name);
348   }
349 
get_glyph_from_namehb_font_t350   hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
351 				 hb_codepoint_t *glyph)
352   {
353     *glyph = 0;
354     if (len == -1) len = strlen (name);
355     return klass->get.f.glyph_from_name (this, user_data,
356 					 name, len,
357 					 glyph,
358 					 klass->user_data.glyph_from_name);
359   }
360 
361 
362   /* A bit higher-level, and with fallback */
363 
get_h_extents_with_fallbackhb_font_t364   void get_h_extents_with_fallback (hb_font_extents_t *extents)
365   {
366     if (!get_font_h_extents (extents))
367     {
368       extents->ascender = y_scale * .8;
369       extents->descender = extents->ascender - y_scale;
370       extents->line_gap = 0;
371     }
372   }
get_v_extents_with_fallbackhb_font_t373   void get_v_extents_with_fallback (hb_font_extents_t *extents)
374   {
375     if (!get_font_v_extents (extents))
376     {
377       extents->ascender = x_scale / 2;
378       extents->descender = extents->ascender - x_scale;
379       extents->line_gap = 0;
380     }
381   }
382 
get_extents_for_directionhb_font_t383   void get_extents_for_direction (hb_direction_t direction,
384 				  hb_font_extents_t *extents)
385   {
386     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
387       get_h_extents_with_fallback (extents);
388     else
389       get_v_extents_with_fallback (extents);
390   }
391 
get_glyph_advance_for_directionhb_font_t392   void get_glyph_advance_for_direction (hb_codepoint_t glyph,
393 					hb_direction_t direction,
394 					hb_position_t *x, hb_position_t *y)
395   {
396     *x = *y = 0;
397     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
398       *x = get_glyph_h_advance (glyph);
399     else
400       *y = get_glyph_v_advance (glyph);
401   }
get_glyph_advances_for_directionhb_font_t402   void get_glyph_advances_for_direction (hb_direction_t direction,
403 					 unsigned int count,
404 					 const hb_codepoint_t *first_glyph,
405 					 unsigned glyph_stride,
406 					 hb_position_t *first_advance,
407 					 unsigned advance_stride)
408   {
409     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
410       get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
411     else
412       get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
413   }
414 
guess_v_origin_minus_h_originhb_font_t415   void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
416 				      hb_position_t *x, hb_position_t *y)
417   {
418     *x = get_glyph_h_advance (glyph) / 2;
419 
420     /* TODO cache this somehow?! */
421     hb_font_extents_t extents;
422     get_h_extents_with_fallback (&extents);
423     *y = extents.ascender;
424   }
425 
get_glyph_h_origin_with_fallbackhb_font_t426   void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
427 					 hb_position_t *x, hb_position_t *y)
428   {
429     if (!get_glyph_h_origin (glyph, x, y) &&
430 	 get_glyph_v_origin (glyph, x, y))
431     {
432       hb_position_t dx, dy;
433       guess_v_origin_minus_h_origin (glyph, &dx, &dy);
434       *x -= dx; *y -= dy;
435     }
436   }
get_glyph_v_origin_with_fallbackhb_font_t437   void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
438 					 hb_position_t *x, hb_position_t *y)
439   {
440     if (!get_glyph_v_origin (glyph, x, y) &&
441 	 get_glyph_h_origin (glyph, x, y))
442     {
443       hb_position_t dx, dy;
444       guess_v_origin_minus_h_origin (glyph, &dx, &dy);
445       *x += dx; *y += dy;
446     }
447   }
448 
get_glyph_origin_for_directionhb_font_t449   void get_glyph_origin_for_direction (hb_codepoint_t glyph,
450 				       hb_direction_t direction,
451 				       hb_position_t *x, hb_position_t *y)
452   {
453     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
454       get_glyph_h_origin_with_fallback (glyph, x, y);
455     else
456       get_glyph_v_origin_with_fallback (glyph, x, y);
457   }
458 
add_glyph_h_originhb_font_t459   void add_glyph_h_origin (hb_codepoint_t glyph,
460 			   hb_position_t *x, hb_position_t *y)
461   {
462     hb_position_t origin_x, origin_y;
463 
464     get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
465 
466     *x += origin_x;
467     *y += origin_y;
468   }
add_glyph_v_originhb_font_t469   void add_glyph_v_origin (hb_codepoint_t glyph,
470 			   hb_position_t *x, hb_position_t *y)
471   {
472     hb_position_t origin_x, origin_y;
473 
474     get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
475 
476     *x += origin_x;
477     *y += origin_y;
478   }
add_glyph_origin_for_directionhb_font_t479   void add_glyph_origin_for_direction (hb_codepoint_t glyph,
480 				       hb_direction_t direction,
481 				       hb_position_t *x, hb_position_t *y)
482   {
483     hb_position_t origin_x, origin_y;
484 
485     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
486 
487     *x += origin_x;
488     *y += origin_y;
489   }
490 
subtract_glyph_h_originhb_font_t491   void subtract_glyph_h_origin (hb_codepoint_t glyph,
492 			        hb_position_t *x, hb_position_t *y)
493   {
494     hb_position_t origin_x, origin_y;
495 
496     get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
497 
498     *x -= origin_x;
499     *y -= origin_y;
500   }
subtract_glyph_v_originhb_font_t501   void subtract_glyph_v_origin (hb_codepoint_t glyph,
502 				hb_position_t *x, hb_position_t *y)
503   {
504     hb_position_t origin_x, origin_y;
505 
506     get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
507 
508     *x -= origin_x;
509     *y -= origin_y;
510   }
subtract_glyph_origin_for_directionhb_font_t511   void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
512 					    hb_direction_t direction,
513 					    hb_position_t *x, hb_position_t *y)
514   {
515     hb_position_t origin_x, origin_y;
516 
517     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
518 
519     *x -= origin_x;
520     *y -= origin_y;
521   }
522 
get_glyph_kerning_for_directionhb_font_t523   void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
524 					hb_direction_t direction,
525 					hb_position_t *x, hb_position_t *y)
526   {
527     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
528       *y = 0;
529       *x = get_glyph_h_kerning (first_glyph, second_glyph);
530     } else {
531       *x = 0;
532       *y = get_glyph_v_kerning (first_glyph, second_glyph);
533     }
534   }
535 
get_glyph_extents_for_originhb_font_t536   hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
537 					  hb_direction_t direction,
538 					  hb_glyph_extents_t *extents)
539   {
540     hb_bool_t ret = get_glyph_extents (glyph, extents);
541 
542     if (ret)
543       subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
544 
545     return ret;
546   }
547 
get_glyph_contour_point_for_originhb_font_t548   hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
549 						hb_direction_t direction,
550 						hb_position_t *x, hb_position_t *y)
551   {
552     hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
553 
554     if (ret)
555       subtract_glyph_origin_for_direction (glyph, direction, x, y);
556 
557     return ret;
558   }
559 
560   /* Generates gidDDD if glyph has no name. */
561   void
glyph_to_stringhb_font_t562   glyph_to_string (hb_codepoint_t glyph,
563 		   char *s, unsigned int size)
564   {
565     if (get_glyph_name (glyph, s, size)) return;
566 
567     if (size && snprintf (s, size, "gid%u", glyph) < 0)
568       *s = '\0';
569   }
570 
571   /* Parses gidDDD and uniUUUU strings automatically. */
572   hb_bool_t
glyph_from_stringhb_font_t573   glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
574 		     hb_codepoint_t *glyph)
575   {
576     if (get_glyph_from_name (s, len, glyph)) return true;
577 
578     if (len == -1) len = strlen (s);
579 
580     /* Straight glyph index. */
581     if (hb_codepoint_parse (s, len, 10, glyph))
582       return true;
583 
584     if (len > 3)
585     {
586       /* gidDDD syntax for glyph indices. */
587       if (0 == strncmp (s, "gid", 3) &&
588 	  hb_codepoint_parse (s + 3, len - 3, 10, glyph))
589 	return true;
590 
591       /* uniUUUU and other Unicode character indices. */
592       hb_codepoint_t unichar;
593       if (0 == strncmp (s, "uni", 3) &&
594 	  hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
595 	  get_nominal_glyph (unichar, glyph))
596 	return true;
597     }
598 
599     return false;
600   }
601 
em_scalehb_font_t602   hb_position_t em_scale (int16_t v, int scale)
603   {
604     int upem = face->get_upem ();
605     int64_t scaled = v * (int64_t) scale;
606     scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
607     return (hb_position_t) (scaled / upem);
608   }
em_scalefhb_font_t609   hb_position_t em_scalef (float v, int scale)
610   { return (hb_position_t) round (v * scale / face->get_upem ()); }
em_fscalehb_font_t611   float em_fscale (int16_t v, int scale)
612   { return (float) v * scale / face->get_upem (); }
613 };
614 DECLARE_NULL_INSTANCE (hb_font_t);
615 
616 
617 #endif /* HB_FONT_HH */
618