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