Home | History | Annotate | Download | only in src
      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-head-table.hh"
     31 #include "hb-ot-cff-common.hh"
     32 #include "hb-subset-cff1.hh"
     33 
     34 namespace CFF {
     35 
     36 /*
     37  * CFF -- Compact Font Format (CFF)
     38  * http://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
     39  */
     40 #define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
     41 
     42 #define CFF_UNDEF_SID   CFF_UNDEF_CODE
     43 
     44 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
     45 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
     46 
     47 typedef CFFIndex<HBUINT16>  CFF1Index;
     48 template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
     49 
     50 typedef CFFIndex<HBUINT16> CFF1Index;
     51 typedef CFF1Index          CFF1CharStrings;
     52 typedef FDArray<HBUINT16>  CFF1FDArray;
     53 typedef Subrs<HBUINT16>    CFF1Subrs;
     54 
     55 struct CFF1FDSelect : FDSelect {};
     56 
     57 /* Encoding */
     58 struct Encoding0 {
     59   bool sanitize (hb_sanitize_context_t *c) const
     60   {
     61     TRACE_SANITIZE (this);
     62     return_trace (c->check_struct (this) && codes[nCodes - 1].sanitize (c));
     63   }
     64 
     65   hb_codepoint_t get_code (hb_codepoint_t glyph) const
     66   {
     67     assert (glyph > 0);
     68     glyph--;
     69     if (glyph < nCodes)
     70     {
     71       return (hb_codepoint_t)codes[glyph];
     72     }
     73     else
     74       return CFF_UNDEF_CODE;
     75   }
     76 
     77   unsigned int get_size () const
     78   { return HBUINT8::static_size * (nCodes + 1); }
     79 
     80   HBUINT8     nCodes;
     81   HBUINT8     codes[VAR];
     82 
     83   DEFINE_SIZE_ARRAY(1, codes);
     84 };
     85 
     86 struct Encoding1_Range {
     87   bool sanitize (hb_sanitize_context_t *c) const
     88   {
     89     TRACE_SANITIZE (this);
     90     return_trace (c->check_struct (this));
     91   }
     92 
     93   HBUINT8   first;
     94   HBUINT8   nLeft;
     95 
     96   DEFINE_SIZE_STATIC (2);
     97 };
     98 
     99 struct Encoding1 {
    100   unsigned int get_size () const
    101   { return HBUINT8::static_size + Encoding1_Range::static_size * nRanges; }
    102 
    103   bool sanitize (hb_sanitize_context_t *c) const
    104   {
    105     TRACE_SANITIZE (this);
    106     return_trace (c->check_struct (this) && ((nRanges == 0) || (ranges[nRanges - 1]).sanitize (c)));
    107   }
    108 
    109   hb_codepoint_t get_code (hb_codepoint_t glyph) const
    110   {
    111     assert (glyph > 0);
    112     glyph--;
    113     for (unsigned int i = 0; i < nRanges; i++)
    114     {
    115       if (glyph <= ranges[i].nLeft)
    116       {
    117 	return (hb_codepoint_t)ranges[i].first + glyph;
    118       }
    119       glyph -= (ranges[i].nLeft + 1);
    120     }
    121     return CFF_UNDEF_CODE;
    122   }
    123 
    124   HBUINT8	   nRanges;
    125   Encoding1_Range   ranges[VAR];
    126 
    127   DEFINE_SIZE_ARRAY (1, ranges);
    128 };
    129 
    130 struct SuppEncoding {
    131   bool sanitize (hb_sanitize_context_t *c) const
    132   {
    133     TRACE_SANITIZE (this);
    134     return_trace (c->check_struct (this));
    135   }
    136 
    137   HBUINT8   code;
    138   HBUINT16  glyph;
    139 
    140   DEFINE_SIZE_STATIC (3);
    141 };
    142 
    143 struct CFF1SuppEncData {
    144   bool sanitize (hb_sanitize_context_t *c) const
    145   {
    146     TRACE_SANITIZE (this);
    147     return_trace (c->check_struct (this) && ((nSups == 0) || (supps[nSups - 1]).sanitize (c)));
    148   }
    149 
    150   void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
    151   {
    152     for (unsigned int i = 0; i < nSups; i++)
    153       if (sid == supps[i].glyph)
    154 	codes.push (supps[i].code);
    155   }
    156 
    157   unsigned int get_size () const
    158   { return HBUINT8::static_size + SuppEncoding::static_size * nSups; }
    159 
    160   HBUINT8	 nSups;
    161   SuppEncoding   supps[VAR];
    162 
    163   DEFINE_SIZE_ARRAY (1, supps);
    164 };
    165 
    166 struct Encoding {
    167   bool sanitize (hb_sanitize_context_t *c) const
    168   {
    169     TRACE_SANITIZE (this);
    170 
    171     if (unlikely (!c->check_struct (this)))
    172       return_trace (false);
    173     unsigned int fmt = format & 0x7F;
    174     if (unlikely (fmt > 1))
    175       return_trace (false);
    176     if (unlikely (!((fmt == 0)? u.format0.sanitize (c): u.format1.sanitize (c))))
    177       return_trace (false);
    178     return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
    179   }
    180 
    181   /* serialize a fullset Encoding */
    182   bool serialize (hb_serialize_context_t *c, const Encoding &src)
    183   {
    184     TRACE_SERIALIZE (this);
    185     unsigned int size = src.get_size ();
    186     Encoding *dest = c->allocate_size<Encoding> (size);
    187     if (unlikely (dest == nullptr)) return_trace (false);
    188     memcpy (dest, &src, size);
    189     return_trace (true);
    190   }
    191 
    192   /* serialize a subset Encoding */
    193   bool serialize (hb_serialize_context_t *c,
    194 		  uint8_t format,
    195 		  unsigned int enc_count,
    196 		  const hb_vector_t<code_pair>& code_ranges,
    197 		  const hb_vector_t<code_pair>& supp_codes)
    198   {
    199     TRACE_SERIALIZE (this);
    200     Encoding *dest = c->extend_min (*this);
    201     if (unlikely (dest == nullptr)) return_trace (false);
    202     dest->format.set (format | ((supp_codes.len > 0)? 0x80: 0));
    203     if (format == 0)
    204     {
    205       Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
    206     if (unlikely (fmt0 == nullptr)) return_trace (false);
    207       fmt0->nCodes.set (enc_count);
    208       unsigned int glyph = 0;
    209       for (unsigned int i = 0; i < code_ranges.len; i++)
    210       {
    211 	hb_codepoint_t code = code_ranges[i].code;
    212 	for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
    213 	  fmt0->codes[glyph++].set (code++);
    214 	if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
    215 	  return_trace (false);
    216       }
    217     }
    218     else
    219     {
    220       Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.len);
    221       if (unlikely (fmt1 == nullptr)) return_trace (false);
    222       fmt1->nRanges.set (code_ranges.len);
    223       for (unsigned int i = 0; i < code_ranges.len; i++)
    224       {
    225 	if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
    226 	  return_trace (false);
    227 	fmt1->ranges[i].first.set (code_ranges[i].code);
    228 	fmt1->ranges[i].nLeft.set (code_ranges[i].glyph);
    229       }
    230     }
    231     if (supp_codes.len > 0)
    232     {
    233       CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.len);
    234       if (unlikely (suppData == nullptr)) return_trace (false);
    235       suppData->nSups.set (supp_codes.len);
    236       for (unsigned int i = 0; i < supp_codes.len; i++)
    237       {
    238 	suppData->supps[i].code.set (supp_codes[i].code);
    239 	suppData->supps[i].glyph.set (supp_codes[i].glyph); /* actually SID */
    240       }
    241     }
    242     return_trace (true);
    243   }
    244 
    245   /* parallel to above: calculate the size of a subset Encoding */
    246   static unsigned int calculate_serialized_size (uint8_t format,
    247 						 unsigned int enc_count,
    248 						 unsigned int supp_count)
    249   {
    250     unsigned int  size = min_size;
    251     if (format == 0)
    252       size += Encoding0::min_size + HBUINT8::static_size * enc_count;
    253     else
    254       size += Encoding1::min_size + Encoding1_Range::static_size * enc_count;
    255     if (supp_count > 0)
    256       size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
    257     return size;
    258   }
    259 
    260   unsigned int get_size () const
    261   {
    262     unsigned int size = min_size;
    263     if (table_format () == 0)
    264       size += u.format0.get_size ();
    265     else
    266       size += u.format1.get_size ();
    267     if (has_supplement ())
    268       size += suppEncData ().get_size ();
    269     return size;
    270   }
    271 
    272   hb_codepoint_t get_code (hb_codepoint_t glyph) const
    273   {
    274     if (table_format () == 0)
    275       return u.format0.get_code (glyph);
    276     else
    277       return u.format1.get_code (glyph);
    278   }
    279 
    280   uint8_t table_format () const { return (format & 0x7F); }
    281   bool  has_supplement () const { return (format & 0x80) != 0; }
    282 
    283   void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
    284   {
    285     codes.resize (0);
    286     if (has_supplement ())
    287       suppEncData().get_codes (sid, codes);
    288   }
    289 
    290   protected:
    291   const CFF1SuppEncData &suppEncData () const
    292   {
    293     if ((format & 0x7F) == 0)
    294       return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes-1]);
    295     else
    296       return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges-1]);
    297   }
    298 
    299   public:
    300   HBUINT8       format;
    301 
    302   union {
    303     Encoding0   format0;
    304     Encoding1   format1;
    305   } u;
    306   /* CFF1SuppEncData  suppEncData; */
    307 
    308   DEFINE_SIZE_MIN (1);
    309 };
    310 
    311 /* Charset */
    312 struct Charset0 {
    313   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
    314   {
    315     TRACE_SANITIZE (this);
    316     return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
    317   }
    318 
    319   hb_codepoint_t get_sid (hb_codepoint_t glyph) const
    320   {
    321     if (glyph == 0)
    322       return 0;
    323     else
    324       return sids[glyph - 1];
    325   }
    326 
    327   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
    328   {
    329     if (sid == 0)
    330       return 0;
    331 
    332     for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
    333     {
    334       if (sids[glyph-1] == sid)
    335 	return glyph;
    336     }
    337     return 0;
    338   }
    339 
    340   unsigned int get_size (unsigned int num_glyphs) const
    341   {
    342     assert (num_glyphs > 0);
    343     return HBUINT16::static_size * (num_glyphs - 1);
    344   }
    345 
    346   HBUINT16  sids[VAR];
    347 
    348   DEFINE_SIZE_ARRAY(0, sids);
    349 };
    350 
    351 template <typename TYPE>
    352 struct Charset_Range {
    353   bool sanitize (hb_sanitize_context_t *c) const
    354   {
    355     TRACE_SANITIZE (this);
    356     return_trace (c->check_struct (this));
    357   }
    358 
    359   HBUINT16  first;
    360   TYPE      nLeft;
    361 
    362   DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
    363 };
    364 
    365 template <typename TYPE>
    366 struct Charset1_2 {
    367   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
    368   {
    369     TRACE_SANITIZE (this);
    370     if (unlikely (!c->check_struct (this)))
    371       return_trace (false);
    372     num_glyphs--;
    373     for (unsigned int i = 0; num_glyphs > 0; i++)
    374     {
    375       if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
    376 	return_trace (false);
    377       num_glyphs -= (ranges[i].nLeft + 1);
    378     }
    379     return_trace (true);
    380   }
    381 
    382   hb_codepoint_t get_sid (hb_codepoint_t glyph) const
    383   {
    384     if (glyph == 0) return 0;
    385     glyph--;
    386     for (unsigned int i = 0;; i++)
    387     {
    388       if (glyph <= ranges[i].nLeft)
    389 	return (hb_codepoint_t)ranges[i].first + glyph;
    390       glyph -= (ranges[i].nLeft + 1);
    391     }
    392 
    393     return 0;
    394   }
    395 
    396   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
    397   {
    398     if (sid == 0) return 0;
    399     hb_codepoint_t  glyph = 1;
    400     for (unsigned int i = 0;; i++)
    401     {
    402       if (glyph >= num_glyphs)
    403       	return 0;
    404       if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
    405 	return glyph + (sid - ranges[i].first);
    406       glyph += (ranges[i].nLeft + 1);
    407     }
    408 
    409     return 0;
    410   }
    411 
    412   unsigned int get_size (unsigned int num_glyphs) const
    413   {
    414     unsigned int size = HBUINT8::static_size;
    415     int glyph = (int)num_glyphs;
    416 
    417     assert (glyph > 0);
    418     glyph--;
    419     for (unsigned int i = 0; glyph > 0; i++)
    420     {
    421       glyph -= (ranges[i].nLeft + 1);
    422       size += Charset_Range<TYPE>::static_size;
    423     }
    424 
    425     return size;
    426   }
    427 
    428   Charset_Range<TYPE>   ranges[VAR];
    429 
    430   DEFINE_SIZE_ARRAY (0, ranges);
    431 };
    432 
    433 typedef Charset1_2<HBUINT8>     Charset1;
    434 typedef Charset1_2<HBUINT16>    Charset2;
    435 typedef Charset_Range<HBUINT8>  Charset1_Range;
    436 typedef Charset_Range<HBUINT16> Charset2_Range;
    437 
    438 struct Charset {
    439   bool sanitize (hb_sanitize_context_t *c) const
    440   {
    441     TRACE_SANITIZE (this);
    442 
    443     if (unlikely (!c->check_struct (this)))
    444       return_trace (false);
    445     if (format == 0)
    446       return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
    447     else if (format == 1)
    448       return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
    449     else if (likely (format == 2))
    450       return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
    451     else
    452       return_trace (false);
    453   }
    454 
    455   /* serialize a fullset Charset */
    456   bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
    457   {
    458     TRACE_SERIALIZE (this);
    459     unsigned int size = src.get_size (num_glyphs);
    460     Charset *dest = c->allocate_size<Charset> (size);
    461     if (unlikely (dest == nullptr)) return_trace (false);
    462     memcpy (dest, &src, size);
    463     return_trace (true);
    464   }
    465 
    466   /* serialize a subset Charset */
    467   bool serialize (hb_serialize_context_t *c,
    468 		  uint8_t format,
    469 		  unsigned int num_glyphs,
    470 		  const hb_vector_t<code_pair>& sid_ranges)
    471   {
    472     TRACE_SERIALIZE (this);
    473     Charset *dest = c->extend_min (*this);
    474     if (unlikely (dest == nullptr)) return_trace (false);
    475     dest->format.set (format);
    476     if (format == 0)
    477     {
    478       Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
    479     if (unlikely (fmt0 == nullptr)) return_trace (false);
    480       unsigned int glyph = 0;
    481       for (unsigned int i = 0; i < sid_ranges.len; i++)
    482       {
    483 	hb_codepoint_t sid = sid_ranges[i].code;
    484 	for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
    485 	  fmt0->sids[glyph++].set (sid++);
    486       }
    487     }
    488     else if (format == 1)
    489     {
    490       Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.len);
    491       if (unlikely (fmt1 == nullptr)) return_trace (false);
    492       for (unsigned int i = 0; i < sid_ranges.len; i++)
    493       {
    494       	if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
    495 	  return_trace (false);
    496 	fmt1->ranges[i].first.set (sid_ranges[i].code);
    497 	fmt1->ranges[i].nLeft.set (sid_ranges[i].glyph);
    498       }
    499     }
    500     else /* format 2 */
    501     {
    502       Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.len);
    503       if (unlikely (fmt2 == nullptr)) return_trace (false);
    504       for (unsigned int i = 0; i < sid_ranges.len; i++)
    505       {
    506       	if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
    507 	  return_trace (false);
    508 	fmt2->ranges[i].first.set (sid_ranges[i].code);
    509 	fmt2->ranges[i].nLeft.set (sid_ranges[i].glyph);
    510       }
    511     }
    512     return_trace (true);
    513   }
    514 
    515   /* parallel to above: calculate the size of a subset Charset */
    516   static unsigned int calculate_serialized_size (
    517 			uint8_t format,
    518 			unsigned int count)
    519   {
    520     unsigned int  size = min_size;
    521     if (format == 0)
    522       size += Charset0::min_size + HBUINT16::static_size * (count - 1);
    523     else if (format == 1)
    524       size += Charset1::min_size + Charset1_Range::static_size * count;
    525     else
    526       size += Charset2::min_size + Charset2_Range::static_size * count;
    527 
    528     return size;
    529   }
    530 
    531   unsigned int get_size (unsigned int num_glyphs) const
    532   {
    533     unsigned int size = min_size;
    534     if (format == 0)
    535       size += u.format0.get_size (num_glyphs);
    536     else if (format == 1)
    537       size += u.format1.get_size (num_glyphs);
    538     else
    539       size += u.format2.get_size (num_glyphs);
    540     return size;
    541   }
    542 
    543   hb_codepoint_t get_sid (hb_codepoint_t glyph) const
    544   {
    545     if (format == 0)
    546       return u.format0.get_sid (glyph);
    547     else if (format == 1)
    548       return u.format1.get_sid (glyph);
    549     else
    550       return u.format2.get_sid (glyph);
    551   }
    552 
    553   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
    554   {
    555     if (format == 0)
    556       return u.format0.get_glyph (sid, num_glyphs);
    557     else if (format == 1)
    558       return u.format1.get_glyph (sid, num_glyphs);
    559     else
    560       return u.format2.get_glyph (sid, num_glyphs);
    561   }
    562 
    563   HBUINT8       format;
    564   union {
    565     Charset0    format0;
    566     Charset1    format1;
    567     Charset2    format2;
    568   } u;
    569 
    570   DEFINE_SIZE_MIN (1);
    571 };
    572 
    573 struct CFF1StringIndex : CFF1Index
    574 {
    575   bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
    576 		  unsigned int offSize_, const Remap &sidmap)
    577   {
    578     TRACE_SERIALIZE (this);
    579     if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
    580     {
    581       if (!unlikely (c->extend_min (this->count)))
    582 	return_trace (false);
    583       count.set (0);
    584       return_trace (true);
    585     }
    586 
    587     ByteStrArray bytesArray;
    588     bytesArray.init ();
    589     if (!bytesArray.resize (sidmap.get_count ()))
    590       return_trace (false);
    591     for (unsigned int i = 0; i < strings.count; i++)
    592     {
    593       hb_codepoint_t  j = sidmap[i];
    594       if (j != CFF_UNDEF_CODE)
    595 	bytesArray[j] = strings[i];
    596     }
    597 
    598     bool result = CFF1Index::serialize (c, offSize_, bytesArray);
    599     bytesArray.fini ();
    600     return_trace (result);
    601   }
    602 
    603   /* in parallel to above */
    604   unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const Remap &sidmap) const
    605   {
    606     offSize = 0;
    607     if ((count == 0) || (sidmap.get_count () == 0))
    608       return count.static_size;
    609 
    610     unsigned int dataSize = 0;
    611     for (unsigned int i = 0; i < count; i++)
    612       if (sidmap[i] != CFF_UNDEF_CODE)
    613 	dataSize += length_at (i);
    614 
    615     offSize = calcOffSize(dataSize);
    616     return CFF1Index::calculate_serialized_size (offSize, sidmap.get_count (), dataSize);
    617   }
    618 };
    619 
    620 struct CFF1TopDictInterpEnv : NumInterpEnv
    621 {
    622   CFF1TopDictInterpEnv ()
    623     : NumInterpEnv(), prev_offset(0), last_offset(0) {}
    624 
    625   unsigned int prev_offset;
    626   unsigned int last_offset;
    627 };
    628 
    629 struct NameDictValues
    630 {
    631   enum NameDictValIndex
    632   {
    633       version,
    634       notice,
    635       copyright,
    636       fullName,
    637       familyName,
    638       weight,
    639       postscript,
    640       fontName,
    641       baseFontName,
    642       registry,
    643       ordering,
    644 
    645       ValCount
    646   };
    647 
    648   void init ()
    649   {
    650     for (unsigned int i = 0; i < ValCount; i++)
    651       values[i] = CFF_UNDEF_SID;
    652   }
    653 
    654   unsigned int& operator[] (unsigned int i)
    655   { assert (i < ValCount); return values[i]; }
    656 
    657   unsigned int operator[] (unsigned int i) const
    658   { assert (i < ValCount); return values[i]; }
    659 
    660   static enum NameDictValIndex name_op_to_index (OpCode op)
    661   {
    662     switch (op) {
    663       default: // can't happen - just make some compiler happy
    664       case OpCode_version:
    665 	return version;
    666       case OpCode_Notice:
    667 	return notice;
    668       case OpCode_Copyright:
    669 	return copyright;
    670       case OpCode_FullName:
    671 	return fullName;
    672       case OpCode_FamilyName:
    673 	return familyName;
    674       case OpCode_Weight:
    675 	return weight;
    676       case OpCode_PostScript:
    677 	return postscript;
    678       case OpCode_FontName:
    679 	return fontName;
    680       case OpCode_BaseFontName:
    681 	return baseFontName;
    682     }
    683   }
    684 
    685   unsigned int  values[ValCount];
    686 };
    687 
    688 struct CFF1TopDictVal : OpStr
    689 {
    690   unsigned int  last_arg_offset;
    691 };
    692 
    693 struct CFF1TopDictValues : TopDictValues<CFF1TopDictVal>
    694 {
    695   void init ()
    696   {
    697     TopDictValues<CFF1TopDictVal>::init ();
    698 
    699     nameSIDs.init ();
    700     ros_supplement = 0;
    701     cidCount = 8720;
    702     EncodingOffset = 0;
    703     CharsetOffset = 0;
    704     FDSelectOffset = 0;
    705     privateDictInfo.init ();
    706   }
    707   void fini () { TopDictValues<CFF1TopDictVal>::fini (); }
    708 
    709   bool is_CID () const
    710   { return nameSIDs[NameDictValues::registry] != CFF_UNDEF_SID; }
    711 
    712   NameDictValues  nameSIDs;
    713   unsigned int    ros_supplement_offset;
    714   unsigned int    ros_supplement;
    715   unsigned int    cidCount;
    716 
    717   unsigned int    EncodingOffset;
    718   unsigned int    CharsetOffset;
    719   unsigned int    FDSelectOffset;
    720   TableInfo       privateDictInfo;
    721 };
    722 
    723 struct CFF1TopDictOpSet : TopDictOpSet<CFF1TopDictVal>
    724 {
    725   static void process_op (OpCode op, CFF1TopDictInterpEnv& env, CFF1TopDictValues& dictval)
    726   {
    727     CFF1TopDictVal  val;
    728     val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
    729 
    730     switch (op) {
    731       case OpCode_version:
    732       case OpCode_Notice:
    733       case OpCode_Copyright:
    734       case OpCode_FullName:
    735       case OpCode_FamilyName:
    736       case OpCode_Weight:
    737       case OpCode_PostScript:
    738       case OpCode_BaseFontName:
    739 	dictval.nameSIDs[NameDictValues::name_op_to_index (op)] = env.argStack.pop_uint ();
    740 	env.clear_args ();
    741 	break;
    742       case OpCode_isFixedPitch:
    743       case OpCode_ItalicAngle:
    744       case OpCode_UnderlinePosition:
    745       case OpCode_UnderlineThickness:
    746       case OpCode_PaintType:
    747       case OpCode_CharstringType:
    748       case OpCode_UniqueID:
    749       case OpCode_StrokeWidth:
    750       case OpCode_SyntheticBase:
    751       case OpCode_CIDFontVersion:
    752       case OpCode_CIDFontRevision:
    753       case OpCode_CIDFontType:
    754       case OpCode_UIDBase:
    755       case OpCode_FontBBox:
    756       case OpCode_XUID:
    757       case OpCode_BaseFontBlend:
    758 	env.clear_args ();
    759 	break;
    760 
    761       case OpCode_CIDCount:
    762 	dictval.cidCount = env.argStack.pop_uint ();
    763 	env.clear_args ();
    764 	break;
    765 
    766       case OpCode_ROS:
    767 	dictval.ros_supplement = env.argStack.pop_uint ();
    768 	dictval.nameSIDs[NameDictValues::ordering] = env.argStack.pop_uint ();
    769 	dictval.nameSIDs[NameDictValues::registry] = env.argStack.pop_uint ();
    770 	env.clear_args ();
    771 	break;
    772 
    773       case OpCode_Encoding:
    774 	dictval.EncodingOffset = env.argStack.pop_uint ();
    775 	env.clear_args ();
    776 	if (unlikely (dictval.EncodingOffset == 0)) return;
    777 	break;
    778 
    779       case OpCode_charset:
    780 	dictval.CharsetOffset = env.argStack.pop_uint ();
    781 	env.clear_args ();
    782 	if (unlikely (dictval.CharsetOffset == 0)) return;
    783 	break;
    784 
    785       case OpCode_FDSelect:
    786 	dictval.FDSelectOffset = env.argStack.pop_uint ();
    787 	env.clear_args ();
    788 	break;
    789 
    790       case OpCode_Private:
    791 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
    792 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
    793 	env.clear_args ();
    794 	break;
    795 
    796       default:
    797 	env.last_offset = env.substr.offset;
    798 	TopDictOpSet<CFF1TopDictVal>::process_op (op, env, dictval);
    799 	/* Record this operand below if stack is empty, otherwise done */
    800 	if (!env.argStack.is_empty ()) return;
    801 	break;
    802     }
    803 
    804     if (unlikely (env.in_error ())) return;
    805 
    806     dictval.add_op (op, env.substr, val);
    807   }
    808 };
    809 
    810 struct CFF1FontDictValues : DictValues<OpStr>
    811 {
    812   void init ()
    813   {
    814     DictValues<OpStr>::init ();
    815     privateDictInfo.init ();
    816     fontName = CFF_UNDEF_SID;
    817   }
    818   void fini () { DictValues<OpStr>::fini (); }
    819 
    820   TableInfo       privateDictInfo;
    821   unsigned int    fontName;
    822 };
    823 
    824 struct CFF1FontDictOpSet : DictOpSet
    825 {
    826   static void process_op (OpCode op, NumInterpEnv& env, CFF1FontDictValues& dictval)
    827   {
    828     switch (op) {
    829       case OpCode_FontName:
    830 	dictval.fontName = env.argStack.pop_uint ();
    831 	env.clear_args ();
    832 	break;
    833       case OpCode_FontMatrix:
    834       case OpCode_PaintType:
    835 	env.clear_args ();
    836 	break;
    837       case OpCode_Private:
    838 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
    839 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
    840 	env.clear_args ();
    841 	break;
    842 
    843       default:
    844 	DictOpSet::process_op (op, env);
    845 	if (!env.argStack.is_empty ()) return;
    846 	break;
    847     }
    848 
    849     if (unlikely (env.in_error ())) return;
    850 
    851     dictval.add_op (op, env.substr);
    852   }
    853 };
    854 
    855 template <typename VAL>
    856 struct CFF1PrivateDictValues_Base : DictValues<VAL>
    857 {
    858   void init ()
    859   {
    860     DictValues<VAL>::init ();
    861     subrsOffset = 0;
    862     localSubrs = &Null(CFF1Subrs);
    863   }
    864   void fini () { DictValues<VAL>::fini (); }
    865 
    866   unsigned int calculate_serialized_size () const
    867   {
    868     unsigned int size = 0;
    869     for (unsigned int i = 0; i < DictValues<VAL>::get_count; i++)
    870       if (DictValues<VAL>::get_value (i).op == OpCode_Subrs)
    871 	size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
    872       else
    873 	size += DictValues<VAL>::get_value (i).str.len;
    874     return size;
    875   }
    876 
    877   unsigned int      subrsOffset;
    878   const CFF1Subrs    *localSubrs;
    879 };
    880 
    881 typedef CFF1PrivateDictValues_Base<OpStr> CFF1PrivateDictValues_Subset;
    882 typedef CFF1PrivateDictValues_Base<NumDictVal> CFF1PrivateDictValues;
    883 
    884 struct CFF1PrivateDictOpSet : DictOpSet
    885 {
    886   static void process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues& dictval)
    887   {
    888     NumDictVal val;
    889     val.init ();
    890 
    891     switch (op) {
    892       case OpCode_BlueValues:
    893       case OpCode_OtherBlues:
    894       case OpCode_FamilyBlues:
    895       case OpCode_FamilyOtherBlues:
    896       case OpCode_StemSnapH:
    897       case OpCode_StemSnapV:
    898 	env.clear_args ();
    899 	break;
    900       case OpCode_StdHW:
    901       case OpCode_StdVW:
    902       case OpCode_BlueScale:
    903       case OpCode_BlueShift:
    904       case OpCode_BlueFuzz:
    905       case OpCode_ForceBold:
    906       case OpCode_LanguageGroup:
    907       case OpCode_ExpansionFactor:
    908       case OpCode_initialRandomSeed:
    909       case OpCode_defaultWidthX:
    910       case OpCode_nominalWidthX:
    911 	val.single_val = env.argStack.pop_num ();
    912 	env.clear_args ();
    913 	break;
    914       case OpCode_Subrs:
    915 	dictval.subrsOffset = env.argStack.pop_uint ();
    916 	env.clear_args ();
    917 	break;
    918 
    919       default:
    920 	DictOpSet::process_op (op, env);
    921 	if (!env.argStack.is_empty ()) return;
    922 	break;
    923     }
    924 
    925     if (unlikely (env.in_error ())) return;
    926 
    927     dictval.add_op (op, env.substr, val);
    928   }
    929 };
    930 
    931 struct CFF1PrivateDictOpSet_Subset : DictOpSet
    932 {
    933   static void process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues_Subset& dictval)
    934   {
    935     switch (op) {
    936       case OpCode_BlueValues:
    937       case OpCode_OtherBlues:
    938       case OpCode_FamilyBlues:
    939       case OpCode_FamilyOtherBlues:
    940       case OpCode_StemSnapH:
    941       case OpCode_StemSnapV:
    942       case OpCode_StdHW:
    943       case OpCode_StdVW:
    944       case OpCode_BlueScale:
    945       case OpCode_BlueShift:
    946       case OpCode_BlueFuzz:
    947       case OpCode_ForceBold:
    948       case OpCode_LanguageGroup:
    949       case OpCode_ExpansionFactor:
    950       case OpCode_initialRandomSeed:
    951       case OpCode_defaultWidthX:
    952       case OpCode_nominalWidthX:
    953 	env.clear_args ();
    954 	break;
    955 
    956       case OpCode_Subrs:
    957 	dictval.subrsOffset = env.argStack.pop_uint ();
    958 	env.clear_args ();
    959 	break;
    960 
    961       default:
    962 	DictOpSet::process_op (op, env);
    963 	if (!env.argStack.is_empty ()) return;
    964 	break;
    965     }
    966 
    967     if (unlikely (env.in_error ())) return;
    968 
    969     dictval.add_op (op, env.substr);
    970   }
    971 };
    972 
    973 typedef DictInterpreter<CFF1TopDictOpSet, CFF1TopDictValues, CFF1TopDictInterpEnv> CFF1TopDict_Interpreter;
    974 typedef DictInterpreter<CFF1FontDictOpSet, CFF1FontDictValues> CFF1FontDict_Interpreter;
    975 typedef DictInterpreter<CFF1PrivateDictOpSet, CFF1PrivateDictValues> CFF1PrivateDict_Interpreter;
    976 
    977 typedef CFF1Index CFF1NameIndex;
    978 typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
    979 
    980 }; /* namespace CFF */
    981 
    982 namespace OT {
    983 
    984 using namespace CFF;
    985 
    986 struct cff1
    987 {
    988   static const hb_tag_t tableTag	= HB_OT_TAG_cff1;
    989 
    990   bool sanitize (hb_sanitize_context_t *c) const
    991   {
    992     TRACE_SANITIZE (this);
    993     return_trace (c->check_struct (this) &&
    994 		  likely (version.major == 1));
    995   }
    996 
    997   template <typename PRIVOPSET, typename PRIVDICTVAL>
    998   struct accelerator_templ_t
    999   {
   1000     void init (hb_face_t *face)
   1001     {
   1002       topDict.init ();
   1003       fontDicts.init ();
   1004       privateDicts.init ();
   1005 
   1006       this->blob = sc.reference_table<cff1> (face);
   1007 
   1008       /* setup for run-time santization */
   1009       sc.init (this->blob);
   1010       sc.start_processing ();
   1011 
   1012       const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
   1013 
   1014       if (cff == &Null(OT::cff1))
   1015       { fini (); return; }
   1016 
   1017       nameIndex = &cff->nameIndex (cff);
   1018       if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
   1019       { fini (); return; }
   1020 
   1021       topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
   1022       if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
   1023       { fini (); return; }
   1024 
   1025       { /* parse top dict */
   1026 	const ByteStr topDictStr = (*topDictIndex)[0];
   1027 	if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
   1028 	CFF1TopDict_Interpreter top_interp;
   1029 	top_interp.env.init (topDictStr);
   1030 	topDict.init ();
   1031 	if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
   1032       }
   1033 
   1034       if (is_predef_charset ())
   1035 	charset = &Null(Charset);
   1036       else
   1037       {
   1038 	charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
   1039 	if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
   1040       }
   1041 
   1042       fdCount = 1;
   1043       if (is_CID ())
   1044       {
   1045 	fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
   1046 	fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
   1047 	if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
   1048 	    (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
   1049 	{ fini (); return; }
   1050 
   1051 	fdCount = fdArray->count;
   1052       }
   1053       else
   1054       {
   1055 	fdArray = &Null(CFF1FDArray);
   1056 	fdSelect = &Null(CFF1FDSelect);
   1057       }
   1058 
   1059       stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
   1060       if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
   1061       { fini (); return; }
   1062 
   1063       globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
   1064       if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
   1065       { fini (); return; }
   1066 
   1067       charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
   1068 
   1069       if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
   1070       { fini (); return; }
   1071 
   1072       num_glyphs = charStrings->count;
   1073       if (num_glyphs != sc.get_num_glyphs ())
   1074       { fini (); return; }
   1075 
   1076       privateDicts.resize (fdCount);
   1077       for (unsigned int i = 0; i < fdCount; i++)
   1078 	privateDicts[i].init ();
   1079 
   1080       // parse CID font dicts and gather private dicts
   1081       if (is_CID ())
   1082       {
   1083 	for (unsigned int i = 0; i < fdCount; i++)
   1084 	{
   1085 	  ByteStr fontDictStr = (*fdArray)[i];
   1086 	  if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
   1087 	  CFF1FontDictValues  *font;
   1088 	  CFF1FontDict_Interpreter font_interp;
   1089 	  font_interp.env.init (fontDictStr);
   1090 	  font = fontDicts.push ();
   1091 	  if (unlikely (font == &Crap(CFF1FontDictValues))) { fini (); return; }
   1092 	  font->init ();
   1093 	  if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
   1094 	  PRIVDICTVAL  *priv = &privateDicts[i];
   1095 	  const ByteStr privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
   1096 	  if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
   1097 	  DictInterpreter<PRIVOPSET, PRIVDICTVAL> priv_interp;
   1098 	  priv_interp.env.init (privDictStr);
   1099 	  priv->init ();
   1100 	  if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
   1101 
   1102 	  priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (privDictStr.str, priv->subrsOffset);
   1103 	  if (priv->localSubrs != &Null(CFF1Subrs) &&
   1104 	      unlikely (!priv->localSubrs->sanitize (&sc)))
   1105 	  { fini (); return; }
   1106 	}
   1107       }
   1108       else  /* non-CID */
   1109       {
   1110 	CFF1TopDictValues  *font = &topDict;
   1111 	PRIVDICTVAL  *priv = &privateDicts[0];
   1112 
   1113 	const ByteStr privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
   1114 	if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
   1115 	DictInterpreter<PRIVOPSET, PRIVDICTVAL> priv_interp;
   1116 	priv_interp.env.init (privDictStr);
   1117 	priv->init ();
   1118 	if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
   1119 
   1120 	priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (privDictStr.str, priv->subrsOffset);
   1121 	if (priv->localSubrs != &Null(CFF1Subrs) &&
   1122 	    unlikely (!priv->localSubrs->sanitize (&sc)))
   1123 	{ fini (); return; }
   1124       }
   1125     }
   1126 
   1127     void fini ()
   1128     {
   1129       sc.end_processing ();
   1130       topDict.fini ();
   1131       fontDicts.fini_deep ();
   1132       privateDicts.fini_deep ();
   1133       hb_blob_destroy (blob);
   1134       blob = nullptr;
   1135     }
   1136 
   1137     bool is_valid () const { return blob != nullptr; }
   1138     bool is_CID () const { return topDict.is_CID (); }
   1139 
   1140     bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
   1141 
   1142     unsigned int std_code_to_glyph (hb_codepoint_t code) const
   1143     {
   1144       hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
   1145       if (unlikely (sid == CFF_UNDEF_SID))
   1146 	return 0;
   1147 
   1148       if (charset != &Null(Charset))
   1149 	return charset->get_glyph (sid, num_glyphs);
   1150       else if ((topDict.CharsetOffset == ISOAdobeCharset)
   1151 	      && (code <= 228 /*zcaron*/)) return sid;
   1152       return 0;
   1153     }
   1154 
   1155     protected:
   1156     hb_blob_t	       *blob;
   1157     hb_sanitize_context_t   sc;
   1158 
   1159     public:
   1160     const Charset	   *charset;
   1161     const CFF1NameIndex     *nameIndex;
   1162     const CFF1TopDictIndex  *topDictIndex;
   1163     const CFF1StringIndex   *stringIndex;
   1164     const CFF1Subrs	 *globalSubrs;
   1165     const CFF1CharStrings   *charStrings;
   1166     const CFF1FDArray       *fdArray;
   1167     const CFF1FDSelect      *fdSelect;
   1168     unsigned int	    fdCount;
   1169 
   1170     CFF1TopDictValues       topDict;
   1171     hb_vector_t<CFF1FontDictValues>   fontDicts;
   1172     hb_vector_t<PRIVDICTVAL>	  privateDicts;
   1173 
   1174     unsigned int	    num_glyphs;
   1175   };
   1176 
   1177   struct accelerator_t : accelerator_templ_t<CFF1PrivateDictOpSet, CFF1PrivateDictValues>
   1178   {
   1179     HB_INTERNAL bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
   1180     HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
   1181   };
   1182 
   1183   struct accelerator_subset_t : accelerator_templ_t<CFF1PrivateDictOpSet_Subset, CFF1PrivateDictValues_Subset>
   1184   {
   1185     void init (hb_face_t *face)
   1186     {
   1187       SUPER::init (face);
   1188       if (blob == nullptr) return;
   1189 
   1190       const OT::cff1 *cff = this->blob->as<OT::cff1> ();
   1191       encoding = &Null(Encoding);
   1192       if (is_CID ())
   1193       {
   1194 	if (unlikely (charset == &Null(Charset))) { fini (); return; }
   1195       }
   1196       else
   1197       {
   1198 	if (!is_predef_encoding ())
   1199 	{
   1200 	  encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
   1201 	  if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
   1202 	}
   1203       }
   1204     }
   1205 
   1206     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
   1207 
   1208     hb_codepoint_t  glyph_to_code (hb_codepoint_t glyph) const
   1209     {
   1210       if (encoding != &Null(Encoding))
   1211 	return encoding->get_code (glyph);
   1212       else
   1213       {
   1214 	hb_codepoint_t  sid = glyph_to_sid (glyph);
   1215 	if (sid == 0) return 0;
   1216 	hb_codepoint_t  code = 0;
   1217 	switch (topDict.EncodingOffset)
   1218 	{
   1219 	  case  StandardEncoding:
   1220 	    code = lookup_standard_encoding_for_code (sid);
   1221 	    break;
   1222 	  case  ExpertEncoding:
   1223 	    code = lookup_expert_encoding_for_code (sid);
   1224 	    break;
   1225 	  default:
   1226 	    break;
   1227 	}
   1228 	return code;
   1229       }
   1230     }
   1231 
   1232     hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
   1233     {
   1234       if (charset != &Null(Charset))
   1235 	return charset->get_sid (glyph);
   1236       else
   1237       {
   1238 	hb_codepoint_t sid = 0;
   1239 	switch (topDict.CharsetOffset)
   1240 	{
   1241 	  case  ISOAdobeCharset:
   1242 	    if (glyph <= 228 /*zcaron*/) sid = glyph;
   1243 	    break;
   1244 	  case  ExpertCharset:
   1245 	    sid = lookup_expert_charset_for_sid (glyph);
   1246 	    break;
   1247 	  case  ExpertSubsetCharset:
   1248 	      sid = lookup_expert_subset_charset_for_sid (glyph);
   1249 	    break;
   1250 	  default:
   1251 	    break;
   1252 	}
   1253 	return sid;
   1254       }
   1255     }
   1256 
   1257     const Encoding	  *encoding;
   1258 
   1259     private:
   1260     typedef accelerator_templ_t<CFF1PrivateDictOpSet_Subset, CFF1PrivateDictValues_Subset> SUPER;
   1261   };
   1262 
   1263   bool subset (hb_subset_plan_t *plan) const
   1264   {
   1265     hb_blob_t *cff_prime = nullptr;
   1266 
   1267     bool success = true;
   1268     if (hb_subset_cff1 (plan, &cff_prime)) {
   1269       success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime);
   1270       hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
   1271       success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
   1272       hb_blob_destroy (head_blob);
   1273     } else {
   1274       success = false;
   1275     }
   1276     hb_blob_destroy (cff_prime);
   1277 
   1278     return success;
   1279   }
   1280 
   1281   protected:
   1282   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
   1283   HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
   1284   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
   1285   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
   1286   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
   1287 
   1288   public:
   1289   FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
   1290   OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
   1291   HBUINT8	       offSize;	  /* offset size (unused?) */
   1292 
   1293   public:
   1294   DEFINE_SIZE_STATIC (4);
   1295 };
   1296 
   1297 struct cff1_accelerator_t : cff1::accelerator_t {};
   1298 } /* namespace OT */
   1299 
   1300 #endif /* HB_OT_CFF1_TABLE_HH */
   1301