tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

hb-font.hh (33559B)


      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-atomic.hh"
     36 #include "hb-draw.hh"
     37 #include "hb-paint-extents.hh"
     38 #include "hb-shaper.hh"
     39 #include "hb-outline.hh"
     40 
     41 
     42 /*
     43 * hb_font_funcs_t
     44 */
     45 
     46 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
     47  HB_FONT_FUNC_IMPLEMENT (get_,font_h_extents) \
     48  HB_FONT_FUNC_IMPLEMENT (get_,font_v_extents) \
     49  HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyph) \
     50  HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyphs) \
     51  HB_FONT_FUNC_IMPLEMENT (get_,variation_glyph) \
     52  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advance) \
     53  HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advance) \
     54  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advances) \
     55  HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advances) \
     56  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origin) \
     57  HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origin) \
     58  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origins) \
     59  HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origins) \
     60  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_kerning) \
     61  HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_kerning)) \
     62  HB_FONT_FUNC_IMPLEMENT (get_,glyph_extents) \
     63  HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \
     64  HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \
     65  HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \
     66  HB_FONT_FUNC_IMPLEMENT (,draw_glyph_or_fail) \
     67  HB_FONT_FUNC_IMPLEMENT (,paint_glyph_or_fail) \
     68  /* ^--- Add new callbacks here */
     69 
     70 struct hb_font_funcs_t
     71 {
     72  hb_object_header_t header;
     73 
     74  struct {
     75 #define HB_FONT_FUNC_IMPLEMENT(get_,name) void *name;
     76    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
     77 #undef HB_FONT_FUNC_IMPLEMENT
     78  } *user_data;
     79 
     80  struct {
     81 #define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_destroy_func_t name;
     82    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
     83 #undef HB_FONT_FUNC_IMPLEMENT
     84  } *destroy;
     85 
     86  /* Don't access these directly.  Call font->get_*() instead. */
     87  union get_t {
     88    struct get_funcs_t {
     89 #define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_font_##get_##name##_func_t name;
     90      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
     91 #undef HB_FONT_FUNC_IMPLEMENT
     92    } f;
     93    void (*array[0
     94 #define HB_FONT_FUNC_IMPLEMENT(get_,name) +1
     95      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
     96 #undef HB_FONT_FUNC_IMPLEMENT
     97 	]) ();
     98  } get;
     99 };
    100 DECLARE_NULL_INSTANCE (hb_font_funcs_t);
    101 
    102 
    103 /*
    104 * hb_font_t
    105 */
    106 
    107 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font);
    108 #include "hb-shaper-list.hh"
    109 #undef HB_SHAPER_IMPLEMENT
    110 
    111 struct hb_font_t
    112 {
    113  hb_object_header_t header;
    114  hb_atomic_t<unsigned> serial;
    115  hb_atomic_t<unsigned> serial_coords;
    116 
    117  hb_font_t *parent;
    118  hb_face_t *face;
    119 
    120  int32_t x_scale;
    121  int32_t y_scale;
    122 
    123  bool is_synthetic;
    124 
    125  float x_embolden;
    126  float y_embolden;
    127  bool embolden_in_place;
    128  int32_t x_strength; /* x_embolden, in scaled units. */
    129  int32_t y_strength; /* y_embolden, in scaled units. */
    130 
    131  float slant;
    132  float slant_xy;
    133 
    134  float x_multf;
    135  float y_multf;
    136  int64_t x_mult;
    137  int64_t y_mult;
    138 
    139  unsigned int x_ppem;
    140  unsigned int y_ppem;
    141 
    142  float ptem;
    143 
    144  /* Font variation coordinates. */
    145  unsigned int instance_index;
    146  bool has_nonzero_coords;
    147  unsigned int num_coords;
    148  int *coords;
    149  float *design_coords;
    150 
    151  hb_font_funcs_t   *klass;
    152  void              *user_data;
    153  hb_destroy_func_t  destroy;
    154 
    155  hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */
    156 
    157 
    158  /* Convert from font-space to user-space */
    159  int64_t dir_mult (hb_direction_t direction)
    160  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
    161  hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
    162  hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
    163  hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); }
    164  hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
    165  float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); }
    166  float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); }
    167  float em_fscalef_x (float v) { return em_fmultf (v, x_multf); }
    168  float em_fscalef_y (float v) { return em_fmultf (v, y_multf); }
    169  hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
    170  { return em_mult (v, dir_mult (direction)); }
    171 
    172  /* Convert from parent-font user-space to our user-space */
    173  hb_position_t parent_scale_x_distance (hb_position_t v)
    174  {
    175    if (unlikely (parent && parent->x_scale != x_scale))
    176      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
    177    return v;
    178  }
    179  hb_position_t parent_scale_y_distance (hb_position_t v)
    180  {
    181    if (unlikely (parent && parent->y_scale != y_scale))
    182      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
    183    return v;
    184  }
    185  hb_position_t parent_scale_x_position (hb_position_t v)
    186  { return parent_scale_x_distance (v); }
    187  hb_position_t parent_scale_y_position (hb_position_t v)
    188  { return parent_scale_y_distance (v); }
    189 
    190  void parent_scale_distance (hb_position_t *x, hb_position_t *y)
    191  {
    192    *x = parent_scale_x_distance (*x);
    193    *y = parent_scale_y_distance (*y);
    194  }
    195  void parent_scale_position (hb_position_t *x, hb_position_t *y)
    196  {
    197    *x = parent_scale_x_position (*x);
    198    *y = parent_scale_y_position (*y);
    199  }
    200 
    201  void scale_glyph_extents (hb_glyph_extents_t *extents)
    202  {
    203    float x1 = em_scale_x (extents->x_bearing);
    204    float y1 = em_scale_y (extents->y_bearing);
    205    float x2 = em_scale_x (extents->x_bearing + extents->width);
    206    float y2 = em_scale_y (extents->y_bearing + extents->height);
    207 
    208    extents->x_bearing = roundf (x1);
    209    extents->y_bearing = roundf (y1);
    210    extents->width = roundf (x2) - extents->x_bearing;
    211    extents->height = roundf (y2) - extents->y_bearing;
    212  }
    213 
    214  void synthetic_glyph_extents (hb_glyph_extents_t *extents)
    215  {
    216    /* Slant. */
    217    if (slant_xy)
    218    {
    219      hb_position_t x1 = extents->x_bearing;
    220      hb_position_t y1 = extents->y_bearing;
    221      hb_position_t x2 = extents->x_bearing + extents->width;
    222      hb_position_t y2 = extents->y_bearing + extents->height;
    223 
    224      x1 += floorf (hb_min (y1 * slant_xy, y2 * slant_xy));
    225      x2 += ceilf (hb_max (y1 * slant_xy, y2 * slant_xy));
    226 
    227      extents->x_bearing = x1;
    228      extents->width = x2 - extents->x_bearing;
    229    }
    230 
    231    /* Embolden. */
    232    if (x_strength || y_strength)
    233    {
    234      /* Y */
    235      int y_shift = y_strength;
    236      if (y_scale < 0) y_shift = -y_shift;
    237      extents->y_bearing += y_shift;
    238      extents->height -= y_shift;
    239 
    240      /* X */
    241      int x_shift = x_strength;
    242      if (x_scale < 0) x_shift = -x_shift;
    243      if (embolden_in_place)
    244 extents->x_bearing -= x_shift / 2;
    245      extents->width += x_shift;
    246    }
    247  }
    248 
    249 
    250  /* Public getters */
    251 
    252  HB_INTERNAL bool has_func (unsigned int i);
    253  HB_INTERNAL bool has_func_set (unsigned int i);
    254 
    255  /* has_* ... */
    256 #define HB_FONT_FUNC_IMPLEMENT(get_,name) \
    257  bool \
    258  has_##name##_func () \
    259  { \
    260    hb_font_funcs_t *funcs = this->klass; \
    261    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
    262    return has_func (i); \
    263  } \
    264  bool \
    265  has_##name##_func_set () \
    266  { \
    267    hb_font_funcs_t *funcs = this->klass; \
    268    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
    269    return has_func_set (i); \
    270  }
    271  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
    272 #undef HB_FONT_FUNC_IMPLEMENT
    273 
    274  hb_bool_t get_font_h_extents (hb_font_extents_t *extents,
    275 			bool synthetic = true)
    276  {
    277    hb_memset (extents, 0, sizeof (*extents));
    278    bool ret = klass->get.f.font_h_extents (this, user_data,
    279 				    extents,
    280 				    !klass->user_data ? nullptr : klass->user_data->font_h_extents);
    281 
    282    if (synthetic && ret)
    283    {
    284      /* Embolden */
    285      int y_shift = y_scale < 0 ? -y_strength : y_strength;
    286      extents->ascender += y_shift;
    287    }
    288 
    289    return ret;
    290  }
    291  hb_bool_t get_font_v_extents (hb_font_extents_t *extents,
    292 			bool synthetic = true)
    293  {
    294    hb_memset (extents, 0, sizeof (*extents));
    295    bool ret = klass->get.f.font_v_extents (this, user_data,
    296 				    extents,
    297 				    !klass->user_data ? nullptr : klass->user_data->font_v_extents);
    298 
    299    if (synthetic && ret)
    300    {
    301      /* Embolden */
    302      int x_shift = x_scale < 0 ? -x_strength : x_strength;
    303      if (embolden_in_place)
    304      {
    305 extents->ascender += x_shift / 2;
    306 extents->descender -= x_shift - x_shift / 2;
    307      }
    308      else
    309 extents->ascender += x_shift;
    310    }
    311 
    312    return ret;
    313  }
    314 
    315  bool has_glyph (hb_codepoint_t unicode)
    316  {
    317    hb_codepoint_t glyph;
    318    return get_nominal_glyph (unicode, &glyph);
    319  }
    320 
    321  hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
    322 		       hb_codepoint_t *glyph,
    323 		       hb_codepoint_t not_found = 0)
    324  {
    325    *glyph = not_found;
    326    return klass->get.f.nominal_glyph (this, user_data,
    327 			       unicode, glyph,
    328 			       !klass->user_data ? nullptr : klass->user_data->nominal_glyph);
    329  }
    330  unsigned int get_nominal_glyphs (unsigned int count,
    331 			   const hb_codepoint_t *first_unicode,
    332 			   unsigned int unicode_stride,
    333 			   hb_codepoint_t *first_glyph,
    334 			   unsigned int glyph_stride)
    335  {
    336    return klass->get.f.nominal_glyphs (this, user_data,
    337 				count,
    338 				first_unicode, unicode_stride,
    339 				first_glyph, glyph_stride,
    340 				!klass->user_data ? nullptr : klass->user_data->nominal_glyphs);
    341  }
    342 
    343  hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
    344 			 hb_codepoint_t *glyph,
    345 			 hb_codepoint_t not_found = 0)
    346  {
    347    *glyph = not_found;
    348    return klass->get.f.variation_glyph (this, user_data,
    349 				 unicode, variation_selector, glyph,
    350 				 !klass->user_data ? nullptr : klass->user_data->variation_glyph);
    351  }
    352 
    353  hb_position_t get_glyph_h_advance (hb_codepoint_t glyph,
    354 			     bool synthetic = true)
    355  {
    356    hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data,
    357 						  glyph,
    358 						  !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
    359 
    360    if (synthetic && x_strength && !embolden_in_place)
    361    {
    362      /* Embolden */
    363      hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
    364      advance += advance ? strength : 0;
    365    }
    366 
    367    return advance;
    368  }
    369 
    370  hb_position_t get_glyph_v_advance (hb_codepoint_t glyph,
    371 			     bool synthetic = true)
    372  {
    373    hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data,
    374 						  glyph,
    375 						  !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
    376 
    377    if (synthetic && y_strength && !embolden_in_place)
    378    {
    379      /* Embolden */
    380      hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
    381      advance += advance ? strength : 0;
    382    }
    383 
    384    return advance;
    385  }
    386 
    387  void get_glyph_h_advances (unsigned int count,
    388 		     const hb_codepoint_t *first_glyph,
    389 		     unsigned int glyph_stride,
    390 		     hb_position_t *first_advance,
    391 		     unsigned int advance_stride,
    392 		     bool synthetic = true)
    393  {
    394    klass->get.f.glyph_h_advances (this, user_data,
    395 			   count,
    396 			   first_glyph, glyph_stride,
    397 			   first_advance, advance_stride,
    398 			   !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
    399 
    400    if (synthetic && x_strength && !embolden_in_place)
    401    {
    402      /* Embolden */
    403      hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
    404      for (unsigned int i = 0; i < count; i++)
    405      {
    406 *first_advance += *first_advance ? strength : 0;
    407 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    408      }
    409    }
    410  }
    411 
    412  void get_glyph_v_advances (unsigned int count,
    413 		     const hb_codepoint_t *first_glyph,
    414 		     unsigned int glyph_stride,
    415 		     hb_position_t *first_advance,
    416 		     unsigned int advance_stride,
    417 		     bool synthetic = true)
    418  {
    419    klass->get.f.glyph_v_advances (this, user_data,
    420 			   count,
    421 			   first_glyph, glyph_stride,
    422 			   first_advance, advance_stride,
    423 			   !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
    424 
    425    if (synthetic && y_strength && !embolden_in_place)
    426    {
    427      /* Embolden */
    428      hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
    429      for (unsigned int i = 0; i < count; i++)
    430      {
    431 *first_advance += *first_advance ? strength : 0;
    432 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    433      }
    434    }
    435  }
    436 
    437  hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
    438 			hb_position_t *x, hb_position_t *y,
    439 			bool synthetic = true)
    440  {
    441    *x = *y = 0;
    442    bool ret = klass->get.f.glyph_h_origin (this, user_data,
    443 				    glyph, x, y,
    444 				    !klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
    445 
    446    if (synthetic && ret)
    447    {
    448      /* Slant is ignored as it does not affect glyph origin */
    449 
    450      /* Embolden */
    451      if (!embolden_in_place)
    452      {
    453        *x += x_scale < 0 ? -x_strength : x_strength;
    454 *y += y_scale < 0 ? -y_strength : y_strength;
    455      }
    456    }
    457 
    458    return ret;
    459  }
    460 
    461  hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
    462 			hb_position_t *x, hb_position_t *y,
    463 			bool synthetic = true)
    464  {
    465    *x = *y = 0;
    466    bool ret = klass->get.f.glyph_v_origin (this, user_data,
    467 				    glyph, x, y,
    468 				    !klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
    469 
    470    if (synthetic && ret)
    471    {
    472      /* Slant is ignored as it does not affect glyph origin */
    473 
    474      /* Embolden */
    475      if (!embolden_in_place)
    476      {
    477        *x += x_scale < 0 ? -x_strength : x_strength;
    478 *y += y_scale < 0 ? -y_strength : y_strength;
    479      }
    480    }
    481 
    482    return ret;
    483  }
    484 
    485  hb_bool_t get_glyph_h_origins (unsigned int count,
    486 			 const hb_codepoint_t *first_glyph,
    487 			 unsigned int glyph_stride,
    488 			 hb_position_t *first_x,
    489 			 unsigned int x_stride,
    490 			 hb_position_t *first_y,
    491 			 unsigned int y_stride,
    492 			 bool synthetic = true)
    493 
    494  {
    495    bool ret = klass->get.f.glyph_h_origins (this, user_data,
    496 				     count,
    497 				     first_glyph, glyph_stride,
    498 				     first_x, x_stride, first_y, y_stride,
    499 				     !klass->user_data ? nullptr : klass->user_data->glyph_h_origins);
    500 
    501    if (synthetic && ret)
    502    {
    503      hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength;
    504      hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
    505      for (unsigned i = 0; i < count; i++)
    506      {
    507 /* Slant is ignored as it does not affect glyph origin */
    508 
    509 /* Embolden */
    510 if (!embolden_in_place)
    511 {
    512   *first_x += x_shift;
    513   *first_y += y_shift;
    514 }
    515 first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
    516 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
    517      }
    518    }
    519 
    520    return ret;
    521  }
    522 
    523  hb_bool_t get_glyph_v_origins (unsigned int count,
    524 			 const hb_codepoint_t *first_glyph,
    525 			 unsigned int glyph_stride,
    526 			 hb_position_t *first_x,
    527 			 unsigned int x_stride,
    528 			 hb_position_t *first_y,
    529 			 unsigned int y_stride,
    530 			 bool synthetic = true)
    531 
    532  {
    533    bool ret = klass->get.f.glyph_v_origins (this, user_data,
    534 				     count,
    535 				     first_glyph, glyph_stride,
    536 				     first_x, x_stride, first_y, y_stride,
    537 				     !klass->user_data ? nullptr : klass->user_data->glyph_v_origins);
    538 
    539    if (synthetic && is_synthetic && ret)
    540    {
    541      hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength;
    542      hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
    543      for (unsigned i = 0; i < count; i++)
    544      {
    545 /* Slant is ignored as it does not affect glyph origin */
    546 
    547 /* Embolden */
    548 if (!embolden_in_place)
    549 {
    550   *first_x += x_shift;
    551   *first_y += y_shift;
    552 }
    553 first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
    554 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
    555      }
    556    }
    557 
    558    return ret;
    559  }
    560 
    561  hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
    562 			     hb_codepoint_t right_glyph)
    563  {
    564 #ifdef HB_DISABLE_DEPRECATED
    565    return 0;
    566 #else
    567    return klass->get.f.glyph_h_kerning (this, user_data,
    568 				 left_glyph, right_glyph,
    569 				 !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning);
    570 #endif
    571  }
    572 
    573  hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
    574 			     hb_codepoint_t bottom_glyph)
    575  {
    576 #ifdef HB_DISABLE_DEPRECATED
    577    return 0;
    578 #else
    579    return klass->get.f.glyph_v_kerning (this, user_data,
    580 				 top_glyph, bottom_glyph,
    581 				 !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning);
    582 #endif
    583  }
    584 
    585  hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
    586 		       hb_glyph_extents_t *extents,
    587 		       bool synthetic = true)
    588  {
    589    hb_memset (extents, 0, sizeof (*extents));
    590 
    591    /* This is rather messy, but necessary. */
    592 
    593    if (!synthetic)
    594    {
    595      return klass->get.f.glyph_extents (this, user_data,
    596 				 glyph,
    597 				 extents,
    598 				 !klass->user_data ? nullptr : klass->user_data->glyph_extents);
    599    }
    600    if (!is_synthetic &&
    601 klass->get.f.glyph_extents (this, user_data,
    602 			    glyph,
    603 			    extents,
    604 			    !klass->user_data ? nullptr : klass->user_data->glyph_extents))
    605      return true;
    606 
    607    /* Try getting extents from paint(), then draw(), *then* get_extents()
    608     * and apply synthetic settings in the last case. */
    609 
    610 #ifndef HB_NO_PAINT
    611    hb_paint_extents_context_t paint_extents;
    612    if (paint_glyph_or_fail (glyph,
    613 		     hb_paint_extents_get_funcs (), &paint_extents,
    614 		     0, 0))
    615    {
    616      *extents = paint_extents.get_extents ().to_glyph_extents ();
    617      return true;
    618    }
    619 #endif
    620 
    621 #ifndef HB_NO_DRAW
    622    hb_extents_t<> draw_extents;
    623    if (draw_glyph_or_fail (glyph,
    624 		    hb_draw_extents_get_funcs (), &draw_extents))
    625    {
    626      *extents = draw_extents.to_glyph_extents ();
    627      return true;
    628    }
    629 #endif
    630 
    631    bool ret = klass->get.f.glyph_extents (this, user_data,
    632 				   glyph,
    633 				   extents,
    634 				   !klass->user_data ? nullptr : klass->user_data->glyph_extents);
    635    if (ret)
    636      synthetic_glyph_extents (extents);
    637 
    638    return ret;
    639  }
    640 
    641  hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
    642 			     hb_position_t *x, hb_position_t *y,
    643 			     bool synthetic = true)
    644  {
    645    *x = *y = 0;
    646    bool ret = klass->get.f.glyph_contour_point (this, user_data,
    647 					 glyph, point_index,
    648 					 x, y,
    649 					 !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
    650 
    651    if (synthetic && ret)
    652    {
    653      /* Slant */
    654      if (slant_xy)
    655        *x += roundf (*y * slant_xy);
    656 
    657      /* Embolden */
    658      if (!embolden_in_place)
    659      {
    660 int x_shift = x_scale < 0 ? -x_strength : x_strength;
    661 *x += x_shift;
    662      }
    663    }
    664 
    665    return ret;
    666  }
    667 
    668  hb_bool_t get_glyph_name (hb_codepoint_t glyph,
    669 		    char *name, unsigned int size)
    670  {
    671    if (size) *name = '\0';
    672    return klass->get.f.glyph_name (this, user_data,
    673 			    glyph,
    674 			    name, size,
    675 			    !klass->user_data ? nullptr : klass->user_data->glyph_name);
    676  }
    677 
    678  hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
    679 			 hb_codepoint_t *glyph)
    680  {
    681    *glyph = 0;
    682    if (len == -1) len = strlen (name);
    683    return klass->get.f.glyph_from_name (this, user_data,
    684 				 name, len,
    685 				 glyph,
    686 				 !klass->user_data ? nullptr : klass->user_data->glyph_from_name);
    687  }
    688 
    689  bool draw_glyph_or_fail (hb_codepoint_t glyph,
    690 		   hb_draw_funcs_t *draw_funcs, void *draw_data,
    691 		   bool synthetic = true)
    692  {
    693 #ifndef HB_NO_DRAW
    694 #ifndef HB_NO_OUTLINE
    695    bool embolden = x_strength || y_strength;
    696    bool slanted = slant_xy;
    697    synthetic = synthetic && (embolden || slanted);
    698 #else
    699    synthetic = false;
    700 #endif
    701 
    702    if (!synthetic)
    703    {
    704      return klass->get.f.draw_glyph_or_fail (this, user_data,
    705 				      glyph,
    706 				      draw_funcs, draw_data,
    707 				      !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail);
    708    }
    709 
    710 #ifndef HB_NO_OUTLINE
    711 
    712    hb_outline_t outline;
    713    if (!klass->get.f.draw_glyph_or_fail (this, user_data,
    714 				  glyph,
    715 				  hb_outline_recording_pen_get_funcs (), &outline,
    716 				  !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail))
    717      return false;
    718 
    719    // Slant before embolden; produces nicer results.
    720 
    721    if (slanted)
    722    {
    723      hb_position_t xo = 0, yo = 0;
    724      get_glyph_h_origin (glyph, &xo, &yo, false);
    725      outline.translate (-xo, -yo);
    726      outline.slant (slant_xy);
    727      outline.translate (xo, yo);
    728    }
    729 
    730    if (embolden)
    731    {
    732      float x_shift = embolden_in_place ? 0 : (float) x_strength / 2;
    733      float y_shift = (float) y_strength / 2;
    734      if (x_scale < 0) x_shift = -x_shift;
    735      if (y_scale < 0) y_shift = -y_shift;
    736      outline.embolden (x_strength, y_strength, x_shift, y_shift);
    737    }
    738 
    739    outline.replay (draw_funcs, draw_data);
    740 
    741    return true;
    742 #endif
    743 #endif
    744    return false;
    745  }
    746 
    747  bool paint_glyph_or_fail (hb_codepoint_t glyph,
    748 		    hb_paint_funcs_t *paint_funcs, void *paint_data,
    749 		    unsigned int palette,
    750 		    hb_color_t foreground,
    751 		    bool synthetic = true)
    752  {
    753 #ifndef HB_NO_PAINT
    754    /* Slant */
    755    if (synthetic && slant_xy)
    756      hb_paint_push_transform (paint_funcs, paint_data,
    757 		       1.f, 0.f,
    758 		       slant_xy, 1.f,
    759 		       0.f, 0.f);
    760 
    761    bool ret = klass->get.f.paint_glyph_or_fail (this, user_data,
    762 					 glyph,
    763 					 paint_funcs, paint_data,
    764 					 palette, foreground,
    765 					 !klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail);
    766 
    767    if (synthetic && slant_xy)
    768      hb_paint_pop_transform (paint_funcs, paint_data);
    769 
    770    return ret;
    771 #endif
    772    return false;
    773  }
    774 
    775  /* A bit higher-level, and with fallback */
    776 
    777  HB_INTERNAL
    778  void paint_glyph (hb_codepoint_t glyph,
    779 	    hb_paint_funcs_t *paint_funcs, void *paint_data,
    780 	    unsigned int palette,
    781 	    hb_color_t foreground);
    782 
    783  void get_h_extents_with_fallback (hb_font_extents_t *extents)
    784  {
    785    if (!get_font_h_extents (extents))
    786    {
    787      extents->ascender = y_scale * .8;
    788      extents->descender = extents->ascender - y_scale;
    789      extents->line_gap = 0;
    790    }
    791  }
    792  void get_v_extents_with_fallback (hb_font_extents_t *extents)
    793  {
    794    if (!get_font_v_extents (extents))
    795    {
    796      extents->ascender = x_scale / 2;
    797      extents->descender = extents->ascender - x_scale;
    798      extents->line_gap = 0;
    799    }
    800  }
    801 
    802  void get_extents_for_direction (hb_direction_t direction,
    803 			  hb_font_extents_t *extents)
    804  {
    805    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
    806      get_h_extents_with_fallback (extents);
    807    else
    808      get_v_extents_with_fallback (extents);
    809  }
    810 
    811  void get_glyph_advance_for_direction (hb_codepoint_t glyph,
    812 				hb_direction_t direction,
    813 				hb_position_t *x, hb_position_t *y)
    814  {
    815    *x = *y = 0;
    816    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
    817      *x = get_glyph_h_advance (glyph);
    818    else
    819      *y = get_glyph_v_advance (glyph);
    820  }
    821  void get_glyph_advances_for_direction (hb_direction_t direction,
    822 				 unsigned int count,
    823 				 const hb_codepoint_t *first_glyph,
    824 				 unsigned glyph_stride,
    825 				 hb_position_t *first_advance,
    826 				 unsigned advance_stride)
    827  {
    828    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
    829      get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
    830    else
    831      get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
    832  }
    833 
    834  void apply_offset (hb_position_t *x, hb_position_t *y,
    835 	     hb_position_t dx, hb_position_t dy,
    836 	     signed mult)
    837  {
    838    assert (mult == -1 || mult == +1);
    839 
    840    *x += dx * mult;
    841    *y += dy * mult;
    842  }
    843  void add_offset (hb_position_t *x, hb_position_t *y,
    844 	   hb_position_t dx, hb_position_t dy)
    845  {
    846    *x += dx;
    847    *y += dy;
    848  }
    849  void subtract_offset (hb_position_t *x, hb_position_t *y,
    850 		hb_position_t dx, hb_position_t dy)
    851  {
    852    *x -= dx;
    853    *y -= dy;
    854  }
    855 
    856  void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
    857 			      hb_position_t *x, hb_position_t *y)
    858  {
    859    *x = get_glyph_h_advance (glyph) / 2;
    860 
    861    hb_font_extents_t extents;
    862    get_h_extents_with_fallback (&extents);
    863    *y = extents.ascender;
    864  }
    865 
    866  void apply_glyph_h_origins_with_fallback (hb_buffer_t *buf, int mult)
    867  {
    868    bool has_ascender = false;
    869    hb_position_t ascender = 0;
    870 
    871    struct { hb_position_t x, y; } origins[32];
    872 
    873    unsigned int offset = 0;
    874    unsigned int count = buf->len;
    875    while (offset < count)
    876    {
    877      unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
    878      if (!get_glyph_h_origins (n,
    879 			&buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
    880 			&origins[0].x, sizeof (origins[0]),
    881 			&origins[0].y, sizeof (origins[0])))
    882      {
    883        if (get_glyph_v_origins (n,
    884 			  &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
    885 			  &origins[0].x, sizeof (origins[0]),
    886 			  &origins[0].y, sizeof (origins[0])))
    887 {
    888   if (!has_ascender)
    889   {
    890     hb_font_extents_t extents;
    891     get_h_extents_with_fallback (&extents);
    892     ascender = extents.ascender;
    893     has_ascender = true;
    894   }
    895 
    896   /* We got the v_origins, adjust them to h_origins. */
    897   for (unsigned j = 0; j < n; j++)
    898   {
    899     hb_codepoint_t glyph = buf->info[offset + j].codepoint;
    900     origins[j].x -= get_glyph_h_advance (glyph) / 2;
    901     origins[j].y -= ascender;
    902   }
    903 }
    904 else
    905 {
    906   for (unsigned j = 0; j < n; j++)
    907   {
    908     origins[j].x = 0;
    909     origins[j].y = 0;
    910   }
    911 }
    912      }
    913 
    914      assert (mult == -1 || mult == +1);
    915      if (mult == +1)
    916        for (unsigned j = 0; j < n; j++)
    917 {
    918   hb_glyph_position_t *pos = &buf->pos[offset + j];
    919   add_offset (&pos->x_offset, &pos->y_offset,
    920 	      origins[j].x, origins[j].y);
    921 }
    922      else /* mult == -1 */
    923 for (unsigned j = 0; j < n; j++)
    924 {
    925   hb_glyph_position_t *pos = &buf->pos[offset + j];
    926   subtract_offset (&pos->x_offset, &pos->y_offset,
    927 		   origins[j].x, origins[j].y);
    928 }
    929 
    930      offset += n;
    931    }
    932  }
    933  void apply_glyph_v_origins_with_fallback (hb_buffer_t *buf, int mult)
    934  {
    935    bool has_ascender = false;
    936    hb_position_t ascender = 0;
    937 
    938    struct { hb_position_t x, y; } origins[32];
    939 
    940    unsigned int offset = 0;
    941    unsigned int count = buf->len;
    942    while (offset < count)
    943    {
    944      unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
    945      if (!get_glyph_v_origins (n,
    946 			&buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
    947 			&origins[0].x, sizeof (origins[0]),
    948 			&origins[0].y, sizeof (origins[0])))
    949      {
    950 if (get_glyph_h_origins (n,
    951 			 &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
    952 			 &origins[0].x, sizeof (origins[0]),
    953 			 &origins[0].y, sizeof (origins[0])))
    954 {
    955   if (!has_ascender)
    956   {
    957     hb_font_extents_t extents;
    958     get_h_extents_with_fallback (&extents);
    959     ascender = extents.ascender;
    960     has_ascender = true;
    961   }
    962 
    963   /* We got the h_origins, adjust them to v_origins. */
    964   for (unsigned j = 0; j < n; j++)
    965   {
    966     hb_codepoint_t glyph = buf->info[offset + j].codepoint;
    967     origins[j].x += get_glyph_h_advance (glyph) / 2;
    968     origins[j].y += ascender;
    969   }
    970 }
    971 else
    972 {
    973   for (unsigned j = 0; j < n; j++)
    974   {
    975     origins[j].x = 0;
    976     origins[j].y = 0;
    977   }
    978 }
    979      }
    980 
    981      assert (mult == -1 || mult == +1);
    982      if (mult == +1)
    983        for (unsigned j = 0; j < n; j++)
    984 {
    985   hb_glyph_position_t *pos = &buf->pos[offset + j];
    986   add_offset (&pos->x_offset, &pos->y_offset,
    987 	      origins[j].x, origins[j].y);
    988 }
    989      else /* mult == -1 */
    990 for (unsigned j = 0; j < n; j++)
    991 {
    992   hb_glyph_position_t *pos = &buf->pos[offset + j];
    993   subtract_offset (&pos->x_offset, &pos->y_offset,
    994 		   origins[j].x, origins[j].y);
    995 }
    996 
    997      offset += n;
    998    }
    999  }
   1000 
   1001  void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
   1002 				 hb_position_t *x, hb_position_t *y)
   1003  {
   1004    if (!get_glyph_h_origin (glyph, x, y) &&
   1005  get_glyph_v_origin (glyph, x, y))
   1006    {
   1007      hb_position_t dx, dy;
   1008      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
   1009      subtract_offset (x, y, dx, dy);
   1010    }
   1011  }
   1012  void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
   1013 				 hb_position_t *x, hb_position_t *y)
   1014  {
   1015    if (!get_glyph_v_origin (glyph, x, y) &&
   1016  get_glyph_h_origin (glyph, x, y))
   1017    {
   1018      hb_position_t dx, dy;
   1019      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
   1020      add_offset (x, y, dx, dy);
   1021    }
   1022  }
   1023 
   1024  void get_glyph_origin_for_direction (hb_codepoint_t glyph,
   1025 			       hb_direction_t direction,
   1026 			       hb_position_t *x, hb_position_t *y)
   1027  {
   1028    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
   1029      get_glyph_h_origin_with_fallback (glyph, x, y);
   1030    else
   1031      get_glyph_v_origin_with_fallback (glyph, x, y);
   1032  }
   1033 
   1034  void add_glyph_h_origins (hb_buffer_t *buf)
   1035  {
   1036    apply_glyph_h_origins_with_fallback (buf, +1);
   1037  }
   1038  void add_glyph_v_origins (hb_buffer_t *buf)
   1039  {
   1040    apply_glyph_v_origins_with_fallback (buf, +1);
   1041  }
   1042  void add_glyph_origin_for_direction (hb_codepoint_t glyph,
   1043 			       hb_direction_t direction,
   1044 			       hb_position_t *x, hb_position_t *y)
   1045  {
   1046    hb_position_t origin_x, origin_y;
   1047    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
   1048    add_offset (x, y, origin_x, origin_y);
   1049  }
   1050 
   1051  void subtract_glyph_h_origins (hb_buffer_t *buf)
   1052  {
   1053    apply_glyph_h_origins_with_fallback (buf, -1);
   1054  }
   1055  void subtract_glyph_v_origins (hb_buffer_t *buf)
   1056  {
   1057    apply_glyph_v_origins_with_fallback (buf, -1);
   1058  }
   1059  void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
   1060 				    hb_direction_t direction,
   1061 				    hb_position_t *x, hb_position_t *y)
   1062  {
   1063    hb_position_t origin_x, origin_y;
   1064    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
   1065    subtract_offset (x, y, origin_x, origin_y);
   1066  }
   1067 
   1068  void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
   1069 				hb_direction_t direction,
   1070 				hb_position_t *x, hb_position_t *y)
   1071  {
   1072    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
   1073      *y = 0;
   1074      *x = get_glyph_h_kerning (first_glyph, second_glyph);
   1075    } else {
   1076      *x = 0;
   1077      *y = get_glyph_v_kerning (first_glyph, second_glyph);
   1078    }
   1079  }
   1080 
   1081  hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
   1082 				  hb_direction_t direction,
   1083 				  hb_glyph_extents_t *extents)
   1084  {
   1085    hb_bool_t ret = get_glyph_extents (glyph, extents);
   1086 
   1087    if (ret)
   1088      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
   1089 
   1090    return ret;
   1091  }
   1092 
   1093  hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
   1094 					hb_direction_t direction,
   1095 					hb_position_t *x, hb_position_t *y)
   1096  {
   1097    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
   1098 
   1099    if (ret)
   1100      subtract_glyph_origin_for_direction (glyph, direction, x, y);
   1101 
   1102    return ret;
   1103  }
   1104 
   1105  /* Generates gidDDD if glyph has no name. */
   1106  void
   1107  glyph_to_string (hb_codepoint_t glyph,
   1108 	   char *s, unsigned int size)
   1109  {
   1110    if (get_glyph_name (glyph, s, size)) return;
   1111 
   1112    if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0)
   1113      *s = '\0';
   1114  }
   1115 
   1116  /* Parses gidDDD and uniUUUU strings automatically. */
   1117  hb_bool_t
   1118  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
   1119 	     hb_codepoint_t *glyph)
   1120  {
   1121    if (get_glyph_from_name (s, len, glyph)) return true;
   1122 
   1123    if (len == -1) len = strlen (s);
   1124 
   1125    /* Straight glyph index. */
   1126    if (hb_codepoint_parse (s, len, 10, glyph))
   1127      return true;
   1128 
   1129    if (len > 3)
   1130    {
   1131      /* gidDDD syntax for glyph indices. */
   1132      if (0 == strncmp (s, "gid", 3) &&
   1133   hb_codepoint_parse (s + 3, len - 3, 10, glyph))
   1134 return true;
   1135 
   1136      /* uniUUUU and other Unicode character indices. */
   1137      hb_codepoint_t unichar;
   1138      if (0 == strncmp (s, "uni", 3) &&
   1139   hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
   1140   get_nominal_glyph (unichar, glyph))
   1141 return true;
   1142    }
   1143 
   1144    return false;
   1145  }
   1146 
   1147  void changed ()
   1148  {
   1149    float upem = face->get_upem ();
   1150 
   1151    x_multf = x_scale / upem;
   1152    y_multf = y_scale / upem;
   1153    bool x_neg = x_scale < 0;
   1154    x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem;
   1155    bool y_neg = y_scale < 0;
   1156    y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
   1157 
   1158    is_synthetic =  x_embolden || y_embolden || slant;
   1159 
   1160    x_strength = roundf (abs (x_scale) * x_embolden);
   1161    y_strength = roundf (abs (y_scale) * y_embolden);
   1162 
   1163    slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
   1164 
   1165    data.fini ();
   1166 
   1167    serial++;
   1168  }
   1169 
   1170  hb_position_t em_mult (int16_t v, int64_t mult)
   1171  { return (hb_position_t) ((v * mult + 32768) >> 16); }
   1172  hb_position_t em_multf (float v, float mult)
   1173  { return (hb_position_t) roundf (em_fmultf (v, mult)); }
   1174  float em_fmultf (float v, float mult)
   1175  { return v * mult; }
   1176  float em_fmult (int16_t v, float mult)
   1177  { return (float) v * mult; }
   1178 };
   1179 DECLARE_NULL_INSTANCE (hb_font_t);
   1180 
   1181 
   1182 #endif /* HB_FONT_HH */