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