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 */
 130   int dir_scale (hb_direction_t direction)
 131   { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
 132   hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
 133   hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
 134   hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
 135   hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
 136   float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
 137   float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
 138   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 */
 142   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   }
 148   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   }
 154   hb_position_t parent_scale_x_position (hb_position_t v)
 155   { return parent_scale_x_distance (v); }
 156   hb_position_t parent_scale_y_position (hb_position_t v)
 157   { return parent_scale_y_distance (v); }
 158 
 159   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   }
 164   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 
 195   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   }
 202   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 
 210   bool has_glyph (hb_codepoint_t unicode)
 211   {
 212     hb_codepoint_t glyph;
 213     return get_nominal_glyph (unicode, &glyph);
 214   }
 215 
 216   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   }
 224   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 
 237   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 
 246   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 
 253   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 
 260   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 
 273   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 
 286   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 
 295   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 
 304   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 
 312   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 
 320   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 
 330   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 
 340   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 
 350   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 
 364   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   }
 373   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 
 383   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 
 392   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   }
 402   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 
 415   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 
 426   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   }
 437   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 
 449   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 
 459   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   }
 469   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   }
 479   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 
 491   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   }
 501   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   }
 511   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 
 523   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 
 536   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 
 548   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
 562   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
 573   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 
 602   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   }
 609   hb_position_t em_scalef (float v, int scale)
 610   { return (hb_position_t) round (v * scale / face->get_upem ()); }
 611   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 */