tor-browser

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

hb-ot-font.cc (30620B)


      1 /*
      2 * Copyright © 2011,2014  Google, Inc.
      3 *
      4 *  This is part of HarfBuzz, a text shaping library.
      5 *
      6 * Permission is hereby granted, without written agreement and without
      7 * license or royalty fees, to use, copy, modify, and distribute this
      8 * software and its documentation for any purpose, provided that the
      9 * above copyright notice and the following two paragraphs appear in
     10 * all copies of this software.
     11 *
     12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     16 * DAMAGE.
     17 *
     18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     20 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     23 *
     24 * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
     25 */
     26 
     27 #include "hb.hh"
     28 
     29 #ifndef HB_NO_OT_FONT
     30 
     31 #include "hb-ot.h"
     32 
     33 #include "hb-cache.hh"
     34 #include "hb-font.hh"
     35 #include "hb-machinery.hh"
     36 #include "hb-ot-face.hh"
     37 
     38 #include "hb-ot-cmap-table.hh"
     39 #include "hb-ot-glyf-table.hh"
     40 #include "hb-ot-var-gvar-table.hh"
     41 #include "hb-ot-cff2-table.hh"
     42 #include "hb-ot-cff1-table.hh"
     43 #include "hb-ot-hmtx-table.hh"
     44 #include "hb-ot-post-table.hh"
     45 #include "hb-ot-stat-table.hh"
     46 #include "hb-ot-var-varc-table.hh"
     47 #include "hb-ot-vorg-table.hh"
     48 #include "OT/Color/CBDT/CBDT.hh"
     49 #include "OT/Color/COLR/COLR.hh"
     50 #include "OT/Color/sbix/sbix.hh"
     51 #include "OT/Color/svg/svg.hh"
     52 
     53 
     54 /**
     55 * SECTION:hb-ot-font
     56 * @title: hb-ot-font
     57 * @short_description: OpenType font implementation
     58 * @include: hb-ot.h
     59 *
     60 * Functions for using OpenType fonts with hb_shape().  Note that fonts returned
     61 * by hb_font_create() default to using these functions, so most clients would
     62 * never need to call these functions directly.
     63 **/
     64 
     65 using hb_ot_font_advance_cache_t = hb_cache_t<24, 16>;
     66 static_assert (sizeof (hb_ot_font_advance_cache_t) == 1024, "");
     67 
     68 using hb_ot_font_origin_cache_t = hb_cache_t<20, 20>;
     69 static_assert (sizeof (hb_ot_font_origin_cache_t) == 1024, "");
     70 
     71 struct hb_ot_font_t
     72 {
     73  const hb_ot_face_t *ot_face;
     74 
     75  mutable hb_atomic_t<int> cached_serial;
     76  mutable hb_atomic_t<int> cached_coords_serial;
     77 
     78  struct direction_cache_t
     79  {
     80    mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache;
     81    mutable hb_atomic_t<OT::hb_scalar_cache_t *> varStore_cache;
     82 
     83    ~direction_cache_t ()
     84    {
     85      clear ();
     86    }
     87 
     88    hb_ot_font_advance_cache_t *acquire_advance_cache () const
     89    {
     90    retry:
     91      auto *cache = advance_cache.get_acquire ();
     92      if (!cache)
     93      {
     94        cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
     95 if (!cache)
     96   return nullptr;
     97 new (cache) hb_ot_font_advance_cache_t;
     98 return cache;
     99      }
    100      if (advance_cache.cmpexch (cache, nullptr))
    101        return cache;
    102      else
    103        goto retry;
    104    }
    105    void release_advance_cache (hb_ot_font_advance_cache_t *cache) const
    106    {
    107      if (!cache)
    108        return;
    109      if (!advance_cache.cmpexch (nullptr, cache))
    110        hb_free (cache);
    111    }
    112    void clear_advance_cache () const
    113    {
    114    retry:
    115      auto *cache = advance_cache.get_acquire ();
    116      if (!cache)
    117 return;
    118      if (advance_cache.cmpexch (cache, nullptr))
    119 hb_free (cache);
    120      else
    121        goto retry;
    122    }
    123 
    124    OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
    125    {
    126    retry:
    127      auto *cache = varStore_cache.get_acquire ();
    128      if (!cache)
    129 return varStore.create_cache ();
    130      if (varStore_cache.cmpexch (cache, nullptr))
    131 return cache;
    132      else
    133 goto retry;
    134    }
    135    void release_varStore_cache (OT::hb_scalar_cache_t *cache) const
    136    {
    137      if (!cache)
    138 return;
    139      if (!varStore_cache.cmpexch (nullptr, cache))
    140 OT::ItemVariationStore::destroy_cache (cache);
    141    }
    142    void clear_varStore_cache () const
    143    {
    144    retry:
    145      auto *cache = varStore_cache.get_acquire ();
    146      if (!cache)
    147 return;
    148      if (varStore_cache.cmpexch (cache, nullptr))
    149 OT::ItemVariationStore::destroy_cache (cache);
    150      else
    151 goto retry;
    152    }
    153 
    154    void clear () const
    155    {
    156      clear_advance_cache ();
    157      clear_varStore_cache ();
    158    }
    159 
    160  } h, v;
    161 
    162  struct origin_cache_t
    163  {
    164    mutable hb_atomic_t<hb_ot_font_origin_cache_t *> origin_cache;
    165    mutable hb_atomic_t<OT::hb_scalar_cache_t *> varStore_cache;
    166 
    167    ~origin_cache_t ()
    168    {
    169      clear ();
    170    }
    171 
    172    hb_ot_font_origin_cache_t *acquire_origin_cache () const
    173    {
    174    retry:
    175      auto *cache = origin_cache.get_acquire ();
    176      if (!cache)
    177      {
    178        cache = (hb_ot_font_origin_cache_t *) hb_malloc (sizeof (hb_ot_font_origin_cache_t));
    179 if (!cache)
    180   return nullptr;
    181 new (cache) hb_ot_font_origin_cache_t;
    182 return cache;
    183      }
    184      if (origin_cache.cmpexch (cache, nullptr))
    185        return cache;
    186      else
    187        goto retry;
    188    }
    189    void release_origin_cache (hb_ot_font_origin_cache_t *cache) const
    190    {
    191      if (!cache)
    192        return;
    193      if (!origin_cache.cmpexch (nullptr, cache))
    194        hb_free (cache);
    195    }
    196    void clear_origin_cache () const
    197    {
    198    retry:
    199      auto *cache = origin_cache.get_acquire ();
    200      if (!cache)
    201 return;
    202      if (origin_cache.cmpexch (cache, nullptr))
    203 hb_free (cache);
    204      else
    205        goto retry;
    206    }
    207 
    208    OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
    209    {
    210    retry:
    211      auto *cache = varStore_cache.get_acquire ();
    212      if (!cache)
    213 return varStore.create_cache ();
    214      if (varStore_cache.cmpexch (cache, nullptr))
    215 return cache;
    216      else
    217 goto retry;
    218    }
    219    void release_varStore_cache (OT::hb_scalar_cache_t *cache) const
    220    {
    221      if (!cache)
    222 return;
    223      if (!varStore_cache.cmpexch (nullptr, cache))
    224 OT::ItemVariationStore::destroy_cache (cache);
    225    }
    226    void clear_varStore_cache () const
    227    {
    228    retry:
    229      auto *cache = varStore_cache.get_acquire ();
    230      if (!cache)
    231 return;
    232      if (varStore_cache.cmpexch (cache, nullptr))
    233 OT::ItemVariationStore::destroy_cache (cache);
    234      else
    235 goto retry;
    236    }
    237 
    238    void clear () const
    239    {
    240      clear_origin_cache ();
    241      clear_varStore_cache ();
    242    }
    243  } v_origin;
    244 
    245  struct draw_cache_t
    246  {
    247    mutable hb_atomic_t<OT::hb_scalar_cache_t *> gvar_cache;
    248 
    249    ~draw_cache_t ()
    250    {
    251      clear ();
    252    }
    253 
    254    OT::hb_scalar_cache_t *acquire_gvar_cache (const OT::gvar_accelerator_t &gvar) const
    255    {
    256    retry:
    257      auto *cache = gvar_cache.get_acquire ();
    258      if (!cache)
    259 return gvar.create_cache ();
    260      if (gvar_cache.cmpexch (cache, nullptr))
    261 return cache;
    262      else
    263 goto retry;
    264    }
    265    void release_gvar_cache (OT::hb_scalar_cache_t *cache) const
    266    {
    267      if (!cache)
    268 return;
    269      if (!gvar_cache.cmpexch (nullptr, cache))
    270 OT::gvar_accelerator_t::destroy_cache (cache);
    271    }
    272    void clear_gvar_cache () const
    273    {
    274    retry:
    275      auto *cache = gvar_cache.get_acquire ();
    276      if (!cache)
    277 return;
    278      if (gvar_cache.cmpexch (cache, nullptr))
    279 OT::gvar_accelerator_t::destroy_cache (cache);
    280      else
    281 goto retry;
    282    }
    283 
    284    void clear () const
    285    {
    286      clear_gvar_cache ();
    287    }
    288  } draw;
    289 
    290  void check_serial (hb_font_t *font) const
    291  {
    292    int font_serial = font->serial_coords.get_acquire ();
    293    if (cached_serial.get_acquire () != font_serial)
    294    {
    295      /* These caches are dependent on scale and synthetic settings.
    296       * Any change to the font invalidates them. */
    297      v_origin.clear ();
    298 
    299      cached_serial.set_release (font_serial);
    300    }
    301 
    302    int font_serial_coords = font->serial_coords.get_acquire ();
    303    if (cached_coords_serial.get_acquire () != font_serial_coords)
    304    {
    305      /* These caches are independent of scale or synthetic settings.
    306       * Just variation changes will invalidate them. */
    307      h.clear ();
    308      v.clear ();
    309      draw.clear ();
    310 
    311      cached_coords_serial.set_release (font_serial_coords);
    312    }
    313  }
    314 };
    315 
    316 static hb_ot_font_t *
    317 _hb_ot_font_create (hb_font_t *font)
    318 {
    319  hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
    320  if (unlikely (!ot_font))
    321    return nullptr;
    322 
    323  ot_font->ot_face = &font->face->table;
    324 
    325  return ot_font;
    326 }
    327 
    328 static void
    329 _hb_ot_font_destroy (void *font_data)
    330 {
    331  hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
    332 
    333  ot_font->~hb_ot_font_t ();
    334 
    335  hb_free (ot_font);
    336 }
    337 
    338 static hb_bool_t
    339 hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
    340 		 void *font_data,
    341 		 hb_codepoint_t unicode,
    342 		 hb_codepoint_t *glyph,
    343 		 void *user_data HB_UNUSED)
    344 {
    345  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    346  const hb_ot_face_t *ot_face = ot_font->ot_face;
    347  return ot_face->cmap->get_nominal_glyph (unicode, glyph);
    348 }
    349 
    350 static unsigned int
    351 hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
    352 		  void *font_data,
    353 		  unsigned int count,
    354 		  const hb_codepoint_t *first_unicode,
    355 		  unsigned int unicode_stride,
    356 		  hb_codepoint_t *first_glyph,
    357 		  unsigned int glyph_stride,
    358 		  void *user_data HB_UNUSED)
    359 {
    360  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    361  const hb_ot_face_t *ot_face = ot_font->ot_face;
    362  return ot_face->cmap->get_nominal_glyphs (count,
    363 				    first_unicode, unicode_stride,
    364 				    first_glyph, glyph_stride);
    365 }
    366 
    367 static hb_bool_t
    368 hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
    369 		   void *font_data,
    370 		   hb_codepoint_t unicode,
    371 		   hb_codepoint_t variation_selector,
    372 		   hb_codepoint_t *glyph,
    373 		   void *user_data HB_UNUSED)
    374 {
    375  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    376  const hb_ot_face_t *ot_face = ot_font->ot_face;
    377  return ot_face->cmap->get_variation_glyph (unicode,
    378                                             variation_selector, glyph);
    379 }
    380 
    381 static void
    382 hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
    383 		    unsigned count,
    384 		    const hb_codepoint_t *first_glyph,
    385 		    unsigned glyph_stride,
    386 		    hb_position_t *first_advance,
    387 		    unsigned advance_stride,
    388 		    void *user_data HB_UNUSED)
    389 {
    390  // Duplicated in v_advances. Ugly. Keep in sync'ish.
    391 
    392  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    393  const hb_ot_face_t *ot_face = ot_font->ot_face;
    394  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
    395 
    396  if (unlikely (!hmtx.has_data ()))
    397  {
    398    hb_position_t advance = font->face->get_upem () / 2;
    399    advance = font->em_scale_x (advance);
    400    for (unsigned int i = 0; i < count; i++)
    401    {
    402      *first_advance = advance;
    403      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    404    }
    405    return;
    406  }
    407 
    408 #ifndef HB_NO_VAR
    409  if (!font->has_nonzero_coords)
    410  {
    411  fallback:
    412 #else
    413  {
    414 #endif
    415    // Just plain htmx data. No need to cache.
    416    for (unsigned int i = 0; i < count; i++)
    417    {
    418      *first_advance = font->em_scale_x (hmtx.get_advance_without_var_unscaled (*first_glyph));
    419      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    420      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    421    }
    422    return;
    423  }
    424 
    425 #ifndef HB_NO_VAR
    426  /* has_nonzero_coords. */
    427 
    428  ot_font->check_serial (font);
    429  hb_ot_font_advance_cache_t *advance_cache = ot_font->h.acquire_advance_cache ();
    430  if (!advance_cache)
    431  {
    432    // malloc failure. Just use the fallback non-variable path.
    433    goto fallback;
    434  }
    435 
    436  /* If HVAR is present, use it.*/
    437  const OT::HVAR &HVAR = *hmtx.var_table;
    438  if (HVAR.has_data ())
    439  {
    440    const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
    441    OT::hb_scalar_cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore);
    442 
    443    for (unsigned int i = 0; i < count; i++)
    444    {
    445      hb_position_t v;
    446      unsigned cv;
    447      if (advance_cache->get (*first_glyph, &cv))
    448 v = cv;
    449      else
    450      {
    451        v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
    452 advance_cache->set (*first_glyph, v);
    453      }
    454      *first_advance = font->em_scale_x (v);
    455      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    456      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    457    }
    458 
    459    ot_font->h.release_varStore_cache (varStore_cache);
    460    ot_font->h.release_advance_cache (advance_cache);
    461    return;
    462  }
    463 
    464  const auto &gvar = *ot_face->gvar;
    465  if (gvar.has_data ())
    466  {
    467    const auto &glyf = *ot_face->glyf;
    468    auto *scratch = glyf.acquire_scratch ();
    469    if (unlikely (!scratch))
    470    {
    471      ot_font->h.release_advance_cache (advance_cache);
    472      goto fallback;
    473    }
    474    OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
    475 
    476    for (unsigned int i = 0; i < count; i++)
    477    {
    478      hb_position_t v;
    479      unsigned cv;
    480      if (advance_cache->get (*first_glyph, &cv))
    481 v = cv;
    482      else
    483      {
    484        v = glyf.get_advance_with_var_unscaled (*first_glyph, font, false, *scratch, gvar_cache);
    485 advance_cache->set (*first_glyph, v);
    486      }
    487      *first_advance = font->em_scale_x (v);
    488      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    489      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    490    }
    491 
    492    ot_font->draw.release_gvar_cache (gvar_cache);
    493    glyf.release_scratch (scratch);
    494    ot_font->h.release_advance_cache (advance_cache);
    495    return;
    496  }
    497 
    498  ot_font->h.release_advance_cache (advance_cache);
    499  // No HVAR or GVAR.  Just use the fallback non-variable path.
    500  goto fallback;
    501 #endif
    502 }
    503 
    504 #ifndef HB_NO_VERTICAL
    505 static void
    506 hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
    507 		    unsigned count,
    508 		    const hb_codepoint_t *first_glyph,
    509 		    unsigned glyph_stride,
    510 		    hb_position_t *first_advance,
    511 		    unsigned advance_stride,
    512 		    void *user_data HB_UNUSED)
    513 {
    514  // Duplicated from h_advances. Ugly. Keep in sync'ish.
    515 
    516  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    517  const hb_ot_face_t *ot_face = ot_font->ot_face;
    518  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
    519 
    520  if (unlikely (!vmtx.has_data ()))
    521  {
    522    hb_font_extents_t font_extents;
    523    font->get_h_extents_with_fallback (&font_extents);
    524    hb_position_t advance = font_extents.descender - font_extents.ascender;
    525    for (unsigned int i = 0; i < count; i++)
    526    {
    527      *first_advance = advance;
    528      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    529    }
    530    return;
    531  }
    532 
    533 #ifndef HB_NO_VAR
    534  if (!font->has_nonzero_coords)
    535  {
    536  fallback:
    537 #else
    538  {
    539 #endif
    540    // Just plain vtmx data. No need to cache.
    541    for (unsigned int i = 0; i < count; i++)
    542    {
    543      *first_advance = font->em_scale_y (- (int) vmtx.get_advance_without_var_unscaled (*first_glyph));
    544      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    545      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    546    }
    547    return;
    548  }
    549 
    550 #ifndef HB_NO_VAR
    551  /* has_nonzero_coords. */
    552 
    553  ot_font->check_serial (font);
    554  hb_ot_font_advance_cache_t *advance_cache = ot_font->v.acquire_advance_cache ();
    555  if (!advance_cache)
    556  {
    557    // malloc failure. Just use the fallback non-variable path.
    558    goto fallback;
    559  }
    560 
    561  /* If VVAR is present, use it.*/
    562  const OT::VVAR &VVAR = *vmtx.var_table;
    563  if (VVAR.has_data ())
    564  {
    565    const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
    566    OT::hb_scalar_cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore);
    567 
    568    for (unsigned int i = 0; i < count; i++)
    569    {
    570      hb_position_t v;
    571      unsigned cv;
    572      if (advance_cache->get (*first_glyph, &cv))
    573 v = cv;
    574      else
    575      {
    576        v = vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
    577 advance_cache->set (*first_glyph, v);
    578      }
    579      *first_advance = font->em_scale_y (- (int) v);
    580      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    581      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    582    }
    583 
    584    ot_font->v.release_varStore_cache (varStore_cache);
    585    ot_font->v.release_advance_cache (advance_cache);
    586    return;
    587  }
    588 
    589  const auto &gvar = *ot_face->gvar;
    590  if (gvar.has_data ())
    591  {
    592    const auto &glyf = *ot_face->glyf;
    593    auto *scratch = glyf.acquire_scratch ();
    594    if (unlikely (!scratch))
    595    {
    596      ot_font->v.release_advance_cache (advance_cache);
    597      goto fallback;
    598    }
    599    OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
    600 
    601    for (unsigned int i = 0; i < count; i++)
    602    {
    603      hb_position_t v;
    604      unsigned cv;
    605      if (advance_cache->get (*first_glyph, &cv))
    606 v = cv;
    607      else
    608      {
    609        v = glyf.get_advance_with_var_unscaled (*first_glyph, font, true, *scratch, gvar_cache);
    610 advance_cache->set (*first_glyph, v);
    611      }
    612      *first_advance = font->em_scale_y (- (int) v);
    613      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    614      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
    615    }
    616 
    617    ot_font->draw.release_gvar_cache (gvar_cache);
    618    glyf.release_scratch (scratch);
    619    ot_font->v.release_advance_cache (advance_cache);
    620    return;
    621  }
    622 
    623  ot_font->v.release_advance_cache (advance_cache);
    624  // No VVAR or GVAR.  Just use the fallback non-variable path.
    625  goto fallback;
    626 #endif
    627 }
    628 #endif
    629 
    630 #ifndef HB_NO_VERTICAL
    631 HB_HOT
    632 static hb_bool_t
    633 hb_ot_get_glyph_v_origins (hb_font_t *font,
    634 		   void *font_data,
    635 		   unsigned int count,
    636 		   const hb_codepoint_t *first_glyph,
    637 		   unsigned glyph_stride,
    638 		   hb_position_t *first_x,
    639 		   unsigned x_stride,
    640 		   hb_position_t *first_y,
    641 		   unsigned y_stride,
    642 		   void *user_data HB_UNUSED)
    643 {
    644  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    645  const hb_ot_face_t *ot_face = ot_font->ot_face;
    646 
    647  /* First, set all the x values to half the advance width. */
    648  font->get_glyph_h_advances (count,
    649 		      first_glyph, glyph_stride,
    650 		      first_x, x_stride);
    651  for (unsigned i = 0; i < count; i++)
    652  {
    653    *first_x /= 2;
    654    first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
    655  }
    656 
    657  /* The vertical origin business is messy...
    658   *
    659   * We allocate the cache, then have various code paths that use the cache.
    660   * Each one is responsible to free it before returning.
    661   */
    662  hb_ot_font_origin_cache_t *origin_cache = ot_font->v_origin.acquire_origin_cache ();
    663 
    664  /* If there is VORG, always use it. It uses VVAR for variations if necessary. */
    665  const OT::VORG &VORG = *ot_face->VORG;
    666  if (origin_cache && VORG.has_data ())
    667  {
    668 #ifndef HB_NO_VAR
    669    if (!font->has_nonzero_coords)
    670 #endif
    671    {
    672      for (unsigned i = 0; i < count; i++)
    673      {
    674 hb_position_t origin;
    675 unsigned cv;
    676 if (origin_cache->get (*first_glyph, &cv))
    677   origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
    678 else
    679 {
    680   origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph));
    681   origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
    682 }
    683 
    684 *first_y = origin;
    685 
    686 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    687 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
    688      }
    689    }
    690 #ifndef HB_NO_VAR
    691    else
    692    {
    693      const OT::VVAR &VVAR = *ot_face->vmtx->var_table;
    694      const auto &varStore = &VVAR + VVAR.varStore;
    695      auto *varStore_cache = ot_font->v_origin.acquire_varStore_cache (varStore);
    696      for (unsigned i = 0; i < count; i++)
    697      {
    698 hb_position_t origin;
    699 unsigned cv;
    700 if (origin_cache->get (*first_glyph, &cv))
    701   origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
    702 else
    703 {
    704   origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph) +
    705 			      VVAR.get_vorg_delta_unscaled (*first_glyph,
    706 							    font->coords, font->num_coords,
    707 							    varStore_cache));
    708   origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
    709 }
    710 
    711 *first_y = origin;
    712 
    713 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    714 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
    715      }
    716      ot_font->v_origin.release_varStore_cache (varStore_cache);
    717    }
    718 #endif
    719    ot_font->v_origin.release_origin_cache (origin_cache);
    720    return true;
    721  }
    722 
    723  /* If and only if `vmtx` is present and it's a `glyf` font,
    724   * we use the top phantom point, deduced from vmtx,glyf[,gvar]. */
    725  const auto &vmtx = *ot_face->vmtx;
    726  const auto &glyf = *ot_face->glyf;
    727  if (origin_cache && vmtx.has_data() && glyf.has_data ())
    728  {
    729    auto *scratch = glyf.acquire_scratch ();
    730    if (unlikely (!scratch))
    731    {
    732      ot_font->v_origin.release_origin_cache (origin_cache);
    733      return false;
    734    }
    735    OT::hb_scalar_cache_t *gvar_cache = font->has_nonzero_coords ?
    736 				ot_font->draw.acquire_gvar_cache (*ot_face->gvar) :
    737 				nullptr;
    738 
    739    for (unsigned i = 0; i < count; i++)
    740    {
    741      hb_position_t origin;
    742      unsigned cv;
    743      if (origin_cache->get (*first_glyph, &cv))
    744 origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
    745      else
    746      {
    747 origin = font->em_scalef_y (glyf.get_v_origin_with_var_unscaled (*first_glyph, font, *scratch, gvar_cache));
    748 origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
    749      }
    750 
    751      *first_y = origin;
    752 
    753      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    754      first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
    755    }
    756 
    757    if (gvar_cache)
    758      ot_font->draw.release_gvar_cache (gvar_cache);
    759    glyf.release_scratch (scratch);
    760    ot_font->v_origin.release_origin_cache (origin_cache);
    761    return true;
    762  }
    763 
    764  /* Otherwise, use glyph extents to center the glyph vertically.
    765   * If getting glyph extents failed, just use the font ascender. */
    766  if (origin_cache && font->has_glyph_extents_func ())
    767  {
    768    hb_font_extents_t font_extents;
    769    font->get_h_extents_with_fallback (&font_extents);
    770    hb_position_t font_advance = font_extents.ascender - font_extents.descender;
    771 
    772    for (unsigned i = 0; i < count; i++)
    773    {
    774      hb_position_t origin;
    775      unsigned cv;
    776 
    777      if (origin_cache->get (*first_glyph, &cv))
    778 origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
    779      else
    780      {
    781 hb_glyph_extents_t extents = {0};
    782 if (likely (font->get_glyph_extents (*first_glyph, &extents)))
    783   origin = extents.y_bearing + ((font_advance - -extents.height) >> 1);
    784 else
    785   origin = font_extents.ascender;
    786 
    787 origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
    788      }
    789 
    790      *first_y = origin;
    791 
    792      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
    793      first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
    794    }
    795  }
    796 
    797  ot_font->v_origin.release_origin_cache (origin_cache);
    798  return true;
    799 }
    800 #endif
    801 
    802 static hb_bool_t
    803 hb_ot_get_glyph_extents (hb_font_t *font,
    804 		 void *font_data,
    805 		 hb_codepoint_t glyph,
    806 		 hb_glyph_extents_t *extents,
    807 		 void *user_data HB_UNUSED)
    808 {
    809  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    810  const hb_ot_face_t *ot_face = ot_font->ot_face;
    811 
    812 #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
    813  if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
    814  if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
    815 #endif
    816 #if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
    817  if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
    818 #endif
    819 #ifndef HB_NO_VAR_COMPOSITES
    820  if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
    821 #endif
    822  if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
    823 #ifndef HB_NO_OT_FONT_CFF
    824  if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
    825  if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
    826 #endif
    827 
    828  return false;
    829 }
    830 
    831 #ifndef HB_NO_OT_FONT_GLYPH_NAMES
    832 static hb_bool_t
    833 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
    834 	      void *font_data,
    835 	      hb_codepoint_t glyph,
    836 	      char *name, unsigned int size,
    837 	      void *user_data HB_UNUSED)
    838 {
    839  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    840  const hb_ot_face_t *ot_face = ot_font->ot_face;
    841 
    842  if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
    843 #ifndef HB_NO_OT_FONT_CFF
    844  if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
    845 #endif
    846  return false;
    847 }
    848 static hb_bool_t
    849 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
    850 		   void *font_data,
    851 		   const char *name, int len,
    852 		   hb_codepoint_t *glyph,
    853 		   void *user_data HB_UNUSED)
    854 {
    855  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    856  const hb_ot_face_t *ot_face = ot_font->ot_face;
    857 
    858  if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
    859 #ifndef HB_NO_OT_FONT_CFF
    860    if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
    861 #endif
    862  return false;
    863 }
    864 #endif
    865 
    866 static hb_bool_t
    867 hb_ot_get_font_h_extents (hb_font_t *font,
    868 		  void *font_data HB_UNUSED,
    869 		  hb_font_extents_t *metrics,
    870 		  void *user_data HB_UNUSED)
    871 {
    872  return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
    873  _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
    874  _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
    875 }
    876 
    877 #ifndef HB_NO_VERTICAL
    878 static hb_bool_t
    879 hb_ot_get_font_v_extents (hb_font_t *font,
    880 		  void *font_data HB_UNUSED,
    881 		  hb_font_extents_t *metrics,
    882 		  void *user_data HB_UNUSED)
    883 {
    884  return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_ASCENDER, &metrics->ascender) &&
    885  _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) &&
    886  _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
    887 }
    888 #endif
    889 
    890 #ifndef HB_NO_DRAW
    891 static hb_bool_t
    892 hb_ot_draw_glyph_or_fail (hb_font_t *font,
    893 		  void *font_data HB_UNUSED,
    894 		  hb_codepoint_t glyph,
    895 		  hb_draw_funcs_t *draw_funcs, void *draw_data,
    896 		  void *user_data)
    897 {
    898  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
    899  hb_draw_session_t draw_session {draw_funcs, draw_data};
    900  bool ret = false;
    901 
    902  OT::hb_scalar_cache_t *gvar_cache = nullptr;
    903  if (font->num_coords)
    904  {
    905    ot_font->check_serial (font);
    906    gvar_cache = ot_font->draw.acquire_gvar_cache (*ot_font->ot_face->gvar);
    907  }
    908 
    909 #ifndef HB_NO_VAR_COMPOSITES
    910  if (font->face->table.VARC->get_path (font, glyph, draw_session)) { ret = true; goto done; }
    911 #endif
    912  // Keep the following in synch with VARC::get_path_at()
    913  if (font->face->table.glyf->get_path (font, glyph, draw_session, gvar_cache)) { ret = true; goto done; }
    914 
    915 #ifndef HB_NO_CFF
    916  if (font->face->table.cff2->get_path (font, glyph, draw_session)) { ret = true; goto done; }
    917  if (font->face->table.cff1->get_path (font, glyph, draw_session)) { ret = true; goto done; }
    918 #endif
    919 
    920 done:
    921 
    922  ot_font->draw.release_gvar_cache (gvar_cache);
    923 
    924  return ret;
    925 }
    926 #endif
    927 
    928 #ifndef HB_NO_PAINT
    929 static hb_bool_t
    930 hb_ot_paint_glyph_or_fail (hb_font_t *font,
    931 		   void *font_data,
    932 		   hb_codepoint_t glyph,
    933 		   hb_paint_funcs_t *paint_funcs, void *paint_data,
    934 		   unsigned int palette,
    935 		   hb_color_t foreground,
    936 		   void *user_data)
    937 {
    938 #ifndef HB_NO_COLOR
    939  if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true;
    940  if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
    941 #ifndef HB_NO_OT_FONT_BITMAP
    942  if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
    943  if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
    944 #endif
    945 #endif
    946  return false;
    947 }
    948 #endif
    949 
    950 static inline void free_static_ot_funcs ();
    951 
    952 static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
    953 {
    954  static hb_font_funcs_t *create ()
    955  {
    956    hb_font_funcs_t *funcs = hb_font_funcs_create ();
    957 
    958    hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
    959    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
    960    hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
    961 
    962    hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
    963    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
    964 
    965 #ifndef HB_NO_VERTICAL
    966    hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
    967    hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
    968    hb_font_funcs_set_glyph_v_origins_func (funcs, hb_ot_get_glyph_v_origins, nullptr, nullptr);
    969 #endif
    970 
    971 #ifndef HB_NO_DRAW
    972    hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ot_draw_glyph_or_fail, nullptr, nullptr);
    973 #endif
    974 
    975 #ifndef HB_NO_PAINT
    976    hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ot_paint_glyph_or_fail, nullptr, nullptr);
    977 #endif
    978 
    979    hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
    980    //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
    981 
    982 #ifndef HB_NO_OT_FONT_GLYPH_NAMES
    983    hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
    984    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
    985 #endif
    986 
    987    hb_font_funcs_make_immutable (funcs);
    988 
    989    hb_atexit (free_static_ot_funcs);
    990 
    991    return funcs;
    992  }
    993 } static_ot_funcs;
    994 
    995 static inline
    996 void free_static_ot_funcs ()
    997 {
    998  static_ot_funcs.free_instance ();
    999 }
   1000 
   1001 static hb_font_funcs_t *
   1002 _hb_ot_get_font_funcs ()
   1003 {
   1004  return static_ot_funcs.get_unconst ();
   1005 }
   1006 
   1007 
   1008 /**
   1009 * hb_ot_font_set_funcs:
   1010 * @font: #hb_font_t to work upon
   1011 *
   1012 * Sets the font functions to use when working with @font to
   1013 * the HarfBuzz's native implementation. This is the default
   1014 * for fonts newly created.
   1015 *
   1016 * Since: 0.9.28
   1017 **/
   1018 void
   1019 hb_ot_font_set_funcs (hb_font_t *font)
   1020 {
   1021  hb_ot_font_t *ot_font = _hb_ot_font_create (font);
   1022  if (unlikely (!ot_font))
   1023    return;
   1024 
   1025  hb_font_set_funcs (font,
   1026 	     _hb_ot_get_font_funcs (),
   1027 	     ot_font,
   1028 	     _hb_ot_font_destroy);
   1029 }
   1030 
   1031 #endif