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