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 {
sanitizeCFF::Encoding064   bool sanitize (hb_sanitize_context_t *c) const
65   {
66     TRACE_SANITIZE (this);
67     return_trace (codes.sanitize (c));
68   }
69 
get_codeCFF::Encoding070   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 
nCodesCFF::Encoding082   HBUINT8 &nCodes () { return codes.len; }
nCodesCFF::Encoding083   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 {
sanitizeCFF::Encoding1_Range91   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 {
sanitizeCFF::Encoding1104   bool sanitize (hb_sanitize_context_t *c) const
105   {
106     TRACE_SANITIZE (this);
107     return_trace (ranges.sanitize (c));
108   }
109 
get_codeCFF::Encoding1110   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 
nRangesCFF::Encoding1126   HBUINT8 &nRanges () { return ranges.len; }
nRangesCFF::Encoding1127   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 {
sanitizeCFF::SuppEncoding135   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 {
sanitizeCFF::CFF1SuppEncData148   bool sanitize (hb_sanitize_context_t *c) const
149   {
150     TRACE_SANITIZE (this);
151     return_trace (supps.sanitize (c));
152   }
153 
get_codesCFF::CFF1SuppEncData154   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 
nSupsCFF::CFF1SuppEncData161   HBUINT8 &nSups () { return supps.len; }
nSupsCFF::CFF1SuppEncData162   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 */
serializeCFF::Encoding172   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 */
serializeCFF::Encoding183   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 
get_sizeCFF::Encoding243   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 
get_codeCFF::Encoding256   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 
table_formatCFF::Encoding266   uint8_t table_format () const { return format & 0x7F; }
has_supplementCFF::Encoding267   bool  has_supplement () const { return format & 0x80; }
268 
get_supplement_codesCFF::Encoding269   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 
sanitizeCFF::Encoding276   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:
suppEncDataCFF::Encoding292   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 {
sanitizeCFF::Charset0315   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 
get_sidCFF::Charset0321   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 
get_glyphCFF::Charset0329   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 
get_sizeCFF::Charset0342   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 {
sanitizeCFF::Charset_Range355   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 {
sanitizeCFF::Charset1_2369   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 
get_sidCFF::Charset1_2384   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 
get_glyphCFF::Charset1_2398   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 
get_sizeCFF::Charset1_2414   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 */
serializeCFF::Charset443   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 */
serializeCFF::Charset454   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 
get_sizeCFF::Charset511   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 
get_sidCFF::Charset522   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 
get_glyphCFF::Charset534   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 
sanitizeCFF::Charset545   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 {
serializeCFF::CFF1StringIndex572   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 {
cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t603   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 
initCFF::name_dict_values_t629   void init ()
630   {
631     for (unsigned int i = 0; i < ValCount; i++)
632       values[i] = CFF_UNDEF_SID;
633   }
634 
operator []CFF::name_dict_values_t635   unsigned int& operator[] (unsigned int i)
636   { assert (i < ValCount); return values[i]; }
637 
operator []CFF::name_dict_values_t638   unsigned int operator[] (unsigned int i) const
639   { assert (i < ValCount); return values[i]; }
640 
name_op_to_indexCFF::name_dict_values_t641   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 {
initCFF::cff1_top_dict_values_t676   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   }
finiCFF::cff1_top_dict_values_t688   void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
689 
is_CIDCFF::cff1_top_dict_values_t690   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 {
process_opCFF::cff1_top_dict_opset_t706   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 {
initCFF::cff1_font_dict_values_t793   void init ()
794   {
795     dict_values_t<op_str_t>::init ();
796     privateDictInfo.init ();
797     fontName = CFF_UNDEF_SID;
798   }
finiCFF::cff1_font_dict_values_t799   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 {
process_opCFF::cff1_font_dict_opset_t807   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 {
initCFF::cff1_private_dict_values_base_t839   void init ()
840   {
841     dict_values_t<VAL>::init ();
842     subrsOffset = 0;
843     localSubrs = &Null (CFF1Subrs);
844   }
finiCFF::cff1_private_dict_values_base_t845   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 {
process_opCFF::cff1_private_dict_opset_t856   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 {
process_opCFF::cff1_private_dict_opset_subset903   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 {
cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t951   cff1_font_dict_values_mod_t() { init (); }
952 
initCFF::cff1_font_dict_values_mod_t953   void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
954 
initCFF::cff1_font_dict_values_mod_t955   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 
get_countCFF::cff1_font_dict_values_mod_t963   unsigned get_count () const { return base->get_count (); }
964 
operator []CFF::cff1_font_dict_values_mod_t965   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>
serializeCFF::CFF1FDArray976   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 
sanitizeOT::cff1990   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   {
initOT::cff1::accelerator_templ_t1000     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       if (unlikely (!privateDicts.resize (fdCount)))
1091       { fini (); return; }
1092       for (unsigned int i = 0; i < fdCount; i++)
1093 	privateDicts[i].init ();
1094 
1095       // parse CID font dicts and gather private dicts
1096       if (is_CID ())
1097       {
1098 	for (unsigned int i = 0; i < fdCount; i++)
1099 	{
1100 	  byte_str_t fontDictStr = (*fdArray)[i];
1101 	  if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
1102 	  cff1_font_dict_values_t *font;
1103 	  cff1_font_dict_interpreter_t font_interp;
1104 	  font_interp.env.init (fontDictStr);
1105 	  font = fontDicts.push ();
1106 	  if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; }
1107 	  font->init ();
1108 	  if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
1109 	  PRIVDICTVAL *priv = &privateDicts[i];
1110 	  const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
1111 	  if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1112 	  dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1113 	  priv_interp.env.init (privDictStr);
1114 	  priv->init ();
1115 	  if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1116 
1117 	  priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1118 	  if (priv->localSubrs != &Null (CFF1Subrs) &&
1119 	      unlikely (!priv->localSubrs->sanitize (&sc)))
1120 	  { fini (); return; }
1121 	}
1122       }
1123       else  /* non-CID */
1124       {
1125 	cff1_top_dict_values_t *font = &topDict;
1126 	PRIVDICTVAL *priv = &privateDicts[0];
1127 
1128 	const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
1129 	if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1130 	dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1131 	priv_interp.env.init (privDictStr);
1132 	priv->init ();
1133 	if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1134 
1135 	priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1136 	if (priv->localSubrs != &Null (CFF1Subrs) &&
1137 	    unlikely (!priv->localSubrs->sanitize (&sc)))
1138 	{ fini (); return; }
1139       }
1140     }
1141 
finiOT::cff1::accelerator_templ_t1142     void fini ()
1143     {
1144       sc.end_processing ();
1145       topDict.fini ();
1146       fontDicts.fini_deep ();
1147       privateDicts.fini_deep ();
1148       hb_blob_destroy (blob);
1149       blob = nullptr;
1150     }
1151 
is_validOT::cff1::accelerator_templ_t1152     bool is_valid () const { return blob; }
is_CIDOT::cff1::accelerator_templ_t1153     bool   is_CID () const { return topDict.is_CID (); }
1154 
is_predef_charsetOT::cff1::accelerator_templ_t1155     bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1156 
std_code_to_glyphOT::cff1::accelerator_templ_t1157     unsigned int std_code_to_glyph (hb_codepoint_t code) const
1158     {
1159       hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1160       if (unlikely (sid == CFF_UNDEF_SID))
1161 	return 0;
1162 
1163       if (charset != &Null (Charset))
1164 	return charset->get_glyph (sid, num_glyphs);
1165       else if ((topDict.CharsetOffset == ISOAdobeCharset)
1166 	      && (code <= 228 /*zcaron*/)) return sid;
1167       return 0;
1168     }
1169 
is_predef_encodingOT::cff1::accelerator_templ_t1170     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1171 
glyph_to_codeOT::cff1::accelerator_templ_t1172     hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
1173     {
1174       if (encoding != &Null (Encoding))
1175 	return encoding->get_code (glyph);
1176       else
1177       {
1178 	hb_codepoint_t sid = glyph_to_sid (glyph);
1179 	if (sid == 0) return 0;
1180 	hb_codepoint_t code = 0;
1181 	switch (topDict.EncodingOffset)
1182 	{
1183 	case StandardEncoding:
1184 	  code = lookup_standard_encoding_for_code (sid);
1185 	  break;
1186 	case ExpertEncoding:
1187 	  code = lookup_expert_encoding_for_code (sid);
1188 	  break;
1189 	default:
1190 	  break;
1191 	}
1192 	return code;
1193       }
1194     }
1195 
glyph_to_sidOT::cff1::accelerator_templ_t1196     hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
1197     {
1198       if (charset != &Null (Charset))
1199 	return charset->get_sid (glyph, num_glyphs);
1200       else
1201       {
1202 	hb_codepoint_t sid = 0;
1203 	switch (topDict.CharsetOffset)
1204 	{
1205 	  case ISOAdobeCharset:
1206 	    if (glyph <= 228 /*zcaron*/) sid = glyph;
1207 	    break;
1208 	  case ExpertCharset:
1209 	    sid = lookup_expert_charset_for_sid (glyph);
1210 	    break;
1211 	  case ExpertSubsetCharset:
1212 	      sid = lookup_expert_subset_charset_for_sid (glyph);
1213 	    break;
1214 	  default:
1215 	    break;
1216 	}
1217 	return sid;
1218       }
1219     }
1220 
sid_to_glyphOT::cff1::accelerator_templ_t1221     hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
1222     {
1223       if (charset != &Null (Charset))
1224 	return charset->get_glyph (sid, num_glyphs);
1225       else
1226       {
1227 	hb_codepoint_t glyph = 0;
1228 	switch (topDict.CharsetOffset)
1229 	{
1230 	  case ISOAdobeCharset:
1231 	    if (sid <= 228 /*zcaron*/) glyph = sid;
1232 	    break;
1233 	  case ExpertCharset:
1234 	    glyph = lookup_expert_charset_for_glyph (sid);
1235 	    break;
1236 	  case ExpertSubsetCharset:
1237 	    glyph = lookup_expert_subset_charset_for_glyph (sid);
1238 	    break;
1239 	  default:
1240 	    break;
1241 	}
1242 	return glyph;
1243       }
1244     }
1245 
1246     protected:
1247     hb_blob_t	           *blob;
1248     hb_sanitize_context_t   sc;
1249 
1250     public:
1251     const Encoding	    *encoding;
1252     const Charset	    *charset;
1253     const CFF1NameIndex     *nameIndex;
1254     const CFF1TopDictIndex  *topDictIndex;
1255     const CFF1StringIndex   *stringIndex;
1256     const CFF1Subrs	    *globalSubrs;
1257     const CFF1CharStrings   *charStrings;
1258     const CFF1FDArray       *fdArray;
1259     const CFF1FDSelect      *fdSelect;
1260     unsigned int	     fdCount;
1261 
1262     cff1_top_dict_values_t   topDict;
1263     hb_vector_t<cff1_font_dict_values_t>
1264 			     fontDicts;
1265     hb_vector_t<PRIVDICTVAL> privateDicts;
1266 
1267     unsigned int	     num_glyphs;
1268   };
1269 
1270   struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1271   {
initOT::cff1::accelerator_t1272     void init (hb_face_t *face)
1273     {
1274       SUPER::init (face);
1275 
1276       if (!is_valid ()) return;
1277       if (is_CID ()) return;
1278 
1279       /* fill glyph_names */
1280       for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
1281       {
1282 	hb_codepoint_t	sid = glyph_to_sid (gid);
1283 	gname_t	gname;
1284 	gname.sid = sid;
1285 	if (sid < cff1_std_strings_length)
1286 	  gname.name = cff1_std_strings (sid);
1287 	else
1288 	{
1289 	  byte_str_t	ustr = (*stringIndex)[sid - cff1_std_strings_length];
1290 	  gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length);
1291 	}
1292 	if (unlikely (!gname.name.arrayZ)) { fini (); return; }
1293 	glyph_names.push (gname);
1294       }
1295       glyph_names.qsort ();
1296     }
1297 
finiOT::cff1::accelerator_t1298     void fini ()
1299     {
1300       glyph_names.fini ();
1301 
1302       SUPER::fini ();
1303     }
1304 
get_glyph_nameOT::cff1::accelerator_t1305     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 
get_glyph_from_nameOT::cff1::accelerator_t1333     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 
cmpOT::cff1::accelerator_t::gname_t1360       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 
cmpOT::cff1::accelerator_t::gname_t1370       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 
subsetOT::cff11380   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 } /* namespace OT */
1402 
1403 #endif /* HB_OT_CFF1_TABLE_HH */
1404