tor-browser

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

hb-ot-cff1-table.hh (42938B)


      1 /*
      2 * Copyright © 2018 Adobe 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 * Adobe Author(s): Michiharu Ariza
     25 */
     26 
     27 #ifndef HB_OT_CFF1_TABLE_HH
     28 #define HB_OT_CFF1_TABLE_HH
     29 
     30 #include "hb-ot-cff-common.hh"
     31 #include "hb-subset-cff-common.hh"
     32 #include "hb-draw.hh"
     33 #include "hb-paint.hh"
     34 
     35 #define HB_STRING_ARRAY_NAME cff1_std_strings
     36 #define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh"
     37 #include "hb-string-array.hh"
     38 #undef HB_STRING_ARRAY_LIST
     39 #undef HB_STRING_ARRAY_NAME
     40 
     41 namespace CFF {
     42 
     43 /*
     44 * CFF -- Compact Font Format (CFF)
     45 * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
     46 */
     47 #define HB_OT_TAG_CFF1 HB_TAG('C','F','F',' ')
     48 
     49 #define CFF_UNDEF_SID   CFF_UNDEF_CODE
     50 
     51 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
     52 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
     53 
     54 typedef CFF1Index          CFF1CharStrings;
     55 typedef Subrs<HBUINT16>    CFF1Subrs;
     56 
     57 struct CFF1FDSelect : FDSelect {};
     58 
     59 /* Encoding */
     60 struct Encoding0 {
     61  bool sanitize (hb_sanitize_context_t *c) const
     62  {
     63    TRACE_SANITIZE (this);
     64    return_trace (codes.sanitize (c));
     65  }
     66 
     67  hb_codepoint_t get_code (hb_codepoint_t glyph) const
     68  {
     69    assert (glyph > 0);
     70    glyph--;
     71    if (glyph < nCodes ())
     72    {
     73      return (hb_codepoint_t)codes[glyph];
     74    }
     75    else
     76      return CFF_UNDEF_CODE;
     77  }
     78 
     79  HBUINT8 &nCodes () { return codes.len; }
     80  HBUINT8 nCodes () const { return codes.len; }
     81 
     82  ArrayOf<HBUINT8, HBUINT8> codes;
     83 
     84  DEFINE_SIZE_ARRAY_SIZED (1, codes);
     85 };
     86 
     87 struct Encoding1_Range {
     88  bool sanitize (hb_sanitize_context_t *c) const
     89  {
     90    TRACE_SANITIZE (this);
     91    return_trace (c->check_struct (this));
     92  }
     93 
     94  HBUINT8   first;
     95  HBUINT8   nLeft;
     96 
     97  DEFINE_SIZE_STATIC (2);
     98 };
     99 
    100 struct Encoding1 {
    101  bool sanitize (hb_sanitize_context_t *c) const
    102  {
    103    TRACE_SANITIZE (this);
    104    return_trace (ranges.sanitize (c));
    105  }
    106 
    107  hb_codepoint_t get_code (hb_codepoint_t glyph) const
    108  {
    109    /* TODO: Add cache like get_sid. */
    110    assert (glyph > 0);
    111    glyph--;
    112    for (unsigned int i = 0; i < nRanges (); i++)
    113    {
    114      if (glyph <= ranges[i].nLeft)
    115      {
    116 hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
    117 return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
    118      }
    119      glyph -= (ranges[i].nLeft + 1);
    120    }
    121    return CFF_UNDEF_CODE;
    122  }
    123 
    124  HBUINT8 &nRanges () { return ranges.len; }
    125  HBUINT8 nRanges () const { return ranges.len; }
    126 
    127  ArrayOf<Encoding1_Range, HBUINT8> ranges;
    128 
    129  DEFINE_SIZE_ARRAY_SIZED (1, ranges);
    130 };
    131 
    132 struct SuppEncoding {
    133  bool sanitize (hb_sanitize_context_t *c) const
    134  {
    135    TRACE_SANITIZE (this);
    136    return_trace (c->check_struct (this));
    137  }
    138 
    139  HBUINT8   code;
    140  HBUINT16  glyph;
    141 
    142  DEFINE_SIZE_STATIC (3);
    143 };
    144 
    145 struct CFF1SuppEncData {
    146  bool sanitize (hb_sanitize_context_t *c) const
    147  {
    148    TRACE_SANITIZE (this);
    149    return_trace (supps.sanitize (c));
    150  }
    151 
    152  void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
    153  {
    154    for (unsigned int i = 0; i < nSups (); i++)
    155      if (sid == supps[i].glyph)
    156 codes.push (supps[i].code);
    157  }
    158 
    159  HBUINT8 &nSups () { return supps.len; }
    160  HBUINT8 nSups () const { return supps.len; }
    161 
    162  ArrayOf<SuppEncoding, HBUINT8> supps;
    163 
    164  DEFINE_SIZE_ARRAY_SIZED (1, supps);
    165 };
    166 
    167 struct Encoding
    168 {
    169  /* serialize a fullset Encoding */
    170  bool serialize (hb_serialize_context_t *c, const Encoding &src)
    171  {
    172    TRACE_SERIALIZE (this);
    173    return_trace (c->embed (src));
    174  }
    175 
    176  /* serialize a subset Encoding */
    177  bool serialize (hb_serialize_context_t *c,
    178 	  uint8_t format,
    179 	  unsigned int enc_count,
    180 	  const hb_vector_t<code_pair_t>& code_ranges,
    181 	  const hb_vector_t<code_pair_t>& supp_codes)
    182  {
    183    TRACE_SERIALIZE (this);
    184    Encoding *dest = c->extend_min (this);
    185    if (unlikely (!dest)) return_trace (false);
    186    dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
    187    switch (format) {
    188    case 0:
    189    {
    190      Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
    191      if (unlikely (!fmt0)) return_trace (false);
    192      fmt0->nCodes () = enc_count;
    193      unsigned int glyph = 0;
    194      for (unsigned int i = 0; i < code_ranges.length; i++)
    195      {
    196 hb_codepoint_t code = code_ranges[i].code;
    197 for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
    198   fmt0->codes[glyph++] = code++;
    199 if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
    200   return_trace (false);
    201      }
    202    }
    203    break;
    204 
    205    case 1:
    206    {
    207      Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
    208      if (unlikely (!fmt1)) return_trace (false);
    209      fmt1->nRanges () = code_ranges.length;
    210      for (unsigned int i = 0; i < code_ranges.length; i++)
    211      {
    212 if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
    213   return_trace (false);
    214 fmt1->ranges[i].first = code_ranges[i].code;
    215 fmt1->ranges[i].nLeft = code_ranges[i].glyph;
    216      }
    217    }
    218    break;
    219 
    220    }
    221 
    222    if (supp_codes.length)
    223    {
    224      CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
    225      if (unlikely (!suppData)) return_trace (false);
    226      suppData->nSups () = supp_codes.length;
    227      for (unsigned int i = 0; i < supp_codes.length; i++)
    228      {
    229 suppData->supps[i].code = supp_codes[i].code;
    230 suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
    231      }
    232    }
    233 
    234    return_trace (true);
    235  }
    236 
    237  unsigned int get_size () const
    238  {
    239    unsigned int size = min_size;
    240    switch (table_format ())
    241    {
    242    case 0: hb_barrier (); size += u.format0.get_size (); break;
    243    case 1: hb_barrier (); size += u.format1.get_size (); break;
    244    }
    245    if (has_supplement ())
    246      size += suppEncData ().get_size ();
    247    return size;
    248  }
    249 
    250  hb_codepoint_t get_code (hb_codepoint_t glyph) const
    251  {
    252    switch (table_format ())
    253    {
    254    case 0: hb_barrier (); return u.format0.get_code (glyph);
    255    case 1: hb_barrier (); return u.format1.get_code (glyph);
    256    default:return 0;
    257    }
    258  }
    259 
    260  uint8_t table_format () const { return format & 0x7F; }
    261  bool  has_supplement () const { return format & 0x80; }
    262 
    263  void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
    264  {
    265    codes.resize (0);
    266    if (has_supplement ())
    267      suppEncData().get_codes (sid, codes);
    268  }
    269 
    270  bool sanitize (hb_sanitize_context_t *c) const
    271  {
    272    TRACE_SANITIZE (this);
    273    if (unlikely (!c->check_struct (this)))
    274      return_trace (false);
    275    hb_barrier ();
    276 
    277    switch (table_format ())
    278    {
    279    case 0: hb_barrier (); if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
    280    case 1: hb_barrier (); if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
    281    default:return_trace (false);
    282    }
    283    return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
    284  }
    285 
    286  protected:
    287  const CFF1SuppEncData &suppEncData () const
    288  {
    289    switch (table_format ())
    290    {
    291    case 0: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
    292    case 1: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
    293    default:return Null (CFF1SuppEncData);
    294    }
    295  }
    296 
    297  public:
    298  HBUINT8	format;
    299  union {
    300  Encoding0	format0;
    301  Encoding1	format1;
    302  } u;
    303  /* CFF1SuppEncData  suppEncData; */
    304 
    305  DEFINE_SIZE_MIN (1);
    306 };
    307 
    308 /* Charset */
    309 struct Charset0
    310 {
    311  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
    312  {
    313    TRACE_SANITIZE (this);
    314    if (num_charset_entries) *num_charset_entries = num_glyphs;
    315    return_trace (sids.sanitize (c, num_glyphs - 1));
    316  }
    317 
    318  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
    319  {
    320    if (unlikely (glyph >= num_glyphs)) return 0;
    321    if (unlikely (glyph == 0))
    322      return 0;
    323    else
    324      return sids[glyph - 1];
    325  }
    326 
    327  void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
    328  {
    329    mapping->resize_dirty  (num_glyphs);
    330    for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
    331      mapping->arrayZ[gid] = {sids[gid - 1], gid};
    332  }
    333 
    334  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
    335  {
    336    if (sid == 0)
    337      return 0;
    338 
    339    for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
    340    {
    341      if (sids[glyph-1] == sid)
    342 return glyph;
    343    }
    344    return 0;
    345  }
    346 
    347  static unsigned int get_size (unsigned int num_glyphs)
    348  {
    349    assert (num_glyphs > 0);
    350    return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1);
    351  }
    352 
    353  UnsizedArrayOf<HBUINT16> sids;
    354 
    355  DEFINE_SIZE_ARRAY(0, sids);
    356 };
    357 
    358 template <typename TYPE>
    359 struct Charset_Range {
    360  bool sanitize (hb_sanitize_context_t *c) const
    361  {
    362    TRACE_SANITIZE (this);
    363    return_trace (c->check_struct (this));
    364  }
    365 
    366  HBUINT16  first;
    367  TYPE      nLeft;
    368 
    369  DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
    370 };
    371 
    372 template <typename TYPE>
    373 struct Charset1_2 {
    374  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
    375  {
    376    TRACE_SANITIZE (this);
    377    num_glyphs--;
    378    unsigned i;
    379    for (i = 0; num_glyphs > 0; i++)
    380    {
    381      if (unlikely (!(ranges[i].sanitize (c) &&
    382 	      hb_barrier () &&
    383 	      (num_glyphs >= ranges[i].nLeft + 1))))
    384 return_trace (false);
    385      num_glyphs -= (ranges[i].nLeft + 1);
    386    }
    387    if (num_charset_entries)
    388      *num_charset_entries = i;
    389    return_trace (true);
    390  }
    391 
    392  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs,
    393 		  code_pair_t *cache = nullptr) const
    394  {
    395    if (unlikely (glyph >= num_glyphs)) return 0;
    396    unsigned i;
    397    hb_codepoint_t start_glyph;
    398    if (cache && likely (cache->glyph <= glyph))
    399    {
    400      i = cache->code;
    401      start_glyph = cache->glyph;
    402    }
    403    else
    404    {
    405      if (unlikely (glyph == 0)) return 0;
    406      i = 0;
    407      start_glyph = 1;
    408    }
    409    glyph -= start_glyph;
    410    for (;; i++)
    411    {
    412      unsigned count = ranges[i].nLeft;
    413      if (glyph <= count)
    414      {
    415        if (cache)
    416   *cache = {i, start_glyph};
    417 return ranges[i].first + glyph;
    418      }
    419      count++;
    420      start_glyph += count;
    421      glyph -= count;
    422    }
    423 
    424    return 0;
    425  }
    426 
    427  void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
    428  {
    429    mapping->resize_dirty  (num_glyphs);
    430    hb_codepoint_t gid = 1;
    431    if (gid >= num_glyphs)
    432      return;
    433    for (unsigned i = 0;; i++)
    434    {
    435      hb_codepoint_t sid = ranges[i].first;
    436      unsigned count = ranges[i].nLeft + 1;
    437      unsigned last = gid + count;
    438      for (unsigned j = 0; j < count; j++)
    439 mapping->arrayZ[gid++] = {sid++, last - 1};
    440 
    441      if (gid >= num_glyphs)
    442        break;
    443    }
    444  }
    445 
    446  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
    447  {
    448    if (sid == 0) return 0;
    449    hb_codepoint_t  glyph = 1;
    450    for (unsigned int i = 0;; i++)
    451    {
    452      if (glyph >= num_glyphs)
    453 return 0;
    454      if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
    455 return glyph + (sid - ranges[i].first);
    456      glyph += (ranges[i].nLeft + 1);
    457    }
    458 
    459    return 0;
    460  }
    461 
    462  unsigned int get_size (unsigned int num_glyphs) const
    463  {
    464    int glyph = (int) num_glyphs;
    465    unsigned num_ranges = 0;
    466 
    467    assert (glyph > 0);
    468    glyph--;
    469    for (unsigned int i = 0; glyph > 0; i++)
    470    {
    471      glyph -= (ranges[i].nLeft + 1);
    472      num_ranges++;
    473    }
    474 
    475    return get_size_for_ranges (num_ranges);
    476  }
    477 
    478  static unsigned int get_size_for_ranges (unsigned int num_ranges)
    479  {
    480    return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges);
    481  }
    482 
    483  UnsizedArrayOf<Charset_Range<TYPE>> ranges;
    484 
    485  DEFINE_SIZE_ARRAY (0, ranges);
    486 };
    487 
    488 typedef Charset1_2<HBUINT8>     Charset1;
    489 typedef Charset1_2<HBUINT16>    Charset2;
    490 typedef Charset_Range<HBUINT8>  Charset1_Range;
    491 typedef Charset_Range<HBUINT16> Charset2_Range;
    492 
    493 struct Charset
    494 {
    495  /* serialize a fullset Charset */
    496  bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
    497  {
    498    TRACE_SERIALIZE (this);
    499    return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs)));
    500  }
    501 
    502  /* serialize a subset Charset */
    503  bool serialize (hb_serialize_context_t *c,
    504 	  uint8_t format,
    505 	  unsigned int num_glyphs,
    506 	  const hb_vector_t<code_pair_t>& sid_ranges)
    507  {
    508    TRACE_SERIALIZE (this);
    509    Charset *dest = c->extend_min (this);
    510    if (unlikely (!dest)) return_trace (false);
    511    dest->format = format;
    512    switch (format)
    513    {
    514    case 0:
    515    {
    516      Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false);
    517      if (unlikely (!fmt0)) return_trace (false);
    518      unsigned int glyph = 0;
    519      for (unsigned int i = 0; i < sid_ranges.length; i++)
    520      {
    521 hb_codepoint_t sid = sid_ranges.arrayZ[i].code;
    522 for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--)
    523   fmt0->sids[glyph++] = sid++;
    524      }
    525    }
    526    break;
    527 
    528    case 1:
    529    {
    530      Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false);
    531      if (unlikely (!fmt1)) return_trace (false);
    532      hb_codepoint_t all_glyphs = 0;
    533      for (unsigned int i = 0; i < sid_ranges.length; i++)
    534      {
    535        auto &_ = sid_ranges.arrayZ[i];
    536        all_glyphs |= _.glyph;
    537 fmt1->ranges[i].first = _.code;
    538 fmt1->ranges[i].nLeft = _.glyph;
    539      }
    540      if (unlikely (!(all_glyphs <= 0xFF)))
    541 return_trace (false);
    542    }
    543    break;
    544 
    545    case 2:
    546    {
    547      Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false);
    548      if (unlikely (!fmt2)) return_trace (false);
    549      hb_codepoint_t all_glyphs = 0;
    550      for (unsigned int i = 0; i < sid_ranges.length; i++)
    551      {
    552        auto &_ = sid_ranges.arrayZ[i];
    553        all_glyphs |= _.glyph;
    554 fmt2->ranges[i].first = _.code;
    555 fmt2->ranges[i].nLeft = _.glyph;
    556      }
    557      if (unlikely (!(all_glyphs <= 0xFFFF)))
    558 return_trace (false);
    559    }
    560    break;
    561 
    562    }
    563    return_trace (true);
    564  }
    565 
    566  unsigned int get_size (unsigned int num_glyphs) const
    567  {
    568    switch (format)
    569    {
    570    case 0: hb_barrier (); return min_size + u.format0.get_size (num_glyphs);
    571    case 1: hb_barrier (); return min_size + u.format1.get_size (num_glyphs);
    572    case 2: hb_barrier (); return min_size + u.format2.get_size (num_glyphs);
    573    default:return 0;
    574    }
    575  }
    576 
    577  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs,
    578 		  code_pair_t *cache = nullptr) const
    579  {
    580    switch (format)
    581    {
    582    case 0: hb_barrier (); return u.format0.get_sid (glyph, num_glyphs);
    583    case 1: hb_barrier (); return u.format1.get_sid (glyph, num_glyphs, cache);
    584    case 2: hb_barrier (); return u.format2.get_sid (glyph, num_glyphs, cache);
    585    default:return 0;
    586    }
    587  }
    588 
    589  void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
    590  {
    591    switch (format)
    592    {
    593    case 0: hb_barrier (); u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
    594    case 1: hb_barrier (); u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
    595    case 2: hb_barrier (); u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
    596    default:return;
    597    }
    598  }
    599 
    600  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
    601  {
    602    switch (format)
    603    {
    604    case 0: hb_barrier (); return u.format0.get_glyph (sid, num_glyphs);
    605    case 1: hb_barrier (); return u.format1.get_glyph (sid, num_glyphs);
    606    case 2: hb_barrier (); return u.format2.get_glyph (sid, num_glyphs);
    607    default:return 0;
    608    }
    609  }
    610 
    611  bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const
    612  {
    613    TRACE_SANITIZE (this);
    614    if (unlikely (!c->check_struct (this)))
    615      return_trace (false);
    616    hb_barrier ();
    617 
    618    switch (format)
    619    {
    620    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
    621    case 1: hb_barrier (); return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
    622    case 2: hb_barrier (); return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
    623    default:return_trace (false);
    624    }
    625  }
    626 
    627  HBUINT8       format;
    628  union {
    629    Charset0    format0;
    630    Charset1    format1;
    631    Charset2    format2;
    632  } u;
    633 
    634  DEFINE_SIZE_MIN (1);
    635 };
    636 
    637 struct CFF1StringIndex : CFF1Index
    638 {
    639  bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
    640 	  const hb_vector_t<unsigned> &sidmap)
    641  {
    642    TRACE_SERIALIZE (this);
    643    if (unlikely ((strings.count == 0) || (sidmap.length == 0)))
    644    {
    645      if (unlikely (!c->extend_min (this->count)))
    646 return_trace (false);
    647      count = 0;
    648      return_trace (true);
    649    }
    650 
    651    if (unlikely (sidmap.in_error ())) return_trace (false);
    652 
    653    // Save this in a vector since serialize() iterates it twice.
    654    hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap)
    655 				 | hb_map (strings));
    656 
    657    if (unlikely (bytesArray.in_error ())) return_trace (false);
    658 
    659    bool result = CFF1Index::serialize (c, bytesArray);
    660    return_trace (result);
    661  }
    662 };
    663 
    664 struct cff1_top_dict_interp_env_t : num_interp_env_t
    665 {
    666  cff1_top_dict_interp_env_t ()
    667    : num_interp_env_t(), prev_offset(0), last_offset(0) {}
    668  cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes)
    669    : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {}
    670 
    671  unsigned int prev_offset;
    672  unsigned int last_offset;
    673 };
    674 
    675 struct name_dict_values_t
    676 {
    677  enum name_dict_val_index_t
    678  {
    679      version,
    680      notice,
    681      copyright,
    682      fullName,
    683      familyName,
    684      weight,
    685      postscript,
    686      fontName,
    687      baseFontName,
    688      registry,
    689      ordering,
    690 
    691      ValCount
    692  };
    693 
    694  void init ()
    695  {
    696    for (unsigned int i = 0; i < ValCount; i++)
    697      values[i] = CFF_UNDEF_SID;
    698  }
    699 
    700  unsigned int& operator[] (unsigned int i)
    701  { assert (i < ValCount); return values[i]; }
    702 
    703  unsigned int operator[] (unsigned int i) const
    704  { assert (i < ValCount); return values[i]; }
    705 
    706  static enum name_dict_val_index_t name_op_to_index (op_code_t op)
    707  {
    708    switch (op) {
    709      default: // can't happen - just make some compiler happy
    710      case OpCode_version:
    711 return version;
    712      case OpCode_Notice:
    713 return notice;
    714      case OpCode_Copyright:
    715 return copyright;
    716      case OpCode_FullName:
    717 return fullName;
    718      case OpCode_FamilyName:
    719 return familyName;
    720      case OpCode_Weight:
    721 return weight;
    722      case OpCode_PostScript:
    723 return postscript;
    724      case OpCode_FontName:
    725 return fontName;
    726      case OpCode_BaseFontName:
    727 return baseFontName;
    728    }
    729  }
    730 
    731  unsigned int  values[ValCount];
    732 };
    733 
    734 struct cff1_top_dict_val_t : op_str_t
    735 {
    736  unsigned int  last_arg_offset;
    737 };
    738 
    739 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
    740 {
    741  void init ()
    742  {
    743    top_dict_values_t<cff1_top_dict_val_t>::init ();
    744 
    745    nameSIDs.init ();
    746    ros_supplement = 0;
    747    cidCount = 8720;
    748    EncodingOffset = 0;
    749    CharsetOffset = 0;
    750    FDSelectOffset = 0;
    751    privateDictInfo.init ();
    752  }
    753  void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
    754 
    755  bool is_CID () const
    756  { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
    757 
    758  name_dict_values_t  nameSIDs;
    759  unsigned int    ros_supplement_offset;
    760  unsigned int    ros_supplement;
    761  unsigned int    cidCount;
    762 
    763  int             EncodingOffset;
    764  int             CharsetOffset;
    765  int             FDSelectOffset;
    766  table_info_t    privateDictInfo;
    767 };
    768 
    769 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
    770 {
    771  static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
    772  {
    773    cff1_top_dict_val_t  val;
    774    val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
    775 
    776    switch (op) {
    777      case OpCode_version:
    778      case OpCode_Notice:
    779      case OpCode_Copyright:
    780      case OpCode_FullName:
    781      case OpCode_FontName:
    782      case OpCode_FamilyName:
    783      case OpCode_Weight:
    784      case OpCode_PostScript:
    785      case OpCode_BaseFontName:
    786 dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
    787 env.clear_args ();
    788 break;
    789      case OpCode_isFixedPitch:
    790      case OpCode_ItalicAngle:
    791      case OpCode_UnderlinePosition:
    792      case OpCode_UnderlineThickness:
    793      case OpCode_PaintType:
    794      case OpCode_CharstringType:
    795      case OpCode_UniqueID:
    796      case OpCode_StrokeWidth:
    797      case OpCode_SyntheticBase:
    798      case OpCode_CIDFontVersion:
    799      case OpCode_CIDFontRevision:
    800      case OpCode_CIDFontType:
    801      case OpCode_UIDBase:
    802      case OpCode_FontBBox:
    803      case OpCode_XUID:
    804      case OpCode_BaseFontBlend:
    805 env.clear_args ();
    806 break;
    807 
    808      case OpCode_CIDCount:
    809 dictval.cidCount = env.argStack.pop_uint ();
    810 env.clear_args ();
    811 break;
    812 
    813      case OpCode_ROS:
    814 dictval.ros_supplement = env.argStack.pop_uint ();
    815 dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
    816 dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
    817 env.clear_args ();
    818 break;
    819 
    820      case OpCode_Encoding:
    821 dictval.EncodingOffset = env.argStack.pop_int ();
    822 env.clear_args ();
    823 if (unlikely (dictval.EncodingOffset == 0)) return;
    824 break;
    825 
    826      case OpCode_charset:
    827 dictval.CharsetOffset = env.argStack.pop_int ();
    828 env.clear_args ();
    829 if (unlikely (dictval.CharsetOffset == 0)) return;
    830 break;
    831 
    832      case OpCode_FDSelect:
    833 dictval.FDSelectOffset = env.argStack.pop_int ();
    834 env.clear_args ();
    835 break;
    836 
    837      case OpCode_Private:
    838 dictval.privateDictInfo.offset = env.argStack.pop_int ();
    839 dictval.privateDictInfo.size = env.argStack.pop_uint ();
    840 env.clear_args ();
    841 break;
    842 
    843      default:
    844 env.last_offset = env.str_ref.get_offset ();
    845 top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
    846 /* Record this operand below if stack is empty, otherwise done */
    847 if (!env.argStack.is_empty ()) return;
    848 break;
    849    }
    850 
    851    if (unlikely (env.in_error ())) return;
    852 
    853    dictval.add_op (op, env.str_ref, val);
    854  }
    855 };
    856 
    857 struct cff1_font_dict_values_t : dict_values_t<op_str_t>
    858 {
    859  void init ()
    860  {
    861    dict_values_t<op_str_t>::init ();
    862    privateDictInfo.init ();
    863    fontName = CFF_UNDEF_SID;
    864  }
    865  void fini () { dict_values_t<op_str_t>::fini (); }
    866 
    867  table_info_t       privateDictInfo;
    868  unsigned int    fontName;
    869 };
    870 
    871 struct cff1_font_dict_opset_t : dict_opset_t
    872 {
    873  static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
    874  {
    875    switch (op) {
    876      case OpCode_FontName:
    877 dictval.fontName = env.argStack.pop_uint ();
    878 env.clear_args ();
    879 break;
    880      case OpCode_FontMatrix:
    881      case OpCode_PaintType:
    882 env.clear_args ();
    883 break;
    884      case OpCode_Private:
    885 dictval.privateDictInfo.offset = env.argStack.pop_uint ();
    886 dictval.privateDictInfo.size = env.argStack.pop_uint ();
    887 env.clear_args ();
    888 break;
    889 
    890      default:
    891 dict_opset_t::process_op (op, env);
    892 if (!env.argStack.is_empty ()) return;
    893 break;
    894    }
    895 
    896    if (unlikely (env.in_error ())) return;
    897 
    898    dictval.add_op (op, env.str_ref);
    899  }
    900 };
    901 
    902 template <typename VAL>
    903 struct cff1_private_dict_values_base_t : dict_values_t<VAL>
    904 {
    905  void init ()
    906  {
    907    dict_values_t<VAL>::init ();
    908    subrsOffset = 0;
    909    localSubrs = &Null (CFF1Subrs);
    910  }
    911  void fini () { dict_values_t<VAL>::fini (); }
    912 
    913  int                 subrsOffset;
    914  const CFF1Subrs    *localSubrs;
    915 };
    916 
    917 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
    918 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
    919 
    920 struct cff1_private_dict_opset_t : dict_opset_t
    921 {
    922  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
    923  {
    924    num_dict_val_t val;
    925    val.init ();
    926 
    927    switch (op) {
    928      case OpCode_BlueValues:
    929      case OpCode_OtherBlues:
    930      case OpCode_FamilyBlues:
    931      case OpCode_FamilyOtherBlues:
    932      case OpCode_StemSnapH:
    933      case OpCode_StemSnapV:
    934      case OpCode_StdHW:
    935      case OpCode_StdVW:
    936      case OpCode_BlueScale:
    937      case OpCode_BlueShift:
    938      case OpCode_BlueFuzz:
    939      case OpCode_ForceBold:
    940      case OpCode_LanguageGroup:
    941      case OpCode_ExpansionFactor:
    942      case OpCode_initialRandomSeed:
    943      case OpCode_defaultWidthX:
    944      case OpCode_nominalWidthX:
    945 env.clear_args ();
    946 break;
    947      case OpCode_Subrs:
    948 dictval.subrsOffset = env.argStack.pop_int ();
    949 env.clear_args ();
    950 break;
    951 
    952      default:
    953 dict_opset_t::process_op (op, env);
    954 if (!env.argStack.is_empty ()) return;
    955 break;
    956    }
    957 
    958    if (unlikely (env.in_error ())) return;
    959 
    960    dictval.add_op (op, env.str_ref, val);
    961  }
    962 };
    963 
    964 struct cff1_private_dict_opset_subset_t : dict_opset_t
    965 {
    966  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
    967  {
    968    switch (op) {
    969      case OpCode_BlueValues:
    970      case OpCode_OtherBlues:
    971      case OpCode_FamilyBlues:
    972      case OpCode_FamilyOtherBlues:
    973      case OpCode_StemSnapH:
    974      case OpCode_StemSnapV:
    975      case OpCode_StdHW:
    976      case OpCode_StdVW:
    977      case OpCode_BlueScale:
    978      case OpCode_BlueShift:
    979      case OpCode_BlueFuzz:
    980      case OpCode_ForceBold:
    981      case OpCode_LanguageGroup:
    982      case OpCode_ExpansionFactor:
    983      case OpCode_initialRandomSeed:
    984      case OpCode_defaultWidthX:
    985      case OpCode_nominalWidthX:
    986 env.clear_args ();
    987 break;
    988 
    989      case OpCode_Subrs:
    990 dictval.subrsOffset = env.argStack.pop_int ();
    991 env.clear_args ();
    992 break;
    993 
    994      default:
    995 dict_opset_t::process_op (op, env);
    996 if (!env.argStack.is_empty ()) return;
    997 break;
    998    }
    999 
   1000    if (unlikely (env.in_error ())) return;
   1001 
   1002    dictval.add_op (op, env.str_ref);
   1003  }
   1004 };
   1005 
   1006 typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> cff1_top_dict_interpreter_t;
   1007 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
   1008 
   1009 typedef CFF1Index CFF1NameIndex;
   1010 typedef CFF1Index CFF1TopDictIndex;
   1011 
   1012 struct cff1_font_dict_values_mod_t
   1013 {
   1014  cff1_font_dict_values_mod_t() { init (); }
   1015 
   1016  void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
   1017 
   1018  void init (const cff1_font_dict_values_t *base_,
   1019      unsigned int fontName_)
   1020  {
   1021    base = base_;
   1022    fontName = fontName_;
   1023    privateDictInfo.init ();
   1024  }
   1025 
   1026  unsigned get_count () const { return base->get_count (); }
   1027 
   1028  const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
   1029 
   1030  const cff1_font_dict_values_t    *base;
   1031  table_info_t		   privateDictInfo;
   1032  unsigned int		fontName;
   1033 };
   1034 
   1035 struct CFF1FDArray : FDArray<HBUINT16>
   1036 {
   1037  /* FDArray::serialize() requires this partial specialization to compile */
   1038  template <typename ITER, typename OP_SERIALIZER>
   1039  bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
   1040  { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
   1041 };
   1042 
   1043 } /* namespace CFF */
   1044 
   1045 namespace OT {
   1046 
   1047 using namespace CFF;
   1048 
   1049 struct cff1
   1050 {
   1051  static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1;
   1052 
   1053  bool sanitize (hb_sanitize_context_t *c) const
   1054  {
   1055    TRACE_SANITIZE (this);
   1056    return_trace (c->check_struct (this) &&
   1057 	  hb_barrier () &&
   1058 	  likely (version.major == 1));
   1059  }
   1060 
   1061  template <typename PRIVOPSET, typename PRIVDICTVAL>
   1062  struct accelerator_templ_t
   1063  {
   1064    static constexpr hb_tag_t tableTag = cff1::tableTag;
   1065 
   1066    accelerator_templ_t (hb_face_t *face)
   1067    {
   1068      if (!face) return;
   1069 
   1070      topDict.init ();
   1071      fontDicts.init ();
   1072      privateDicts.init ();
   1073 
   1074      this->blob = sc.reference_table<cff1> (face);
   1075 
   1076      /* setup for run-time sanitization */
   1077      sc.init (this->blob);
   1078      sc.start_processing ();
   1079 
   1080      const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
   1081 
   1082      if (cff == &Null (OT::cff1))
   1083        goto fail;
   1084 
   1085      nameIndex = &cff->nameIndex (cff);
   1086      if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
   1087        goto fail;
   1088      hb_barrier ();
   1089 
   1090      topDictIndex = &StructAtOffsetOrNull<CFF1TopDictIndex> (nameIndex, nameIndex->get_size (), sc);
   1091      if (topDictIndex == &Null (CFF1TopDictIndex) || (topDictIndex->count == 0))
   1092        goto fail;
   1093      hb_barrier ();
   1094 
   1095      { /* parse top dict */
   1096 const hb_ubytes_t topDictStr = (*topDictIndex)[0];
   1097 if (unlikely (!topDictStr.sanitize (&sc)))   goto fail;
   1098 hb_barrier ();
   1099 cff1_top_dict_interp_env_t env (topDictStr);
   1100 cff1_top_dict_interpreter_t top_interp (env);
   1101 if (unlikely (!top_interp.interpret (topDict)))   goto fail;
   1102      }
   1103 
   1104      if (is_predef_charset ())
   1105 charset = &Null (Charset);
   1106      else
   1107      {
   1108 charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset, sc, &num_charset_entries);
   1109 if (unlikely (charset == &Null (Charset)))   goto fail;
   1110      }
   1111 
   1112      fdCount = 1;
   1113      if (is_CID ())
   1114      {
   1115 fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset, sc);
   1116 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset, sc, fdArray->count);
   1117 if (unlikely (fdArray == &Null (CFF1FDArray) ||
   1118 	      fdSelect == &Null (CFF1FDSelect)))
   1119   goto fail;
   1120 
   1121 fdCount = fdArray->count;
   1122      }
   1123      else
   1124      {
   1125 fdArray = &Null (CFF1FDArray);
   1126 fdSelect = &Null (CFF1FDSelect);
   1127      }
   1128 
   1129      encoding = &Null (Encoding);
   1130      if (is_CID ())
   1131      {
   1132 if (unlikely (charset == &Null (Charset)))   goto fail;
   1133      }
   1134      else
   1135      {
   1136 if (!is_predef_encoding ())
   1137 {
   1138   encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset, sc);
   1139   if (unlikely (encoding == &Null (Encoding)))   goto fail;
   1140 }
   1141      }
   1142 
   1143      stringIndex = &StructAtOffsetOrNull<CFF1StringIndex> (topDictIndex, topDictIndex->get_size (), sc);
   1144      if (stringIndex == &Null (CFF1StringIndex))
   1145        goto fail;
   1146 
   1147      globalSubrs = &StructAtOffsetOrNull<CFF1Subrs> (stringIndex, stringIndex->get_size (), sc);
   1148      charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset, sc);
   1149      if (charStrings == &Null (CFF1CharStrings))
   1150        goto fail;
   1151 
   1152      num_glyphs = charStrings->count;
   1153      if (num_glyphs != sc.get_num_glyphs ())
   1154        goto fail;
   1155 
   1156      if (unlikely (!privateDicts.resize (fdCount)))
   1157        goto fail;
   1158      for (unsigned int i = 0; i < fdCount; i++)
   1159 privateDicts[i].init ();
   1160 
   1161      // parse CID font dicts and gather private dicts
   1162      if (is_CID ())
   1163      {
   1164 for (unsigned int i = 0; i < fdCount; i++)
   1165 {
   1166   hb_ubytes_t fontDictStr = (*fdArray)[i];
   1167   if (unlikely (!fontDictStr.sanitize (&sc)))   goto fail;
   1168   hb_barrier ();
   1169   cff1_font_dict_values_t *font;
   1170   cff1_top_dict_interp_env_t env (fontDictStr);
   1171   cff1_font_dict_interpreter_t font_interp (env);
   1172   font = fontDicts.push ();
   1173   if (unlikely (fontDicts.in_error ()))   goto fail;
   1174 
   1175   font->init ();
   1176   if (unlikely (!font_interp.interpret (*font)))   goto fail;
   1177   PRIVDICTVAL *priv = &privateDicts[i];
   1178   const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
   1179   if (unlikely (font->privateDictInfo.size &&
   1180 		privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
   1181   num_interp_env_t env2 (privDictStr);
   1182   dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
   1183   priv->init ();
   1184   if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
   1185 
   1186   priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc);
   1187 }
   1188      }
   1189      else  /* non-CID */
   1190      {
   1191 cff1_top_dict_values_t *font = &topDict;
   1192 PRIVDICTVAL *priv = &privateDicts[0];
   1193 
   1194 const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
   1195 if (font->privateDictInfo.size &&
   1196     unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
   1197 num_interp_env_t env (privDictStr);
   1198 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
   1199 priv->init ();
   1200 if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
   1201 
   1202 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc);
   1203 hb_barrier ();
   1204      }
   1205 
   1206      return;
   1207 
   1208      fail:
   1209        _fini ();
   1210    }
   1211    ~accelerator_templ_t () { _fini (); }
   1212    void _fini ()
   1213    {
   1214      sc.end_processing ();
   1215      topDict.fini ();
   1216      fontDicts.fini ();
   1217      privateDicts.fini ();
   1218      hb_blob_destroy (blob);
   1219      blob = nullptr;
   1220    }
   1221 
   1222    hb_blob_t *get_blob () const { return blob; }
   1223 
   1224    bool is_valid () const { return blob; }
   1225    bool   is_CID () const { return topDict.is_CID (); }
   1226 
   1227    bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
   1228 
   1229    unsigned int std_code_to_glyph (hb_codepoint_t code) const
   1230    {
   1231      hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
   1232      if (unlikely (sid == CFF_UNDEF_SID))
   1233 return 0;
   1234 
   1235      if (charset != &Null (Charset))
   1236 return charset->get_glyph (sid, num_glyphs);
   1237      else if ((topDict.CharsetOffset == ISOAdobeCharset)
   1238       && (code <= 228 /*zcaron*/)) return sid;
   1239      return 0;
   1240    }
   1241 
   1242    bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
   1243 
   1244    hb_codepoint_t glyph_to_code (hb_codepoint_t glyph,
   1245 			  code_pair_t *glyph_to_sid_cache = nullptr) const
   1246    {
   1247      if (encoding != &Null (Encoding))
   1248 return encoding->get_code (glyph);
   1249      else
   1250      {
   1251 hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache);
   1252 if (sid == 0) return 0;
   1253 hb_codepoint_t code = 0;
   1254 switch (topDict.EncodingOffset)
   1255 {
   1256 case StandardEncoding:
   1257   code = lookup_standard_encoding_for_code (sid);
   1258   break;
   1259 case ExpertEncoding:
   1260   code = lookup_expert_encoding_for_code (sid);
   1261   break;
   1262 default:
   1263   break;
   1264 }
   1265 return code;
   1266      }
   1267    }
   1268 
   1269    glyph_to_sid_map_t *create_glyph_to_sid_map () const
   1270    {
   1271      if (charset != &Null (Charset))
   1272      {
   1273 auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t));
   1274 if (unlikely (!mapping)) return nullptr;
   1275 mapping = new (mapping) glyph_to_sid_map_t ();
   1276 mapping->push (code_pair_t {0, 1});
   1277 charset->collect_glyph_to_sid_map (mapping, num_glyphs);
   1278 return mapping;
   1279      }
   1280      else
   1281 return nullptr;
   1282    }
   1283 
   1284    hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph,
   1285 			 code_pair_t *cache = nullptr) const
   1286    {
   1287      if (charset != &Null (Charset))
   1288 return charset->get_sid (glyph, num_glyphs, cache);
   1289      else
   1290      {
   1291 hb_codepoint_t sid = 0;
   1292 switch (topDict.CharsetOffset)
   1293 {
   1294   case ISOAdobeCharset:
   1295     if (glyph <= 228 /*zcaron*/) sid = glyph;
   1296     break;
   1297   case ExpertCharset:
   1298     sid = lookup_expert_charset_for_sid (glyph);
   1299     break;
   1300   case ExpertSubsetCharset:
   1301       sid = lookup_expert_subset_charset_for_sid (glyph);
   1302     break;
   1303   default:
   1304     break;
   1305 }
   1306 return sid;
   1307      }
   1308    }
   1309 
   1310    hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
   1311    {
   1312      if (charset != &Null (Charset))
   1313 return charset->get_glyph (sid, num_glyphs);
   1314      else
   1315      {
   1316 hb_codepoint_t glyph = 0;
   1317 switch (topDict.CharsetOffset)
   1318 {
   1319   case ISOAdobeCharset:
   1320     if (sid <= 228 /*zcaron*/) glyph = sid;
   1321     break;
   1322   case ExpertCharset:
   1323     glyph = lookup_expert_charset_for_glyph (sid);
   1324     break;
   1325   case ExpertSubsetCharset:
   1326     glyph = lookup_expert_subset_charset_for_glyph (sid);
   1327     break;
   1328   default:
   1329     break;
   1330 }
   1331 return glyph;
   1332      }
   1333    }
   1334 
   1335    protected:
   1336    hb_sanitize_context_t   sc;
   1337 
   1338    public:
   1339    hb_blob_t               *blob = nullptr;
   1340    const Encoding	    *encoding = nullptr;
   1341    const Charset	    *charset = nullptr;
   1342    const CFF1NameIndex     *nameIndex = nullptr;
   1343    const CFF1TopDictIndex  *topDictIndex = nullptr;
   1344    const CFF1StringIndex   *stringIndex = nullptr;
   1345    const CFF1Subrs	    *globalSubrs = nullptr;
   1346    const CFF1CharStrings   *charStrings = nullptr;
   1347    const CFF1FDArray       *fdArray = nullptr;
   1348    const CFF1FDSelect      *fdSelect = nullptr;
   1349    unsigned int	     fdCount = 0;
   1350 
   1351    cff1_top_dict_values_t   topDict;
   1352    hb_vector_t<cff1_font_dict_values_t>
   1353 		     fontDicts;
   1354    hb_vector_t<PRIVDICTVAL> privateDicts;
   1355 
   1356    unsigned int	     num_glyphs = 0;
   1357    unsigned int	     num_charset_entries = 0;
   1358  };
   1359 
   1360  struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
   1361  {
   1362    accelerator_t (hb_face_t *face) : SUPER (face)
   1363    {
   1364      glyph_names.set_relaxed (nullptr);
   1365 
   1366      if (!is_valid ()) return;
   1367      if (is_CID ()) return;
   1368    }
   1369    ~accelerator_t ()
   1370    {
   1371      hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed ();
   1372      if (names)
   1373      {
   1374 names->fini ();
   1375 hb_free (names);
   1376      }
   1377    }
   1378 
   1379    bool get_glyph_name (hb_codepoint_t glyph,
   1380 		 char *buf, unsigned int buf_len) const
   1381    {
   1382      if (unlikely (glyph >= num_glyphs)) return false;
   1383      if (unlikely (!is_valid ())) return false;
   1384      if (is_CID()) return false;
   1385      if (unlikely (!buf_len)) return true;
   1386      hb_codepoint_t sid = glyph_to_sid (glyph);
   1387      const char *str;
   1388      size_t str_len;
   1389      if (sid < cff1_std_strings_length)
   1390      {
   1391 hb_bytes_t byte_str = cff1_std_strings (sid);
   1392 str = byte_str.arrayZ;
   1393 str_len = byte_str.length;
   1394      }
   1395      else
   1396      {
   1397 hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
   1398 str = (const char *)ubyte_str.arrayZ;
   1399 str_len = ubyte_str.length;
   1400      }
   1401      if (!str_len) return false;
   1402      unsigned int len = hb_min (buf_len - 1, str_len);
   1403      strncpy (buf, (const char*)str, len);
   1404      buf[len] = '\0';
   1405      return true;
   1406    }
   1407 
   1408    bool get_glyph_from_name (const char *name, int len,
   1409 		      hb_codepoint_t *glyph) const
   1410    {
   1411      if (unlikely (!is_valid ())) return false;
   1412      if (is_CID()) return false;
   1413      if (len < 0) len = strlen (name);
   1414      if (unlikely (!len)) return false;
   1415 
   1416    retry:
   1417      hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire ();
   1418      if (unlikely (!names))
   1419      {
   1420 names = (hb_sorted_vector_t<gname_t> *) hb_calloc (1, sizeof (hb_sorted_vector_t<gname_t>));
   1421 if (likely (names))
   1422 {
   1423   names->init ();
   1424   /* TODO */
   1425 
   1426   /* fill glyph names */
   1427   code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
   1428   for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
   1429   {
   1430     hb_codepoint_t	sid = glyph_to_sid (gid, &glyph_to_sid_cache);
   1431     gname_t	gname;
   1432     gname.sid = sid;
   1433     if (sid < cff1_std_strings_length)
   1434       gname.name = cff1_std_strings (sid);
   1435     else
   1436     {
   1437       hb_ubytes_t	ustr = (*stringIndex)[sid - cff1_std_strings_length];
   1438       gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length);
   1439     }
   1440     if (unlikely (!gname.name.arrayZ))
   1441       gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */
   1442     names->push (gname);
   1443   }
   1444   names->qsort ();
   1445 }
   1446 if (unlikely (!glyph_names.cmpexch (nullptr, names)))
   1447 {
   1448   if (names)
   1449   {
   1450     names->fini ();
   1451     hb_free (names);
   1452   }
   1453   goto retry;
   1454 }
   1455      }
   1456 
   1457      gname_t key = { hb_bytes_t (name, len), 0 };
   1458      const gname_t *gname = names ? names->bsearch (key) : nullptr;
   1459      if (!gname) return false;
   1460      hb_codepoint_t gid = sid_to_glyph (gname->sid);
   1461      if (!gid && gname->sid) return false;
   1462      *glyph = gid;
   1463      return true;
   1464    }
   1465 
   1466    HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
   1467    HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
   1468 
   1469    private:
   1470    struct gname_t
   1471    {
   1472      hb_bytes_t	name;
   1473      uint16_t		sid;
   1474 
   1475      static int cmp (const void *a_, const void *b_)
   1476      {
   1477 const gname_t *a = (const gname_t *)a_;
   1478 const gname_t *b = (const gname_t *)b_;
   1479 unsigned minlen = hb_min (a->name.length, b->name.length);
   1480 int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
   1481 if (ret) return ret;
   1482 return a->name.length - b->name.length;
   1483      }
   1484 
   1485      int cmp (const gname_t &a) const { return cmp (&a, this); }
   1486    };
   1487 
   1488    mutable hb_atomic_t<hb_sorted_vector_t<gname_t> *> glyph_names;
   1489 
   1490    typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
   1491  };
   1492 
   1493  struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t>
   1494  {
   1495    accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
   1496    ~accelerator_subset_t ()
   1497    {
   1498      if (cff_accelerator)
   1499 cff_subset_accelerator_t::destroy (cff_accelerator);
   1500    }
   1501 
   1502    HB_INTERNAL bool subset (hb_subset_context_t *c) const;
   1503    HB_INTERNAL bool serialize (hb_serialize_context_t *c,
   1504 			struct cff1_subset_plan &plan) const;
   1505    HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
   1506 
   1507    mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
   1508 
   1509    typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER;
   1510  };
   1511 
   1512  protected:
   1513  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
   1514  HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
   1515  HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
   1516  HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
   1517  HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
   1518  HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
   1519  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
   1520 
   1521  public:
   1522  FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
   1523  NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
   1524  HBUINT8	       offSize;	  /* offset size (unused?) */
   1525 
   1526  public:
   1527  DEFINE_SIZE_STATIC (4);
   1528 };
   1529 
   1530 struct cff1_accelerator_t : cff1::accelerator_t {
   1531  cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
   1532 };
   1533 
   1534 struct cff1_subset_accelerator_t : cff1::accelerator_subset_t {
   1535  cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {}
   1536 };
   1537 
   1538 } /* namespace OT */
   1539 
   1540 #endif /* HB_OT_CFF1_TABLE_HH */