• 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 (codes.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 
nCodesCFF::Encoding077   HBUINT8 &nCodes () { return codes.len; }
nCodesCFF::Encoding078   HBUINT8 nCodes () const { return codes.len; }
79 
80   ArrayOf<HBUINT8, HBUINT8> codes;
81 
82   DEFINE_SIZE_ARRAY_SIZED (1, codes);
83 };
84 
85 struct Encoding1_Range {
sanitizeCFF::Encoding1_Range86   bool sanitize (hb_sanitize_context_t *c) const
87   {
88     TRACE_SANITIZE (this);
89     return_trace (c->check_struct (this));
90   }
91 
92   HBUINT8   first;
93   HBUINT8   nLeft;
94 
95   DEFINE_SIZE_STATIC (2);
96 };
97 
98 struct Encoding1 {
sanitizeCFF::Encoding199   bool sanitize (hb_sanitize_context_t *c) const
100   {
101     TRACE_SANITIZE (this);
102     return_trace (ranges.sanitize (c));
103   }
104 
get_codeCFF::Encoding1105   hb_codepoint_t get_code (hb_codepoint_t glyph) const
106   {
107     assert (glyph > 0);
108     glyph--;
109     for (unsigned int i = 0; i < nRanges (); i++)
110     {
111       if (glyph <= ranges[i].nLeft)
112       {
113 	hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
114 	return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
115       }
116       glyph -= (ranges[i].nLeft + 1);
117     }
118     return CFF_UNDEF_CODE;
119   }
120 
nRangesCFF::Encoding1121   HBUINT8 &nRanges () { return ranges.len; }
nRangesCFF::Encoding1122   HBUINT8 nRanges () const { return ranges.len; }
123 
124   ArrayOf<Encoding1_Range, HBUINT8> ranges;
125 
126   DEFINE_SIZE_ARRAY_SIZED (1, ranges);
127 };
128 
129 struct SuppEncoding {
sanitizeCFF::SuppEncoding130   bool sanitize (hb_sanitize_context_t *c) const
131   {
132     TRACE_SANITIZE (this);
133     return_trace (c->check_struct (this));
134   }
135 
136   HBUINT8   code;
137   HBUINT16  glyph;
138 
139   DEFINE_SIZE_STATIC (3);
140 };
141 
142 struct CFF1SuppEncData {
sanitizeCFF::CFF1SuppEncData143   bool sanitize (hb_sanitize_context_t *c) const
144   {
145     TRACE_SANITIZE (this);
146     return_trace (supps.sanitize (c));
147   }
148 
get_codesCFF::CFF1SuppEncData149   void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
150   {
151     for (unsigned int i = 0; i < nSups (); i++)
152       if (sid == supps[i].glyph)
153 	codes.push (supps[i].code);
154   }
155 
nSupsCFF::CFF1SuppEncData156   HBUINT8 &nSups () { return supps.len; }
nSupsCFF::CFF1SuppEncData157   HBUINT8 nSups () const { return supps.len; }
158 
159   ArrayOf<SuppEncoding, HBUINT8> supps;
160 
161   DEFINE_SIZE_ARRAY_SIZED (1, supps);
162 };
163 
164 struct Encoding
165 {
166   /* serialize a fullset Encoding */
serializeCFF::Encoding167   bool serialize (hb_serialize_context_t *c, const Encoding &src)
168   {
169     TRACE_SERIALIZE (this);
170     unsigned int size = src.get_size ();
171     Encoding *dest = c->allocate_size<Encoding> (size);
172     if (unlikely (dest == nullptr)) return_trace (false);
173     memcpy (dest, &src, size);
174     return_trace (true);
175   }
176 
177   /* serialize a subset Encoding */
serializeCFF::Encoding178   bool serialize (hb_serialize_context_t *c,
179 		  uint8_t format,
180 		  unsigned int enc_count,
181 		  const hb_vector_t<code_pair_t>& code_ranges,
182 		  const hb_vector_t<code_pair_t>& supp_codes)
183   {
184     TRACE_SERIALIZE (this);
185     Encoding *dest = c->extend_min (*this);
186     if (unlikely (dest == nullptr)) return_trace (false);
187     dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
188     switch (format) {
189     case 0:
190     {
191       Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
192       if (unlikely (fmt0 == nullptr)) return_trace (false);
193       fmt0->nCodes () = enc_count;
194       unsigned int glyph = 0;
195       for (unsigned int i = 0; i < code_ranges.length; i++)
196       {
197 	hb_codepoint_t code = code_ranges[i].code;
198 	for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
199 	  fmt0->codes[glyph++] = code++;
200 	if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
201 	  return_trace (false);
202       }
203     }
204     break;
205 
206     case 1:
207     {
208       Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
209       if (unlikely (fmt1 == nullptr)) return_trace (false);
210       fmt1->nRanges () = code_ranges.length;
211       for (unsigned int i = 0; i < code_ranges.length; i++)
212       {
213 	if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
214 	  return_trace (false);
215 	fmt1->ranges[i].first = code_ranges[i].code;
216 	fmt1->ranges[i].nLeft = code_ranges[i].glyph;
217       }
218     }
219     break;
220 
221     }
222 
223     if (supp_codes.length)
224     {
225       CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
226       if (unlikely (suppData == nullptr)) return_trace (false);
227       suppData->nSups () = supp_codes.length;
228       for (unsigned int i = 0; i < supp_codes.length; i++)
229       {
230 	suppData->supps[i].code = supp_codes[i].code;
231 	suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
232       }
233     }
234 
235     return_trace (true);
236   }
237 
238   /* parallel to above: calculate the size of a subset Encoding */
calculate_serialized_sizeCFF::Encoding239   static unsigned int calculate_serialized_size (uint8_t format,
240 						 unsigned int enc_count,
241 						 unsigned int supp_count)
242   {
243     unsigned int size = min_size;
244     switch (format)
245     {
246     case 0: size += Encoding0::min_size + HBUINT8::static_size * enc_count; break;
247     case 1: size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; break;
248     default:return 0;
249     }
250     if (supp_count > 0)
251       size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
252     return size;
253   }
254 
get_sizeCFF::Encoding255   unsigned int get_size () const
256   {
257     unsigned int size = min_size;
258     switch (table_format ())
259     {
260     case 0: size += u.format0.get_size (); break;
261     case 1: size += u.format1.get_size (); break;
262     }
263     if (has_supplement ())
264       size += suppEncData ().get_size ();
265     return size;
266   }
267 
get_codeCFF::Encoding268   hb_codepoint_t get_code (hb_codepoint_t glyph) const
269   {
270     switch (table_format ())
271     {
272     case 0: return u.format0.get_code (glyph);
273     case 1: return u.format1.get_code (glyph);
274     default:return 0;
275     }
276   }
277 
table_formatCFF::Encoding278   uint8_t table_format () const { return format & 0x7F; }
has_supplementCFF::Encoding279   bool  has_supplement () const { return format & 0x80; }
280 
get_supplement_codesCFF::Encoding281   void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
282   {
283     codes.resize (0);
284     if (has_supplement ())
285       suppEncData().get_codes (sid, codes);
286   }
287 
sanitizeCFF::Encoding288   bool sanitize (hb_sanitize_context_t *c) const
289   {
290     TRACE_SANITIZE (this);
291     if (unlikely (!c->check_struct (this)))
292       return_trace (false);
293 
294     switch (table_format ())
295     {
296     case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
297     case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
298     default:return_trace (false);
299     }
300     return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
301   }
302 
303   protected:
suppEncDataCFF::Encoding304   const CFF1SuppEncData &suppEncData () const
305   {
306     switch (table_format ())
307     {
308     case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
309     case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
310     default:return Null (CFF1SuppEncData);
311     }
312   }
313 
314   public:
315   HBUINT8	format;
316   union {
317   Encoding0	format0;
318   Encoding1	format1;
319   } u;
320   /* CFF1SuppEncData  suppEncData; */
321 
322   DEFINE_SIZE_MIN (1);
323 };
324 
325 /* Charset */
326 struct Charset0 {
sanitizeCFF::Charset0327   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
328   {
329     TRACE_SANITIZE (this);
330     return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
331   }
332 
get_sidCFF::Charset0333   hb_codepoint_t get_sid (hb_codepoint_t glyph) const
334   {
335     if (glyph == 0)
336       return 0;
337     else
338       return sids[glyph - 1];
339   }
340 
get_glyphCFF::Charset0341   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
342   {
343     if (sid == 0)
344       return 0;
345 
346     for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
347     {
348       if (sids[glyph-1] == sid)
349 	return glyph;
350     }
351     return 0;
352   }
353 
get_sizeCFF::Charset0354   unsigned int get_size (unsigned int num_glyphs) const
355   {
356     assert (num_glyphs > 0);
357     return HBUINT16::static_size * (num_glyphs - 1);
358   }
359 
360   HBUINT16  sids[HB_VAR_ARRAY];
361 
362   DEFINE_SIZE_ARRAY(0, sids);
363 };
364 
365 template <typename TYPE>
366 struct Charset_Range {
sanitizeCFF::Charset_Range367   bool sanitize (hb_sanitize_context_t *c) const
368   {
369     TRACE_SANITIZE (this);
370     return_trace (c->check_struct (this));
371   }
372 
373   HBUINT16  first;
374   TYPE      nLeft;
375 
376   DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
377 };
378 
379 template <typename TYPE>
380 struct Charset1_2 {
sanitizeCFF::Charset1_2381   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
382   {
383     TRACE_SANITIZE (this);
384     if (unlikely (!c->check_struct (this)))
385       return_trace (false);
386     num_glyphs--;
387     for (unsigned int i = 0; num_glyphs > 0; i++)
388     {
389       if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
390 	return_trace (false);
391       num_glyphs -= (ranges[i].nLeft + 1);
392     }
393     return_trace (true);
394   }
395 
get_sidCFF::Charset1_2396   hb_codepoint_t get_sid (hb_codepoint_t glyph) const
397   {
398     if (glyph == 0) return 0;
399     glyph--;
400     for (unsigned int i = 0;; i++)
401     {
402       if (glyph <= ranges[i].nLeft)
403 	return (hb_codepoint_t)ranges[i].first + glyph;
404       glyph -= (ranges[i].nLeft + 1);
405     }
406 
407     return 0;
408   }
409 
get_glyphCFF::Charset1_2410   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
411   {
412     if (sid == 0) return 0;
413     hb_codepoint_t  glyph = 1;
414     for (unsigned int i = 0;; i++)
415     {
416       if (glyph >= num_glyphs)
417       	return 0;
418       if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
419 	return glyph + (sid - ranges[i].first);
420       glyph += (ranges[i].nLeft + 1);
421     }
422 
423     return 0;
424   }
425 
get_sizeCFF::Charset1_2426   unsigned int get_size (unsigned int num_glyphs) const
427   {
428     unsigned int size = HBUINT8::static_size;
429     int glyph = (int)num_glyphs;
430 
431     assert (glyph > 0);
432     glyph--;
433     for (unsigned int i = 0; glyph > 0; i++)
434     {
435       glyph -= (ranges[i].nLeft + 1);
436       size += Charset_Range<TYPE>::static_size;
437     }
438 
439     return size;
440   }
441 
442   Charset_Range<TYPE>   ranges[HB_VAR_ARRAY];
443 
444   DEFINE_SIZE_ARRAY (0, ranges);
445 };
446 
447 typedef Charset1_2<HBUINT8>     Charset1;
448 typedef Charset1_2<HBUINT16>    Charset2;
449 typedef Charset_Range<HBUINT8>  Charset1_Range;
450 typedef Charset_Range<HBUINT16> Charset2_Range;
451 
452 struct Charset
453 {
454   /* serialize a fullset Charset */
serializeCFF::Charset455   bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
456   {
457     TRACE_SERIALIZE (this);
458     unsigned int size = src.get_size (num_glyphs);
459     Charset *dest = c->allocate_size<Charset> (size);
460     if (unlikely (dest == nullptr)) return_trace (false);
461     memcpy (dest, &src, size);
462     return_trace (true);
463   }
464 
465   /* serialize a subset Charset */
serializeCFF::Charset466   bool serialize (hb_serialize_context_t *c,
467 		  uint8_t format,
468 		  unsigned int num_glyphs,
469 		  const hb_vector_t<code_pair_t>& sid_ranges)
470   {
471     TRACE_SERIALIZE (this);
472     Charset *dest = c->extend_min (*this);
473     if (unlikely (dest == nullptr)) return_trace (false);
474     dest->format = format;
475     switch (format)
476     {
477     case 0:
478     {
479       Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
480       if (unlikely (fmt0 == nullptr)) return_trace (false);
481       unsigned int glyph = 0;
482       for (unsigned int i = 0; i < sid_ranges.length; i++)
483       {
484 	hb_codepoint_t sid = sid_ranges[i].code;
485 	for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
486 	  fmt0->sids[glyph++] = sid++;
487       }
488     }
489     break;
490 
491     case 1:
492     {
493       Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
494       if (unlikely (fmt1 == nullptr)) return_trace (false);
495       for (unsigned int i = 0; i < sid_ranges.length; i++)
496       {
497       	if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
498 	  return_trace (false);
499 	fmt1->ranges[i].first = sid_ranges[i].code;
500 	fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
501       }
502     }
503     break;
504 
505     case 2:
506     {
507       Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
508       if (unlikely (fmt2 == nullptr)) return_trace (false);
509       for (unsigned int i = 0; i < sid_ranges.length; i++)
510       {
511       	if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
512 	  return_trace (false);
513 	fmt2->ranges[i].first = sid_ranges[i].code;
514 	fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
515       }
516     }
517     break;
518 
519     }
520     return_trace (true);
521   }
522 
523   /* parallel to above: calculate the size of a subset Charset */
calculate_serialized_sizeCFF::Charset524   static unsigned int calculate_serialized_size (uint8_t format,
525 						 unsigned int count)
526   {
527     switch (format)
528     {
529     case 0: return min_size + Charset0::min_size + HBUINT16::static_size * (count - 1);
530     case 1: return min_size + Charset1::min_size + Charset1_Range::static_size * count;
531     case 2: return min_size + Charset2::min_size + Charset2_Range::static_size * count;
532     default:return 0;
533     }
534   }
535 
get_sizeCFF::Charset536   unsigned int get_size (unsigned int num_glyphs) const
537   {
538     switch (format)
539     {
540     case 0: return min_size + u.format0.get_size (num_glyphs);
541     case 1: return min_size + u.format1.get_size (num_glyphs);
542     case 2: return min_size + u.format2.get_size (num_glyphs);
543     default:return 0;
544     }
545   }
546 
get_sidCFF::Charset547   hb_codepoint_t get_sid (hb_codepoint_t glyph) const
548   {
549     switch (format)
550     {
551     case 0: return u.format0.get_sid (glyph);
552     case 1: return u.format1.get_sid (glyph);
553     case 2: return u.format2.get_sid (glyph);
554     default:return 0;
555     }
556   }
557 
get_glyphCFF::Charset558   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
559   {
560     switch (format)
561     {
562     case 0: return u.format0.get_glyph (sid, num_glyphs);
563     case 1: return u.format1.get_glyph (sid, num_glyphs);
564     case 2: return u.format2.get_glyph (sid, num_glyphs);
565     default:return 0;
566     }
567   }
568 
sanitizeCFF::Charset569   bool sanitize (hb_sanitize_context_t *c) const
570   {
571     TRACE_SANITIZE (this);
572     if (unlikely (!c->check_struct (this)))
573       return_trace (false);
574 
575     switch (format)
576     {
577     case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
578     case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
579     case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
580     default:return_trace (false);
581     }
582   }
583 
584   HBUINT8       format;
585   union {
586     Charset0    format0;
587     Charset1    format1;
588     Charset2    format2;
589   } u;
590 
591   DEFINE_SIZE_MIN (1);
592 };
593 
594 struct CFF1StringIndex : CFF1Index
595 {
serializeCFF::CFF1StringIndex596   bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
597 		  unsigned int offSize_, const hb_inc_bimap_t &sidmap)
598   {
599     TRACE_SERIALIZE (this);
600     if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
601     {
602       if (unlikely (!c->extend_min (this->count)))
603 	return_trace (false);
604       count = 0;
605       return_trace (true);
606     }
607 
608     byte_str_array_t bytesArray;
609     bytesArray.init ();
610     if (!bytesArray.resize (sidmap.get_population ()))
611       return_trace (false);
612     for (unsigned int i = 0; i < strings.count; i++)
613     {
614       hb_codepoint_t  j = sidmap[i];
615       if (j != CFF_UNDEF_CODE)
616 	bytesArray[j] = strings[i];
617     }
618 
619     bool result = CFF1Index::serialize (c, offSize_, bytesArray);
620     bytesArray.fini ();
621     return_trace (result);
622   }
623 
624   /* in parallel to above */
calculate_serialized_sizeCFF::CFF1StringIndex625   unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_inc_bimap_t &sidmap) const
626   {
627     offSize_ = 0;
628     if ((count == 0) || (sidmap.get_population () == 0))
629       return count.static_size;
630 
631     unsigned int dataSize = 0;
632     for (unsigned int i = 0; i < count; i++)
633       if (sidmap[i] != CFF_UNDEF_CODE)
634 	dataSize += length_at (i);
635 
636     offSize_ = calcOffSize(dataSize);
637     return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_population (), dataSize);
638   }
639 };
640 
641 struct cff1_top_dict_interp_env_t : num_interp_env_t
642 {
cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t643   cff1_top_dict_interp_env_t ()
644     : num_interp_env_t(), prev_offset(0), last_offset(0) {}
645 
646   unsigned int prev_offset;
647   unsigned int last_offset;
648 };
649 
650 struct name_dict_values_t
651 {
652   enum name_dict_val_index_t
653   {
654       version,
655       notice,
656       copyright,
657       fullName,
658       familyName,
659       weight,
660       postscript,
661       fontName,
662       baseFontName,
663       registry,
664       ordering,
665 
666       ValCount
667   };
668 
initCFF::name_dict_values_t669   void init ()
670   {
671     for (unsigned int i = 0; i < ValCount; i++)
672       values[i] = CFF_UNDEF_SID;
673   }
674 
operator []CFF::name_dict_values_t675   unsigned int& operator[] (unsigned int i)
676   { assert (i < ValCount); return values[i]; }
677 
operator []CFF::name_dict_values_t678   unsigned int operator[] (unsigned int i) const
679   { assert (i < ValCount); return values[i]; }
680 
name_op_to_indexCFF::name_dict_values_t681   static enum name_dict_val_index_t name_op_to_index (op_code_t op)
682   {
683     switch (op) {
684       default: // can't happen - just make some compiler happy
685       case OpCode_version:
686 	return version;
687       case OpCode_Notice:
688 	return notice;
689       case OpCode_Copyright:
690 	return copyright;
691       case OpCode_FullName:
692 	return fullName;
693       case OpCode_FamilyName:
694 	return familyName;
695       case OpCode_Weight:
696 	return weight;
697       case OpCode_PostScript:
698 	return postscript;
699       case OpCode_FontName:
700 	return fontName;
701       case OpCode_BaseFontName:
702 	return baseFontName;
703     }
704   }
705 
706   unsigned int  values[ValCount];
707 };
708 
709 struct cff1_top_dict_val_t : op_str_t
710 {
711   unsigned int  last_arg_offset;
712 };
713 
714 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
715 {
initCFF::cff1_top_dict_values_t716   void init ()
717   {
718     top_dict_values_t<cff1_top_dict_val_t>::init ();
719 
720     nameSIDs.init ();
721     ros_supplement = 0;
722     cidCount = 8720;
723     EncodingOffset = 0;
724     CharsetOffset = 0;
725     FDSelectOffset = 0;
726     privateDictInfo.init ();
727   }
finiCFF::cff1_top_dict_values_t728   void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
729 
is_CIDCFF::cff1_top_dict_values_t730   bool is_CID () const
731   { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
732 
733   name_dict_values_t  nameSIDs;
734   unsigned int    ros_supplement_offset;
735   unsigned int    ros_supplement;
736   unsigned int    cidCount;
737 
738   unsigned int    EncodingOffset;
739   unsigned int    CharsetOffset;
740   unsigned int    FDSelectOffset;
741   table_info_t       privateDictInfo;
742 };
743 
744 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
745 {
process_opCFF::cff1_top_dict_opset_t746   static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
747   {
748     cff1_top_dict_val_t  val;
749     val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
750 
751     switch (op) {
752       case OpCode_version:
753       case OpCode_Notice:
754       case OpCode_Copyright:
755       case OpCode_FullName:
756       case OpCode_FamilyName:
757       case OpCode_Weight:
758       case OpCode_PostScript:
759       case OpCode_BaseFontName:
760 	dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
761 	env.clear_args ();
762 	break;
763       case OpCode_isFixedPitch:
764       case OpCode_ItalicAngle:
765       case OpCode_UnderlinePosition:
766       case OpCode_UnderlineThickness:
767       case OpCode_PaintType:
768       case OpCode_CharstringType:
769       case OpCode_UniqueID:
770       case OpCode_StrokeWidth:
771       case OpCode_SyntheticBase:
772       case OpCode_CIDFontVersion:
773       case OpCode_CIDFontRevision:
774       case OpCode_CIDFontType:
775       case OpCode_UIDBase:
776       case OpCode_FontBBox:
777       case OpCode_XUID:
778       case OpCode_BaseFontBlend:
779 	env.clear_args ();
780 	break;
781 
782       case OpCode_CIDCount:
783 	dictval.cidCount = env.argStack.pop_uint ();
784 	env.clear_args ();
785 	break;
786 
787       case OpCode_ROS:
788 	dictval.ros_supplement = env.argStack.pop_uint ();
789 	dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
790 	dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
791 	env.clear_args ();
792 	break;
793 
794       case OpCode_Encoding:
795 	dictval.EncodingOffset = env.argStack.pop_uint ();
796 	env.clear_args ();
797 	if (unlikely (dictval.EncodingOffset == 0)) return;
798 	break;
799 
800       case OpCode_charset:
801 	dictval.CharsetOffset = env.argStack.pop_uint ();
802 	env.clear_args ();
803 	if (unlikely (dictval.CharsetOffset == 0)) return;
804 	break;
805 
806       case OpCode_FDSelect:
807 	dictval.FDSelectOffset = env.argStack.pop_uint ();
808 	env.clear_args ();
809 	break;
810 
811       case OpCode_Private:
812 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
813 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
814 	env.clear_args ();
815 	break;
816 
817       default:
818 	env.last_offset = env.str_ref.offset;
819 	top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
820 	/* Record this operand below if stack is empty, otherwise done */
821 	if (!env.argStack.is_empty ()) return;
822 	break;
823     }
824 
825     if (unlikely (env.in_error ())) return;
826 
827     dictval.add_op (op, env.str_ref, val);
828   }
829 };
830 
831 struct cff1_font_dict_values_t : dict_values_t<op_str_t>
832 {
initCFF::cff1_font_dict_values_t833   void init ()
834   {
835     dict_values_t<op_str_t>::init ();
836     privateDictInfo.init ();
837     fontName = CFF_UNDEF_SID;
838   }
finiCFF::cff1_font_dict_values_t839   void fini () { dict_values_t<op_str_t>::fini (); }
840 
841   table_info_t       privateDictInfo;
842   unsigned int    fontName;
843 };
844 
845 struct cff1_font_dict_opset_t : dict_opset_t
846 {
process_opCFF::cff1_font_dict_opset_t847   static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
848   {
849     switch (op) {
850       case OpCode_FontName:
851 	dictval.fontName = env.argStack.pop_uint ();
852 	env.clear_args ();
853 	break;
854       case OpCode_FontMatrix:
855       case OpCode_PaintType:
856 	env.clear_args ();
857 	break;
858       case OpCode_Private:
859 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
860 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
861 	env.clear_args ();
862 	break;
863 
864       default:
865 	dict_opset_t::process_op (op, env);
866 	if (!env.argStack.is_empty ()) return;
867 	break;
868     }
869 
870     if (unlikely (env.in_error ())) return;
871 
872     dictval.add_op (op, env.str_ref);
873   }
874 };
875 
876 template <typename VAL>
877 struct cff1_private_dict_values_base_t : dict_values_t<VAL>
878 {
initCFF::cff1_private_dict_values_base_t879   void init ()
880   {
881     dict_values_t<VAL>::init ();
882     subrsOffset = 0;
883     localSubrs = &Null(CFF1Subrs);
884   }
finiCFF::cff1_private_dict_values_base_t885   void fini () { dict_values_t<VAL>::fini (); }
886 
calculate_serialized_sizeCFF::cff1_private_dict_values_base_t887   unsigned int calculate_serialized_size () const
888   {
889     unsigned int size = 0;
890     for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
891       if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
892 	size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
893       else
894 	size += dict_values_t<VAL>::get_value (i).str.length;
895     return size;
896   }
897 
898   unsigned int      subrsOffset;
899   const CFF1Subrs    *localSubrs;
900 };
901 
902 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
903 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
904 
905 struct cff1_private_dict_opset_t : dict_opset_t
906 {
process_opCFF::cff1_private_dict_opset_t907   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
908   {
909     num_dict_val_t val;
910     val.init ();
911 
912     switch (op) {
913       case OpCode_BlueValues:
914       case OpCode_OtherBlues:
915       case OpCode_FamilyBlues:
916       case OpCode_FamilyOtherBlues:
917       case OpCode_StemSnapH:
918       case OpCode_StemSnapV:
919 	env.clear_args ();
920 	break;
921       case OpCode_StdHW:
922       case OpCode_StdVW:
923       case OpCode_BlueScale:
924       case OpCode_BlueShift:
925       case OpCode_BlueFuzz:
926       case OpCode_ForceBold:
927       case OpCode_LanguageGroup:
928       case OpCode_ExpansionFactor:
929       case OpCode_initialRandomSeed:
930       case OpCode_defaultWidthX:
931       case OpCode_nominalWidthX:
932 	val.single_val = env.argStack.pop_num ();
933 	env.clear_args ();
934 	break;
935       case OpCode_Subrs:
936 	dictval.subrsOffset = env.argStack.pop_uint ();
937 	env.clear_args ();
938 	break;
939 
940       default:
941 	dict_opset_t::process_op (op, env);
942 	if (!env.argStack.is_empty ()) return;
943 	break;
944     }
945 
946     if (unlikely (env.in_error ())) return;
947 
948     dictval.add_op (op, env.str_ref, val);
949   }
950 };
951 
952 struct cff1_private_dict_opset_subset : dict_opset_t
953 {
process_opCFF::cff1_private_dict_opset_subset954   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
955   {
956     switch (op) {
957       case OpCode_BlueValues:
958       case OpCode_OtherBlues:
959       case OpCode_FamilyBlues:
960       case OpCode_FamilyOtherBlues:
961       case OpCode_StemSnapH:
962       case OpCode_StemSnapV:
963       case OpCode_StdHW:
964       case OpCode_StdVW:
965       case OpCode_BlueScale:
966       case OpCode_BlueShift:
967       case OpCode_BlueFuzz:
968       case OpCode_ForceBold:
969       case OpCode_LanguageGroup:
970       case OpCode_ExpansionFactor:
971       case OpCode_initialRandomSeed:
972       case OpCode_defaultWidthX:
973       case OpCode_nominalWidthX:
974 	env.clear_args ();
975 	break;
976 
977       case OpCode_Subrs:
978 	dictval.subrsOffset = env.argStack.pop_uint ();
979 	env.clear_args ();
980 	break;
981 
982       default:
983 	dict_opset_t::process_op (op, env);
984 	if (!env.argStack.is_empty ()) return;
985 	break;
986     }
987 
988     if (unlikely (env.in_error ())) return;
989 
990     dictval.add_op (op, env.str_ref);
991   }
992 };
993 
994 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;
995 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
996 
997 typedef CFF1Index CFF1NameIndex;
998 typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
999 
1000 } /* namespace CFF */
1001 
1002 namespace OT {
1003 
1004 using namespace CFF;
1005 
1006 struct cff1
1007 {
1008   static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
1009 
sanitizeOT::cff11010   bool sanitize (hb_sanitize_context_t *c) const
1011   {
1012     TRACE_SANITIZE (this);
1013     return_trace (c->check_struct (this) &&
1014 		  likely (version.major == 1));
1015   }
1016 
1017   template <typename PRIVOPSET, typename PRIVDICTVAL>
1018   struct accelerator_templ_t
1019   {
initOT::cff1::accelerator_templ_t1020     void init (hb_face_t *face)
1021     {
1022       topDict.init ();
1023       fontDicts.init ();
1024       privateDicts.init ();
1025 
1026       this->blob = sc.reference_table<cff1> (face);
1027 
1028       /* setup for run-time santization */
1029       sc.init (this->blob);
1030       sc.start_processing ();
1031 
1032       const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
1033 
1034       if (cff == &Null(OT::cff1))
1035       { fini (); return; }
1036 
1037       nameIndex = &cff->nameIndex (cff);
1038       if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
1039       { fini (); return; }
1040 
1041       topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
1042       if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
1043       { fini (); return; }
1044 
1045       { /* parse top dict */
1046 	const byte_str_t topDictStr = (*topDictIndex)[0];
1047 	if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
1048 	cff1_top_dict_interpreter_t top_interp;
1049 	top_interp.env.init (topDictStr);
1050 	topDict.init ();
1051 	if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
1052       }
1053 
1054       if (is_predef_charset ())
1055 	charset = &Null(Charset);
1056       else
1057       {
1058 	charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
1059 	if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
1060       }
1061 
1062       fdCount = 1;
1063       if (is_CID ())
1064       {
1065 	fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
1066 	fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
1067 	if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
1068 	    (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
1069 	{ fini (); return; }
1070 
1071 	fdCount = fdArray->count;
1072       }
1073       else
1074       {
1075 	fdArray = &Null(CFF1FDArray);
1076 	fdSelect = &Null(CFF1FDSelect);
1077       }
1078 
1079       stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
1080       if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
1081       { fini (); return; }
1082 
1083       globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
1084       if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
1085       { fini (); return; }
1086 
1087       charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
1088 
1089       if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
1090       { fini (); return; }
1091 
1092       num_glyphs = charStrings->count;
1093       if (num_glyphs != sc.get_num_glyphs ())
1094       { fini (); return; }
1095 
1096       privateDicts.resize (fdCount);
1097       for (unsigned int i = 0; i < fdCount; i++)
1098 	privateDicts[i].init ();
1099 
1100       // parse CID font dicts and gather private dicts
1101       if (is_CID ())
1102       {
1103 	for (unsigned int i = 0; i < fdCount; i++)
1104 	{
1105 	  byte_str_t fontDictStr = (*fdArray)[i];
1106 	  if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
1107 	  cff1_font_dict_values_t  *font;
1108 	  cff1_font_dict_interpreter_t font_interp;
1109 	  font_interp.env.init (fontDictStr);
1110 	  font = fontDicts.push ();
1111 	  if (unlikely (font == &Crap(cff1_font_dict_values_t))) { fini (); return; }
1112 	  font->init ();
1113 	  if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
1114 	  PRIVDICTVAL  *priv = &privateDicts[i];
1115 	  const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
1116 	  if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1117 	  dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1118 	  priv_interp.env.init (privDictStr);
1119 	  priv->init ();
1120 	  if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1121 
1122 	  priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1123 	  if (priv->localSubrs != &Null(CFF1Subrs) &&
1124 	      unlikely (!priv->localSubrs->sanitize (&sc)))
1125 	  { fini (); return; }
1126 	}
1127       }
1128       else  /* non-CID */
1129       {
1130 	cff1_top_dict_values_t  *font = &topDict;
1131 	PRIVDICTVAL  *priv = &privateDicts[0];
1132 
1133 	const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
1134 	if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1135 	dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1136 	priv_interp.env.init (privDictStr);
1137 	priv->init ();
1138 	if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1139 
1140 	priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1141 	if (priv->localSubrs != &Null(CFF1Subrs) &&
1142 	    unlikely (!priv->localSubrs->sanitize (&sc)))
1143 	{ fini (); return; }
1144       }
1145     }
1146 
finiOT::cff1::accelerator_templ_t1147     void fini ()
1148     {
1149       sc.end_processing ();
1150       topDict.fini ();
1151       fontDicts.fini_deep ();
1152       privateDicts.fini_deep ();
1153       hb_blob_destroy (blob);
1154       blob = nullptr;
1155     }
1156 
is_validOT::cff1::accelerator_templ_t1157     bool is_valid () const { return blob != nullptr; }
is_CIDOT::cff1::accelerator_templ_t1158     bool   is_CID () const { return topDict.is_CID (); }
1159 
is_predef_charsetOT::cff1::accelerator_templ_t1160     bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1161 
std_code_to_glyphOT::cff1::accelerator_templ_t1162     unsigned int std_code_to_glyph (hb_codepoint_t code) const
1163     {
1164       hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1165       if (unlikely (sid == CFF_UNDEF_SID))
1166 	return 0;
1167 
1168       if (charset != &Null(Charset))
1169 	return charset->get_glyph (sid, num_glyphs);
1170       else if ((topDict.CharsetOffset == ISOAdobeCharset)
1171 	      && (code <= 228 /*zcaron*/)) return sid;
1172       return 0;
1173     }
1174 
1175     protected:
1176     hb_blob_t	       *blob;
1177     hb_sanitize_context_t   sc;
1178 
1179     public:
1180     const Charset	   *charset;
1181     const CFF1NameIndex     *nameIndex;
1182     const CFF1TopDictIndex  *topDictIndex;
1183     const CFF1StringIndex   *stringIndex;
1184     const CFF1Subrs	 *globalSubrs;
1185     const CFF1CharStrings   *charStrings;
1186     const CFF1FDArray       *fdArray;
1187     const CFF1FDSelect      *fdSelect;
1188     unsigned int	    fdCount;
1189 
1190     cff1_top_dict_values_t       topDict;
1191     hb_vector_t<cff1_font_dict_values_t>   fontDicts;
1192     hb_vector_t<PRIVDICTVAL>	  privateDicts;
1193 
1194     unsigned int	    num_glyphs;
1195   };
1196 
1197   struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1198   {
1199     HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1200     HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
1201   };
1202 
1203   struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t>
1204   {
initOT::cff1::accelerator_subset_t1205     void init (hb_face_t *face)
1206     {
1207       SUPER::init (face);
1208       if (blob == nullptr) return;
1209 
1210       const OT::cff1 *cff = this->blob->as<OT::cff1> ();
1211       encoding = &Null(Encoding);
1212       if (is_CID ())
1213       {
1214 	if (unlikely (charset == &Null(Charset))) { fini (); return; }
1215       }
1216       else
1217       {
1218 	if (!is_predef_encoding ())
1219 	{
1220 	  encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
1221 	  if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
1222 	}
1223       }
1224     }
1225 
is_predef_encodingOT::cff1::accelerator_subset_t1226     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1227 
glyph_to_codeOT::cff1::accelerator_subset_t1228     hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
1229     {
1230       if (encoding != &Null(Encoding))
1231 	return encoding->get_code (glyph);
1232       else
1233       {
1234 	hb_codepoint_t sid = glyph_to_sid (glyph);
1235 	if (sid == 0) return 0;
1236 	hb_codepoint_t code = 0;
1237 	switch (topDict.EncodingOffset)
1238 	{
1239 	case StandardEncoding:
1240 	  code = lookup_standard_encoding_for_code (sid);
1241 	  break;
1242 	case ExpertEncoding:
1243 	  code = lookup_expert_encoding_for_code (sid);
1244 	  break;
1245 	default:
1246 	  break;
1247 	}
1248 	return code;
1249       }
1250     }
1251 
glyph_to_sidOT::cff1::accelerator_subset_t1252     hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
1253     {
1254       if (charset != &Null(Charset))
1255 	return charset->get_sid (glyph);
1256       else
1257       {
1258 	hb_codepoint_t sid = 0;
1259 	switch (topDict.CharsetOffset)
1260 	{
1261 	  case  ISOAdobeCharset:
1262 	    if (glyph <= 228 /*zcaron*/) sid = glyph;
1263 	    break;
1264 	  case  ExpertCharset:
1265 	    sid = lookup_expert_charset_for_sid (glyph);
1266 	    break;
1267 	  case  ExpertSubsetCharset:
1268 	      sid = lookup_expert_subset_charset_for_sid (glyph);
1269 	    break;
1270 	  default:
1271 	    break;
1272 	}
1273 	return sid;
1274       }
1275     }
1276 
1277     const Encoding	  *encoding;
1278 
1279     private:
1280     typedef accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> SUPER;
1281   };
1282 
subsetOT::cff11283   bool subset (hb_subset_plan_t *plan) const
1284   {
1285     hb_blob_t *cff_prime = nullptr;
1286 
1287     bool success = true;
1288     if (hb_subset_cff1 (plan, &cff_prime)) {
1289       success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime);
1290       hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
1291       success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
1292       hb_blob_destroy (head_blob);
1293     } else {
1294       success = false;
1295     }
1296     hb_blob_destroy (cff_prime);
1297 
1298     return success;
1299   }
1300 
1301   protected:
1302   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
1303   HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
1304   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
1305   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
1306   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
1307 
1308   public:
1309   FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
1310   OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
1311   HBUINT8	       offSize;	  /* offset size (unused?) */
1312 
1313   public:
1314   DEFINE_SIZE_STATIC (4);
1315 };
1316 
1317 struct cff1_accelerator_t : cff1::accelerator_t {};
1318 } /* namespace OT */
1319 
1320 #endif /* HB_OT_CFF1_TABLE_HH */
1321