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_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 {
initCFF::cff1_font_dict_values_t794   void init ()
795   {
796     dict_values_t<op_str_t>::init ();
797     privateDictInfo.init ();
798     fontName = CFF_UNDEF_SID;
799   }
finiCFF::cff1_font_dict_values_t800   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 {
process_opCFF::cff1_font_dict_opset_t808   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 {
initCFF::cff1_private_dict_values_base_t840   void init ()
841   {
842     dict_values_t<VAL>::init ();
843     subrsOffset = 0;
844     localSubrs = &Null (CFF1Subrs);
845   }
finiCFF::cff1_private_dict_values_base_t846   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 {
process_opCFF::cff1_private_dict_opset_t857   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 {
process_opCFF::cff1_private_dict_opset_subset904   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 {
cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t952   cff1_font_dict_values_mod_t() { init (); }
953 
initCFF::cff1_font_dict_values_mod_t954   void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
955 
initCFF::cff1_font_dict_values_mod_t956   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 
get_countCFF::cff1_font_dict_values_mod_t964   unsigned get_count () const { return base->get_count (); }
965 
operator []CFF::cff1_font_dict_values_mod_t966   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>
serializeCFF::CFF1FDArray977   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 
sanitizeOT::cff1991   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   {
initOT::cff1::accelerator_templ_t1001     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 
finiOT::cff1::accelerator_templ_t1143     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 
is_validOT::cff1::accelerator_templ_t1153     bool is_valid () const { return blob; }
is_CIDOT::cff1::accelerator_templ_t1154     bool   is_CID () const { return topDict.is_CID (); }
1155 
is_predef_charsetOT::cff1::accelerator_templ_t1156     bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1157 
std_code_to_glyphOT::cff1::accelerator_templ_t1158     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 
is_predef_encodingOT::cff1::accelerator_templ_t1171     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1172 
glyph_to_codeOT::cff1::accelerator_templ_t1173     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 
glyph_to_sidOT::cff1::accelerator_templ_t1197     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 
sid_to_glyphOT::cff1::accelerator_templ_t1222     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   {
accelerator_tOT::cff1::accelerator_t1273     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     }
~accelerator_tOT::cff1::accelerator_t1298     ~accelerator_t ()
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 {
cff1_accelerator_tOT::cff1_accelerator_t1401   cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
1402 };
1403 
1404 } /* namespace OT */
1405 
1406 #endif /* HB_OT_CFF1_TABLE_HH */
1407