6fb59315c9f99dadda6a34f2e9015f8c1ef12688
[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_FontName:
717       case OpCode_FamilyName:
718       case OpCode_Weight:
719       case OpCode_PostScript:
720       case OpCode_BaseFontName:
721         dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
722         env.clear_args ();
723         break;
724       case OpCode_isFixedPitch:
725       case OpCode_ItalicAngle:
726       case OpCode_UnderlinePosition:
727       case OpCode_UnderlineThickness:
728       case OpCode_PaintType:
729       case OpCode_CharstringType:
730       case OpCode_UniqueID:
731       case OpCode_StrokeWidth:
732       case OpCode_SyntheticBase:
733       case OpCode_CIDFontVersion:
734       case OpCode_CIDFontRevision:
735       case OpCode_CIDFontType:
736       case OpCode_UIDBase:
737       case OpCode_FontBBox:
738       case OpCode_XUID:
739       case OpCode_BaseFontBlend:
740         env.clear_args ();
741         break;
742
743       case OpCode_CIDCount:
744         dictval.cidCount = env.argStack.pop_uint ();
745         env.clear_args ();
746         break;
747
748       case OpCode_ROS:
749         dictval.ros_supplement = env.argStack.pop_uint ();
750         dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
751         dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
752         env.clear_args ();
753         break;
754
755       case OpCode_Encoding:
756         dictval.EncodingOffset = env.argStack.pop_uint ();
757         env.clear_args ();
758         if (unlikely (dictval.EncodingOffset == 0)) return;
759         break;
760
761       case OpCode_charset:
762         dictval.CharsetOffset = env.argStack.pop_uint ();
763         env.clear_args ();
764         if (unlikely (dictval.CharsetOffset == 0)) return;
765         break;
766
767       case OpCode_FDSelect:
768         dictval.FDSelectOffset = env.argStack.pop_uint ();
769         env.clear_args ();
770         break;
771
772       case OpCode_Private:
773         dictval.privateDictInfo.offset = env.argStack.pop_uint ();
774         dictval.privateDictInfo.size = env.argStack.pop_uint ();
775         env.clear_args ();
776         break;
777
778       default:
779         env.last_offset = env.str_ref.offset;
780         top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
781         /* Record this operand below if stack is empty, otherwise done */
782         if (!env.argStack.is_empty ()) return;
783         break;
784     }
785
786     if (unlikely (env.in_error ())) return;
787
788     dictval.add_op (op, env.str_ref, val);
789   }
790 };
791
792 struct cff1_font_dict_values_t : dict_values_t<op_str_t>
793 {
794   void init ()
795   {
796     dict_values_t<op_str_t>::init ();
797     privateDictInfo.init ();
798     fontName = CFF_UNDEF_SID;
799   }
800   void fini () { dict_values_t<op_str_t>::fini (); }
801
802   table_info_t       privateDictInfo;
803   unsigned int    fontName;
804 };
805
806 struct cff1_font_dict_opset_t : dict_opset_t
807 {
808   static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
809   {
810     switch (op) {
811       case OpCode_FontName:
812         dictval.fontName = env.argStack.pop_uint ();
813         env.clear_args ();
814         break;
815       case OpCode_FontMatrix:
816       case OpCode_PaintType:
817         env.clear_args ();
818         break;
819       case OpCode_Private:
820         dictval.privateDictInfo.offset = env.argStack.pop_uint ();
821         dictval.privateDictInfo.size = env.argStack.pop_uint ();
822         env.clear_args ();
823         break;
824
825       default:
826         dict_opset_t::process_op (op, env);
827         if (!env.argStack.is_empty ()) return;
828         break;
829     }
830
831     if (unlikely (env.in_error ())) return;
832
833     dictval.add_op (op, env.str_ref);
834   }
835 };
836
837 template <typename VAL>
838 struct cff1_private_dict_values_base_t : dict_values_t<VAL>
839 {
840   void init ()
841   {
842     dict_values_t<VAL>::init ();
843     subrsOffset = 0;
844     localSubrs = &Null (CFF1Subrs);
845   }
846   void fini () { dict_values_t<VAL>::fini (); }
847
848   unsigned int      subrsOffset;
849   const CFF1Subrs    *localSubrs;
850 };
851
852 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
853 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
854
855 struct cff1_private_dict_opset_t : dict_opset_t
856 {
857   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
858   {
859     num_dict_val_t val;
860     val.init ();
861
862     switch (op) {
863       case OpCode_BlueValues:
864       case OpCode_OtherBlues:
865       case OpCode_FamilyBlues:
866       case OpCode_FamilyOtherBlues:
867       case OpCode_StemSnapH:
868       case OpCode_StemSnapV:
869         env.clear_args ();
870         break;
871       case OpCode_StdHW:
872       case OpCode_StdVW:
873       case OpCode_BlueScale:
874       case OpCode_BlueShift:
875       case OpCode_BlueFuzz:
876       case OpCode_ForceBold:
877       case OpCode_LanguageGroup:
878       case OpCode_ExpansionFactor:
879       case OpCode_initialRandomSeed:
880       case OpCode_defaultWidthX:
881       case OpCode_nominalWidthX:
882         val.single_val = env.argStack.pop_num ();
883         env.clear_args ();
884         break;
885       case OpCode_Subrs:
886         dictval.subrsOffset = env.argStack.pop_uint ();
887         env.clear_args ();
888         break;
889
890       default:
891         dict_opset_t::process_op (op, env);
892         if (!env.argStack.is_empty ()) return;
893         break;
894     }
895
896     if (unlikely (env.in_error ())) return;
897
898     dictval.add_op (op, env.str_ref, val);
899   }
900 };
901
902 struct cff1_private_dict_opset_subset : dict_opset_t
903 {
904   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
905   {
906     switch (op) {
907       case OpCode_BlueValues:
908       case OpCode_OtherBlues:
909       case OpCode_FamilyBlues:
910       case OpCode_FamilyOtherBlues:
911       case OpCode_StemSnapH:
912       case OpCode_StemSnapV:
913       case OpCode_StdHW:
914       case OpCode_StdVW:
915       case OpCode_BlueScale:
916       case OpCode_BlueShift:
917       case OpCode_BlueFuzz:
918       case OpCode_ForceBold:
919       case OpCode_LanguageGroup:
920       case OpCode_ExpansionFactor:
921       case OpCode_initialRandomSeed:
922       case OpCode_defaultWidthX:
923       case OpCode_nominalWidthX:
924         env.clear_args ();
925         break;
926
927       case OpCode_Subrs:
928         dictval.subrsOffset = env.argStack.pop_uint ();
929         env.clear_args ();
930         break;
931
932       default:
933         dict_opset_t::process_op (op, env);
934         if (!env.argStack.is_empty ()) return;
935         break;
936     }
937
938     if (unlikely (env.in_error ())) return;
939
940     dictval.add_op (op, env.str_ref);
941   }
942 };
943
944 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;
945 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
946
947 typedef CFF1Index CFF1NameIndex;
948 typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
949
950 struct cff1_font_dict_values_mod_t
951 {
952   cff1_font_dict_values_mod_t() { init (); }
953
954   void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
955
956   void init (const cff1_font_dict_values_t *base_,
957              unsigned int fontName_)
958   {
959     base = base_;
960     fontName = fontName_;
961     privateDictInfo.init ();
962   }
963
964   unsigned get_count () const { return base->get_count (); }
965
966   const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
967
968   const cff1_font_dict_values_t    *base;
969   table_info_t             privateDictInfo;
970   unsigned int          fontName;
971 };
972
973 struct CFF1FDArray : FDArray<HBUINT16>
974 {
975   /* FDArray::serialize() requires this partial specialization to compile */
976   template <typename ITER, typename OP_SERIALIZER>
977   bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
978   { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
979 };
980
981 } /* namespace CFF */
982
983 namespace OT {
984
985 using namespace CFF;
986
987 struct cff1
988 {
989   static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
990
991   bool sanitize (hb_sanitize_context_t *c) const
992   {
993     TRACE_SANITIZE (this);
994     return_trace (c->check_struct (this) &&
995                   likely (version.major == 1));
996   }
997
998   template <typename PRIVOPSET, typename PRIVDICTVAL>
999   struct accelerator_templ_t
1000   {
1001     void init (hb_face_t *face)
1002     {
1003       topDict.init ();
1004       fontDicts.init ();
1005       privateDicts.init ();
1006
1007       this->blob = sc.reference_table<cff1> (face);
1008
1009       /* setup for run-time santization */
1010       sc.init (this->blob);
1011       sc.start_processing ();
1012
1013       const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
1014
1015       if (cff == &Null (OT::cff1))
1016       { fini (); return; }
1017
1018       nameIndex = &cff->nameIndex (cff);
1019       if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
1020       { fini (); return; }
1021
1022       topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
1023       if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
1024       { fini (); return; }
1025
1026       { /* parse top dict */
1027         const byte_str_t topDictStr = (*topDictIndex)[0];
1028         if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
1029         cff1_top_dict_interpreter_t top_interp;
1030         top_interp.env.init (topDictStr);
1031         topDict.init ();
1032         if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
1033       }
1034
1035       if (is_predef_charset ())
1036         charset = &Null (Charset);
1037       else
1038       {
1039         charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
1040         if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
1041       }
1042
1043       fdCount = 1;
1044       if (is_CID ())
1045       {
1046         fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
1047         fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
1048         if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
1049             (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
1050         { fini (); return; }
1051
1052         fdCount = fdArray->count;
1053       }
1054       else
1055       {
1056         fdArray = &Null (CFF1FDArray);
1057         fdSelect = &Null (CFF1FDSelect);
1058       }
1059
1060       encoding = &Null (Encoding);
1061       if (is_CID ())
1062       {
1063         if (unlikely (charset == &Null (Charset))) { fini (); return; }
1064       }
1065       else
1066       {
1067         if (!is_predef_encoding ())
1068         {
1069           encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
1070           if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
1071         }
1072       }
1073
1074       stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
1075       if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
1076       { fini (); return; }
1077
1078       globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
1079       if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
1080       { fini (); return; }
1081
1082       charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
1083
1084       if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
1085       { fini (); return; }
1086
1087       num_glyphs = charStrings->count;
1088       if (num_glyphs != sc.get_num_glyphs ())
1089       { fini (); return; }
1090
1091       if (unlikely (!privateDicts.resize (fdCount)))
1092       { fini (); return; }
1093       for (unsigned int i = 0; i < fdCount; i++)
1094         privateDicts[i].init ();
1095
1096       // parse CID font dicts and gather private dicts
1097       if (is_CID ())
1098       {
1099         for (unsigned int i = 0; i < fdCount; i++)
1100         {
1101           byte_str_t fontDictStr = (*fdArray)[i];
1102           if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
1103           cff1_font_dict_values_t *font;
1104           cff1_font_dict_interpreter_t font_interp;
1105           font_interp.env.init (fontDictStr);
1106           font = fontDicts.push ();
1107           if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; }
1108           font->init ();
1109           if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
1110           PRIVDICTVAL *priv = &privateDicts[i];
1111           const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
1112           if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1113           dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1114           priv_interp.env.init (privDictStr);
1115           priv->init ();
1116           if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1117
1118           priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1119           if (priv->localSubrs != &Null (CFF1Subrs) &&
1120               unlikely (!priv->localSubrs->sanitize (&sc)))
1121           { fini (); return; }
1122         }
1123       }
1124       else  /* non-CID */
1125       {
1126         cff1_top_dict_values_t *font = &topDict;
1127         PRIVDICTVAL *priv = &privateDicts[0];
1128
1129         const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
1130         if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1131         dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1132         priv_interp.env.init (privDictStr);
1133         priv->init ();
1134         if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1135
1136         priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1137         if (priv->localSubrs != &Null (CFF1Subrs) &&
1138             unlikely (!priv->localSubrs->sanitize (&sc)))
1139         { fini (); return; }
1140       }
1141     }
1142
1143     void fini ()
1144     {
1145       sc.end_processing ();
1146       topDict.fini ();
1147       fontDicts.fini ();
1148       privateDicts.fini ();
1149       hb_blob_destroy (blob);
1150       blob = nullptr;
1151     }
1152
1153     bool is_valid () const { return blob; }
1154     bool   is_CID () const { return topDict.is_CID (); }
1155
1156     bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1157
1158     unsigned int std_code_to_glyph (hb_codepoint_t code) const
1159     {
1160       hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1161       if (unlikely (sid == CFF_UNDEF_SID))
1162         return 0;
1163
1164       if (charset != &Null (Charset))
1165         return charset->get_glyph (sid, num_glyphs);
1166       else if ((topDict.CharsetOffset == ISOAdobeCharset)
1167               && (code <= 228 /*zcaron*/)) return sid;
1168       return 0;
1169     }
1170
1171     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1172
1173     hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
1174     {
1175       if (encoding != &Null (Encoding))
1176         return encoding->get_code (glyph);
1177       else
1178       {
1179         hb_codepoint_t sid = glyph_to_sid (glyph);
1180         if (sid == 0) return 0;
1181         hb_codepoint_t code = 0;
1182         switch (topDict.EncodingOffset)
1183         {
1184         case StandardEncoding:
1185           code = lookup_standard_encoding_for_code (sid);
1186           break;
1187         case ExpertEncoding:
1188           code = lookup_expert_encoding_for_code (sid);
1189           break;
1190         default:
1191           break;
1192         }
1193         return code;
1194       }
1195     }
1196
1197     hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
1198     {
1199       if (charset != &Null (Charset))
1200         return charset->get_sid (glyph, num_glyphs);
1201       else
1202       {
1203         hb_codepoint_t sid = 0;
1204         switch (topDict.CharsetOffset)
1205         {
1206           case ISOAdobeCharset:
1207             if (glyph <= 228 /*zcaron*/) sid = glyph;
1208             break;
1209           case ExpertCharset:
1210             sid = lookup_expert_charset_for_sid (glyph);
1211             break;
1212           case ExpertSubsetCharset:
1213               sid = lookup_expert_subset_charset_for_sid (glyph);
1214             break;
1215           default:
1216             break;
1217         }
1218         return sid;
1219       }
1220     }
1221
1222     hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
1223     {
1224       if (charset != &Null (Charset))
1225         return charset->get_glyph (sid, num_glyphs);
1226       else
1227       {
1228         hb_codepoint_t glyph = 0;
1229         switch (topDict.CharsetOffset)
1230         {
1231           case ISOAdobeCharset:
1232             if (sid <= 228 /*zcaron*/) glyph = sid;
1233             break;
1234           case ExpertCharset:
1235             glyph = lookup_expert_charset_for_glyph (sid);
1236             break;
1237           case ExpertSubsetCharset:
1238             glyph = lookup_expert_subset_charset_for_glyph (sid);
1239             break;
1240           default:
1241             break;
1242         }
1243         return glyph;
1244       }
1245     }
1246
1247     protected:
1248     hb_blob_t              *blob = nullptr;
1249     hb_sanitize_context_t   sc;
1250
1251     public:
1252     const Encoding          *encoding = nullptr;
1253     const Charset           *charset = nullptr;
1254     const CFF1NameIndex     *nameIndex = nullptr;
1255     const CFF1TopDictIndex  *topDictIndex = nullptr;
1256     const CFF1StringIndex   *stringIndex = nullptr;
1257     const CFF1Subrs         *globalSubrs = nullptr;
1258     const CFF1CharStrings   *charStrings = nullptr;
1259     const CFF1FDArray       *fdArray = nullptr;
1260     const CFF1FDSelect      *fdSelect = nullptr;
1261     unsigned int             fdCount = 0;
1262
1263     cff1_top_dict_values_t   topDict;
1264     hb_vector_t<cff1_font_dict_values_t>
1265                              fontDicts;
1266     hb_vector_t<PRIVDICTVAL> privateDicts;
1267
1268     unsigned int             num_glyphs = 0;
1269   };
1270
1271   struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1272   {
1273     accelerator_t (hb_face_t *face)
1274     {
1275       SUPER::init (face);
1276
1277       if (!is_valid ()) return;
1278       if (is_CID ()) return;
1279
1280       /* fill glyph_names */
1281       for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
1282       {
1283         hb_codepoint_t  sid = glyph_to_sid (gid);
1284         gname_t gname;
1285         gname.sid = sid;
1286         if (sid < cff1_std_strings_length)
1287           gname.name = cff1_std_strings (sid);
1288         else
1289         {
1290           byte_str_t    ustr = (*stringIndex)[sid - cff1_std_strings_length];
1291           gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length);
1292         }
1293         if (unlikely (!gname.name.arrayZ)) { fini (); return; }
1294         glyph_names.push (gname);
1295       }
1296       glyph_names.qsort ();
1297     }
1298     ~accelerator_t ()
1299     {
1300       glyph_names.fini ();
1301
1302       SUPER::fini ();
1303     }
1304
1305     bool get_glyph_name (hb_codepoint_t glyph,
1306                          char *buf, unsigned int buf_len) const
1307     {
1308       if (!buf) return true;
1309       if (unlikely (!is_valid ())) return false;
1310       if (is_CID()) return false;
1311       hb_codepoint_t sid = glyph_to_sid (glyph);
1312       const char *str;
1313       size_t str_len;
1314       if (sid < cff1_std_strings_length)
1315       {
1316         hb_bytes_t byte_str = cff1_std_strings (sid);
1317         str = byte_str.arrayZ;
1318         str_len = byte_str.length;
1319       }
1320       else
1321       {
1322         byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
1323         str = (const char *)ubyte_str.arrayZ;
1324         str_len = ubyte_str.length;
1325       }
1326       if (!str_len) return false;
1327       unsigned int len = hb_min (buf_len - 1, str_len);
1328       strncpy (buf, (const char*)str, len);
1329       buf[len] = '\0';
1330       return true;
1331     }
1332
1333     bool get_glyph_from_name (const char *name, int len,
1334                               hb_codepoint_t *glyph) const
1335     {
1336       if (len < 0) len = strlen (name);
1337       if (unlikely (!len)) return false;
1338
1339       gname_t key = { hb_bytes_t (name, len), 0 };
1340       const gname_t *gname = glyph_names.bsearch (key);
1341       if (!gname) return false;
1342       hb_codepoint_t gid = sid_to_glyph (gname->sid);
1343       if (!gid && gname->sid) return false;
1344       *glyph = gid;
1345       return true;
1346     }
1347
1348     HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1349     HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
1350 #ifdef HB_EXPERIMENTAL_API
1351     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
1352 #endif
1353
1354     private:
1355     struct gname_t
1356     {
1357       hb_bytes_t        name;
1358       uint16_t          sid;
1359
1360       static int cmp (const void *a_, const void *b_)
1361       {
1362         const gname_t *a = (const gname_t *)a_;
1363         const gname_t *b = (const gname_t *)b_;
1364         int minlen = hb_min (a->name.length, b->name.length);
1365         int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
1366         if (ret) return ret;
1367         return a->name.length - b->name.length;
1368       }
1369
1370       int cmp (const gname_t &a) const { return cmp (&a, this); }
1371     };
1372
1373     hb_sorted_vector_t<gname_t> glyph_names;
1374
1375     typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
1376   };
1377
1378   struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {};
1379
1380   bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); }
1381
1382   protected:
1383   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
1384   HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
1385   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
1386   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
1387   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
1388   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
1389   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
1390
1391   public:
1392   FixedVersion<HBUINT8> version;          /* Version of CFF table. set to 0x0100u */
1393   NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
1394   HBUINT8              offSize;   /* offset size (unused?) */
1395
1396   public:
1397   DEFINE_SIZE_STATIC (4);
1398 };
1399
1400 struct cff1_accelerator_t : cff1::accelerator_t {
1401   cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
1402 };
1403
1404 } /* namespace OT */
1405
1406 #endif /* HB_OT_CFF1_TABLE_HH */