1 /*
2  * Copyright © 2018 Adobe Inc.
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
6  * Permission is hereby granted, without written agreement and without
7  * license or royalty fees, to use, copy, modify, and distribute this
8  * software and its documentation for any purpose, provided that the
9  * above copyright notice and the following two paragraphs appear in
10  * all copies of this software.
11  *
12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16  * DAMAGE.
17  *
18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  *
24  * Adobe Author(s): Michiharu Ariza
25  */
26 
27 #ifndef HB_OT_CFF1_TABLE_HH
28 #define HB_OT_CFF1_TABLE_HH
29 
30 #include "hb-ot-cff-common.hh"
31 
32 #define HB_STRING_ARRAY_NAME cff1_std_strings
33 #define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh"
34 #include "hb-string-array.hh"
35 #undef HB_STRING_ARRAY_LIST
36 #undef HB_STRING_ARRAY_NAME
37 
38 namespace CFF {
39 
40 /*
41  * CFF -- Compact Font Format (CFF)
42  * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
43  */
44 #define HB_OT_TAG_cff1 HB_TAG('C', 'F', 'F', ' ')
45 
46 #define CFF_UNDEF_SID CFF_UNDEF_CODE
47 
48 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
49 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
50 
51 typedef CFFIndex<HBUINT16> CFF1Index;
52 template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type>
53 {
54 };
55 
56 typedef CFFIndex<HBUINT16> CFF1Index;
57 typedef CFF1Index CFF1CharStrings;
58 typedef Subrs<HBUINT16> CFF1Subrs;
59 
60 struct CFF1FDSelect : FDSelect
61 {
62 };
63 
64 /* Encoding */
65 struct Encoding0
66 {
sanitizeCFF::Encoding067     bool sanitize(hb_sanitize_context_t *c) const
68     {
69         TRACE_SANITIZE(this);
70         return_trace(codes.sanitize(c));
71     }
72 
get_codeCFF::Encoding073     hb_codepoint_t get_code(hb_codepoint_t glyph) const
74     {
75         assert(glyph > 0);
76         glyph--;
77         if (glyph < nCodes()) {
78             return (hb_codepoint_t)codes[glyph];
79         } else
80             return CFF_UNDEF_CODE;
81     }
82 
nCodesCFF::Encoding083     HBUINT8 &nCodes()
84     {
85         return codes.len;
86     }
nCodesCFF::Encoding087     HBUINT8 nCodes() const
88     {
89         return codes.len;
90     }
91 
92     ArrayOf<HBUINT8, HBUINT8> codes;
93 
94     DEFINE_SIZE_ARRAY_SIZED(1, codes);
95 };
96 
97 struct Encoding1_Range
98 {
sanitizeCFF::Encoding1_Range99     bool sanitize(hb_sanitize_context_t *c) const
100     {
101         TRACE_SANITIZE(this);
102         return_trace(c->check_struct(this));
103     }
104 
105     HBUINT8 first;
106     HBUINT8 nLeft;
107 
108     DEFINE_SIZE_STATIC(2);
109 };
110 
111 struct Encoding1
112 {
sanitizeCFF::Encoding1113     bool sanitize(hb_sanitize_context_t *c) const
114     {
115         TRACE_SANITIZE(this);
116         return_trace(ranges.sanitize(c));
117     }
118 
get_codeCFF::Encoding1119     hb_codepoint_t get_code(hb_codepoint_t glyph) const
120     {
121         assert(glyph > 0);
122         glyph--;
123         for (unsigned int i = 0; i < nRanges(); i++) {
124             if (glyph <= ranges[i].nLeft) {
125                 hb_codepoint_t code = (hb_codepoint_t)ranges[i].first + glyph;
126                 return (likely(code < 0x100) ? code : CFF_UNDEF_CODE);
127             }
128             glyph -= (ranges[i].nLeft + 1);
129         }
130         return CFF_UNDEF_CODE;
131     }
132 
nRangesCFF::Encoding1133     HBUINT8 &nRanges()
134     {
135         return ranges.len;
136     }
nRangesCFF::Encoding1137     HBUINT8 nRanges() const
138     {
139         return ranges.len;
140     }
141 
142     ArrayOf<Encoding1_Range, HBUINT8> ranges;
143 
144     DEFINE_SIZE_ARRAY_SIZED(1, ranges);
145 };
146 
147 struct SuppEncoding
148 {
sanitizeCFF::SuppEncoding149     bool sanitize(hb_sanitize_context_t *c) const
150     {
151         TRACE_SANITIZE(this);
152         return_trace(c->check_struct(this));
153     }
154 
155     HBUINT8 code;
156     HBUINT16 glyph;
157 
158     DEFINE_SIZE_STATIC(3);
159 };
160 
161 struct CFF1SuppEncData
162 {
sanitizeCFF::CFF1SuppEncData163     bool sanitize(hb_sanitize_context_t *c) const
164     {
165         TRACE_SANITIZE(this);
166         return_trace(supps.sanitize(c));
167     }
168 
get_codesCFF::CFF1SuppEncData169     void get_codes(hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
170     {
171         for (unsigned int i = 0; i < nSups(); i++)
172             if (sid == supps[i].glyph)
173                 codes.push(supps[i].code);
174     }
175 
nSupsCFF::CFF1SuppEncData176     HBUINT8 &nSups()
177     {
178         return supps.len;
179     }
nSupsCFF::CFF1SuppEncData180     HBUINT8 nSups() const
181     {
182         return supps.len;
183     }
184 
185     ArrayOf<SuppEncoding, HBUINT8> supps;
186 
187     DEFINE_SIZE_ARRAY_SIZED(1, supps);
188 };
189 
190 struct Encoding
191 {
get_sizeCFF::Encoding192     unsigned int get_size() const
193     {
194         unsigned int size = min_size;
195         switch (table_format()) {
196         case 0:
197             size += u.format0.get_size();
198             break;
199         case 1:
200             size += u.format1.get_size();
201             break;
202         }
203         if (has_supplement())
204             size += suppEncData().get_size();
205         return size;
206     }
207 
get_codeCFF::Encoding208     hb_codepoint_t get_code(hb_codepoint_t glyph) const
209     {
210         switch (table_format()) {
211         case 0:
212             return u.format0.get_code(glyph);
213         case 1:
214             return u.format1.get_code(glyph);
215         default:
216             return 0;
217         }
218     }
219 
table_formatCFF::Encoding220     uint8_t table_format() const
221     {
222         return format & 0x7F;
223     }
has_supplementCFF::Encoding224     bool has_supplement() const
225     {
226         return format & 0x80;
227     }
228 
get_supplement_codesCFF::Encoding229     void get_supplement_codes(hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
230     {
231         codes.resize(0);
232         if (has_supplement())
233             suppEncData().get_codes(sid, codes);
234     }
235 
sanitizeCFF::Encoding236     bool sanitize(hb_sanitize_context_t *c) const
237     {
238         TRACE_SANITIZE(this);
239         if (unlikely(!c->check_struct(this)))
240             return_trace(false);
241 
242         switch (table_format()) {
243         case 0:
244             if (unlikely(!u.format0.sanitize(c))) {
245                 return_trace(false);
246             }
247             break;
248         case 1:
249             if (unlikely(!u.format1.sanitize(c))) {
250                 return_trace(false);
251             }
252             break;
253         default:
254             return_trace(false);
255         }
256         return_trace(likely(!has_supplement() || suppEncData().sanitize(c)));
257     }
258 
259 protected:
suppEncDataCFF::Encoding260     const CFF1SuppEncData &suppEncData() const
261     {
262         switch (table_format()) {
263         case 0:
264             return StructAfter<CFF1SuppEncData>(u.format0.codes[u.format0.nCodes() - 1]);
265         case 1:
266             return StructAfter<CFF1SuppEncData>(u.format1.ranges[u.format1.nRanges() - 1]);
267         default:
268             return Null(CFF1SuppEncData);
269         }
270     }
271 
272 public:
273     HBUINT8 format;
274     union {
275         Encoding0 format0;
276         Encoding1 format1;
277     } u;
278     /* CFF1SuppEncData  suppEncData; */
279 
280     DEFINE_SIZE_MIN(1);
281 };
282 
283 /* Charset */
284 struct Charset0
285 {
sanitizeCFF::Charset0286     bool sanitize(hb_sanitize_context_t *c, unsigned int num_glyphs) const
287     {
288         TRACE_SANITIZE(this);
289         return_trace(c->check_struct(this) && sids[num_glyphs - 1].sanitize(c));
290     }
291 
get_sidCFF::Charset0292     hb_codepoint_t get_sid(hb_codepoint_t glyph) const
293     {
294         if (glyph == 0)
295             return 0;
296         else
297             return sids[glyph - 1];
298     }
299 
get_glyphCFF::Charset0300     hb_codepoint_t get_glyph(hb_codepoint_t sid, unsigned int num_glyphs) const
301     {
302         if (sid == 0)
303             return 0;
304 
305         for (unsigned int glyph = 1; glyph < num_glyphs; glyph++) {
306             if (sids[glyph - 1] == sid)
307                 return glyph;
308         }
309         return 0;
310     }
311 
get_sizeCFF::Charset0312     unsigned int get_size(unsigned int num_glyphs) const
313     {
314         assert(num_glyphs > 0);
315         return HBUINT16::static_size * (num_glyphs - 1);
316     }
317 
318     HBUINT16 sids[HB_VAR_ARRAY];
319 
320     DEFINE_SIZE_ARRAY(0, sids);
321 };
322 
323 template <typename TYPE> struct Charset_Range
324 {
sanitizeCFF::Charset_Range325     bool sanitize(hb_sanitize_context_t *c) const
326     {
327         TRACE_SANITIZE(this);
328         return_trace(c->check_struct(this));
329     }
330 
331     HBUINT16 first;
332     TYPE nLeft;
333 
334     DEFINE_SIZE_STATIC(HBUINT16::static_size + TYPE::static_size);
335 };
336 
337 template <typename TYPE> struct Charset1_2
338 {
sanitizeCFF::Charset1_2339     bool sanitize(hb_sanitize_context_t *c, unsigned int num_glyphs) const
340     {
341         TRACE_SANITIZE(this);
342         if (unlikely(!c->check_struct(this)))
343             return_trace(false);
344         num_glyphs--;
345         for (unsigned int i = 0; num_glyphs > 0; i++) {
346             if (unlikely(!ranges[i].sanitize(c) || (num_glyphs < ranges[i].nLeft + 1)))
347                 return_trace(false);
348             num_glyphs -= (ranges[i].nLeft + 1);
349         }
350         return_trace(true);
351     }
352 
get_sidCFF::Charset1_2353     hb_codepoint_t get_sid(hb_codepoint_t glyph) const
354     {
355         if (glyph == 0)
356             return 0;
357         glyph--;
358         for (unsigned int i = 0;; i++) {
359             if (glyph <= ranges[i].nLeft)
360                 return (hb_codepoint_t)ranges[i].first + glyph;
361             glyph -= (ranges[i].nLeft + 1);
362         }
363 
364         return 0;
365     }
366 
get_glyphCFF::Charset1_2367     hb_codepoint_t get_glyph(hb_codepoint_t sid, unsigned int num_glyphs) const
368     {
369         if (sid == 0)
370             return 0;
371         hb_codepoint_t glyph = 1;
372         for (unsigned int i = 0;; i++) {
373             if (glyph >= num_glyphs)
374                 return 0;
375             if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
376                 return glyph + (sid - ranges[i].first);
377             glyph += (ranges[i].nLeft + 1);
378         }
379 
380         return 0;
381     }
382 
get_sizeCFF::Charset1_2383     unsigned int get_size(unsigned int num_glyphs) const
384     {
385         unsigned int size = HBUINT8::static_size;
386         int glyph = (int)num_glyphs;
387 
388         assert(glyph > 0);
389         glyph--;
390         for (unsigned int i = 0; glyph > 0; i++) {
391             glyph -= (ranges[i].nLeft + 1);
392             size += Charset_Range<TYPE>::static_size;
393         }
394 
395         return size;
396     }
397 
398     Charset_Range<TYPE> ranges[HB_VAR_ARRAY];
399 
400     DEFINE_SIZE_ARRAY(0, ranges);
401 };
402 
403 typedef Charset1_2<HBUINT8> Charset1;
404 typedef Charset1_2<HBUINT16> Charset2;
405 typedef Charset_Range<HBUINT8> Charset1_Range;
406 typedef Charset_Range<HBUINT16> Charset2_Range;
407 
408 struct Charset
409 {
get_sizeCFF::Charset410     unsigned int get_size(unsigned int num_glyphs) const
411     {
412         switch (format) {
413         case 0:
414             return min_size + u.format0.get_size(num_glyphs);
415         case 1:
416             return min_size + u.format1.get_size(num_glyphs);
417         case 2:
418             return min_size + u.format2.get_size(num_glyphs);
419         default:
420             return 0;
421         }
422     }
423 
get_sidCFF::Charset424     hb_codepoint_t get_sid(hb_codepoint_t glyph, unsigned int num_glyphs) const
425     {
426         if (unlikely(glyph >= num_glyphs))
427             return 0;
428         switch (format) {
429         case 0:
430             return u.format0.get_sid(glyph);
431         case 1:
432             return u.format1.get_sid(glyph);
433         case 2:
434             return u.format2.get_sid(glyph);
435         default:
436             return 0;
437         }
438     }
439 
get_glyphCFF::Charset440     hb_codepoint_t get_glyph(hb_codepoint_t sid, unsigned int num_glyphs) const
441     {
442         switch (format) {
443         case 0:
444             return u.format0.get_glyph(sid, num_glyphs);
445         case 1:
446             return u.format1.get_glyph(sid, num_glyphs);
447         case 2:
448             return u.format2.get_glyph(sid, num_glyphs);
449         default:
450             return 0;
451         }
452     }
453 
sanitizeCFF::Charset454     bool sanitize(hb_sanitize_context_t *c) const
455     {
456         TRACE_SANITIZE(this);
457         if (unlikely(!c->check_struct(this)))
458             return_trace(false);
459 
460         switch (format) {
461         case 0:
462             return_trace(u.format0.sanitize(c, c->get_num_glyphs()));
463         case 1:
464             return_trace(u.format1.sanitize(c, c->get_num_glyphs()));
465         case 2:
466             return_trace(u.format2.sanitize(c, c->get_num_glyphs()));
467         default:
468             return_trace(false);
469         }
470     }
471 
472     HBUINT8 format;
473     union {
474         Charset0 format0;
475         Charset1 format1;
476         Charset2 format2;
477     } u;
478 
479     DEFINE_SIZE_MIN(1);
480 };
481 
482 struct CFF1StringIndex : CFF1Index
483 {
484 };
485 
486 struct cff1_top_dict_interp_env_t : num_interp_env_t
487 {
cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t488     cff1_top_dict_interp_env_t()
489         : num_interp_env_t()
490         , prev_offset(0)
491         , last_offset(0)
492     {
493     }
494 
495     unsigned int prev_offset;
496     unsigned int last_offset;
497 };
498 
499 struct name_dict_values_t
500 {
501     enum name_dict_val_index_t {
502         version,
503         notice,
504         copyright,
505         fullName,
506         familyName,
507         weight,
508         postscript,
509         fontName,
510         baseFontName,
511         registry,
512         ordering,
513 
514         ValCount
515     };
516 
initCFF::name_dict_values_t517     void init()
518     {
519         for (unsigned int i = 0; i < ValCount; i++)
520             values[i] = CFF_UNDEF_SID;
521     }
522 
operator []CFF::name_dict_values_t523     unsigned int &operator[](unsigned int i)
524     {
525         assert(i < ValCount);
526         return values[i];
527     }
528 
operator []CFF::name_dict_values_t529     unsigned int operator[](unsigned int i) const
530     {
531         assert(i < ValCount);
532         return values[i];
533     }
534 
name_op_to_indexCFF::name_dict_values_t535     static enum name_dict_val_index_t name_op_to_index(op_code_t op)
536     {
537         switch (op) {
538         default: // can't happen - just make some compiler happy
539         case OpCode_version:
540             return version;
541         case OpCode_Notice:
542             return notice;
543         case OpCode_Copyright:
544             return copyright;
545         case OpCode_FullName:
546             return fullName;
547         case OpCode_FamilyName:
548             return familyName;
549         case OpCode_Weight:
550             return weight;
551         case OpCode_PostScript:
552             return postscript;
553         case OpCode_FontName:
554             return fontName;
555         case OpCode_BaseFontName:
556             return baseFontName;
557         }
558     }
559 
560     unsigned int values[ValCount];
561 };
562 
563 struct cff1_top_dict_val_t : op_str_t
564 {
565     unsigned int last_arg_offset;
566 };
567 
568 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
569 {
initCFF::cff1_top_dict_values_t570     void init()
571     {
572         top_dict_values_t<cff1_top_dict_val_t>::init();
573 
574         nameSIDs.init();
575         ros_supplement = 0;
576         cidCount = 8720;
577         EncodingOffset = 0;
578         CharsetOffset = 0;
579         FDSelectOffset = 0;
580         privateDictInfo.init();
581     }
finiCFF::cff1_top_dict_values_t582     void fini()
583     {
584         top_dict_values_t<cff1_top_dict_val_t>::fini();
585     }
586 
is_CIDCFF::cff1_top_dict_values_t587     bool is_CID() const
588     {
589         return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID;
590     }
591 
592     name_dict_values_t nameSIDs;
593     unsigned int ros_supplement_offset;
594     unsigned int ros_supplement;
595     unsigned int cidCount;
596 
597     unsigned int EncodingOffset;
598     unsigned int CharsetOffset;
599     unsigned int FDSelectOffset;
600     table_info_t privateDictInfo;
601 };
602 
603 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
604 {
process_opCFF::cff1_top_dict_opset_t605     static void process_op(op_code_t op, cff1_top_dict_interp_env_t &env, cff1_top_dict_values_t &dictval)
606     {
607         cff1_top_dict_val_t val;
608         val.last_arg_offset = (env.last_offset - 1) - dictval.opStart; /* offset to the last argument */
609 
610         switch (op) {
611         case OpCode_version:
612         case OpCode_Notice:
613         case OpCode_Copyright:
614         case OpCode_FullName:
615         case OpCode_FamilyName:
616         case OpCode_Weight:
617         case OpCode_PostScript:
618         case OpCode_BaseFontName:
619             dictval.nameSIDs[name_dict_values_t::name_op_to_index(op)] = env.argStack.pop_uint();
620             env.clear_args();
621             break;
622         case OpCode_isFixedPitch:
623         case OpCode_ItalicAngle:
624         case OpCode_UnderlinePosition:
625         case OpCode_UnderlineThickness:
626         case OpCode_PaintType:
627         case OpCode_CharstringType:
628         case OpCode_UniqueID:
629         case OpCode_StrokeWidth:
630         case OpCode_SyntheticBase:
631         case OpCode_CIDFontVersion:
632         case OpCode_CIDFontRevision:
633         case OpCode_CIDFontType:
634         case OpCode_UIDBase:
635         case OpCode_FontBBox:
636         case OpCode_XUID:
637         case OpCode_BaseFontBlend:
638             env.clear_args();
639             break;
640 
641         case OpCode_CIDCount:
642             dictval.cidCount = env.argStack.pop_uint();
643             env.clear_args();
644             break;
645 
646         case OpCode_ROS:
647             dictval.ros_supplement = env.argStack.pop_uint();
648             dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint();
649             dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint();
650             env.clear_args();
651             break;
652 
653         case OpCode_Encoding:
654             dictval.EncodingOffset = env.argStack.pop_uint();
655             env.clear_args();
656             if (unlikely(dictval.EncodingOffset == 0))
657                 return;
658             break;
659 
660         case OpCode_charset:
661             dictval.CharsetOffset = env.argStack.pop_uint();
662             env.clear_args();
663             if (unlikely(dictval.CharsetOffset == 0))
664                 return;
665             break;
666 
667         case OpCode_FDSelect:
668             dictval.FDSelectOffset = env.argStack.pop_uint();
669             env.clear_args();
670             break;
671 
672         case OpCode_Private:
673             dictval.privateDictInfo.offset = env.argStack.pop_uint();
674             dictval.privateDictInfo.size = env.argStack.pop_uint();
675             env.clear_args();
676             break;
677 
678         default:
679             env.last_offset = env.str_ref.offset;
680             top_dict_opset_t<cff1_top_dict_val_t>::process_op(op, env, dictval);
681             /* Record this operand below if stack is empty, otherwise done */
682             if (!env.argStack.is_empty())
683                 return;
684             break;
685         }
686 
687         if (unlikely(env.in_error()))
688             return;
689 
690         dictval.add_op(op, env.str_ref, val);
691     }
692 };
693 
694 struct cff1_font_dict_values_t : dict_values_t<op_str_t>
695 {
initCFF::cff1_font_dict_values_t696     void init()
697     {
698         dict_values_t<op_str_t>::init();
699         privateDictInfo.init();
700         fontName = CFF_UNDEF_SID;
701     }
finiCFF::cff1_font_dict_values_t702     void fini()
703     {
704         dict_values_t<op_str_t>::fini();
705     }
706 
707     table_info_t privateDictInfo;
708     unsigned int fontName;
709 };
710 
711 struct cff1_font_dict_opset_t : dict_opset_t
712 {
process_opCFF::cff1_font_dict_opset_t713     static void process_op(op_code_t op, num_interp_env_t &env, cff1_font_dict_values_t &dictval)
714     {
715         switch (op) {
716         case OpCode_FontName:
717             dictval.fontName = env.argStack.pop_uint();
718             env.clear_args();
719             break;
720         case OpCode_FontMatrix:
721         case OpCode_PaintType:
722             env.clear_args();
723             break;
724         case OpCode_Private:
725             dictval.privateDictInfo.offset = env.argStack.pop_uint();
726             dictval.privateDictInfo.size = env.argStack.pop_uint();
727             env.clear_args();
728             break;
729 
730         default:
731             dict_opset_t::process_op(op, env);
732             if (!env.argStack.is_empty())
733                 return;
734             break;
735         }
736 
737         if (unlikely(env.in_error()))
738             return;
739 
740         dictval.add_op(op, env.str_ref);
741     }
742 };
743 
744 template <typename VAL> struct cff1_private_dict_values_base_t : dict_values_t<VAL>
745 {
initCFF::cff1_private_dict_values_base_t746     void init()
747     {
748         dict_values_t<VAL>::init();
749         subrsOffset = 0;
750         localSubrs = &Null(CFF1Subrs);
751     }
finiCFF::cff1_private_dict_values_base_t752     void fini()
753     {
754         dict_values_t<VAL>::fini();
755     }
756 
757     unsigned int subrsOffset;
758     const CFF1Subrs *localSubrs;
759 };
760 
761 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
762 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
763 
764 struct cff1_private_dict_opset_t : dict_opset_t
765 {
process_opCFF::cff1_private_dict_opset_t766     static void process_op(op_code_t op, num_interp_env_t &env, cff1_private_dict_values_t &dictval)
767     {
768         num_dict_val_t val;
769         val.init();
770 
771         switch (op) {
772         case OpCode_BlueValues:
773         case OpCode_OtherBlues:
774         case OpCode_FamilyBlues:
775         case OpCode_FamilyOtherBlues:
776         case OpCode_StemSnapH:
777         case OpCode_StemSnapV:
778             env.clear_args();
779             break;
780         case OpCode_StdHW:
781         case OpCode_StdVW:
782         case OpCode_BlueScale:
783         case OpCode_BlueShift:
784         case OpCode_BlueFuzz:
785         case OpCode_ForceBold:
786         case OpCode_LanguageGroup:
787         case OpCode_ExpansionFactor:
788         case OpCode_initialRandomSeed:
789         case OpCode_defaultWidthX:
790         case OpCode_nominalWidthX:
791             val.single_val = env.argStack.pop_num();
792             env.clear_args();
793             break;
794         case OpCode_Subrs:
795             dictval.subrsOffset = env.argStack.pop_uint();
796             env.clear_args();
797             break;
798 
799         default:
800             dict_opset_t::process_op(op, env);
801             if (!env.argStack.is_empty())
802                 return;
803             break;
804         }
805 
806         if (unlikely(env.in_error()))
807             return;
808 
809         dictval.add_op(op, env.str_ref, val);
810     }
811 };
812 
813 struct cff1_private_dict_opset_subset : dict_opset_t
814 {
process_opCFF::cff1_private_dict_opset_subset815     static void process_op(op_code_t op, num_interp_env_t &env, cff1_private_dict_values_subset_t &dictval)
816     {
817         switch (op) {
818         case OpCode_BlueValues:
819         case OpCode_OtherBlues:
820         case OpCode_FamilyBlues:
821         case OpCode_FamilyOtherBlues:
822         case OpCode_StemSnapH:
823         case OpCode_StemSnapV:
824         case OpCode_StdHW:
825         case OpCode_StdVW:
826         case OpCode_BlueScale:
827         case OpCode_BlueShift:
828         case OpCode_BlueFuzz:
829         case OpCode_ForceBold:
830         case OpCode_LanguageGroup:
831         case OpCode_ExpansionFactor:
832         case OpCode_initialRandomSeed:
833         case OpCode_defaultWidthX:
834         case OpCode_nominalWidthX:
835             env.clear_args();
836             break;
837 
838         case OpCode_Subrs:
839             dictval.subrsOffset = env.argStack.pop_uint();
840             env.clear_args();
841             break;
842 
843         default:
844             dict_opset_t::process_op(op, env);
845             if (!env.argStack.is_empty())
846                 return;
847             break;
848         }
849 
850         if (unlikely(env.in_error()))
851             return;
852 
853         dictval.add_op(op, env.str_ref);
854     }
855 };
856 
857 typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t>
858     cff1_top_dict_interpreter_t;
859 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
860 
861 typedef CFF1Index CFF1NameIndex;
862 typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
863 
864 struct cff1_font_dict_values_mod_t
865 {
cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t866     cff1_font_dict_values_mod_t()
867     {
868         init();
869     }
870 
initCFF::cff1_font_dict_values_mod_t871     void init()
872     {
873         init(&Null(cff1_font_dict_values_t), CFF_UNDEF_SID);
874     }
875 
initCFF::cff1_font_dict_values_mod_t876     void init(const cff1_font_dict_values_t *base_, unsigned int fontName_)
877     {
878         base = base_;
879         fontName = fontName_;
880         privateDictInfo.init();
881     }
882 
get_countCFF::cff1_font_dict_values_mod_t883     unsigned get_count() const
884     {
885         return base->get_count();
886     }
887 
operator []CFF::cff1_font_dict_values_mod_t888     const op_str_t &operator[](unsigned int i) const
889     {
890         return (*base)[i];
891     }
892 
893     const cff1_font_dict_values_t *base;
894     table_info_t privateDictInfo;
895     unsigned int fontName;
896 };
897 
898 struct CFF1FDArray : FDArray<HBUINT16>
899 {
900 };
901 
902 } /* namespace CFF */
903 
904 namespace OT {
905 
906 using namespace CFF;
907 
908 struct cff1
909 {
910     static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
911 
sanitizeOT::cff1912     bool sanitize(hb_sanitize_context_t *c) const
913     {
914         TRACE_SANITIZE(this);
915         return_trace(c->check_struct(this) && likely(version.major == 1));
916     }
917 
918     template <typename PRIVOPSET, typename PRIVDICTVAL> struct accelerator_templ_t
919     {
initOT::cff1::accelerator_templ_t920         void init(hb_face_t *face)
921         {
922             topDict.init();
923             fontDicts.init();
924             privateDicts.init();
925 
926             this->blob = sc.reference_table<cff1>(face);
927 
928             /* setup for run-time santization */
929             sc.init(this->blob);
930             sc.start_processing();
931 
932             const OT::cff1 *cff = this->blob->template as<OT::cff1>();
933 
934             if (cff == &Null(OT::cff1)) {
935                 fini();
936                 return;
937             }
938 
939             nameIndex = &cff->nameIndex(cff);
940             if ((nameIndex == &Null(CFF1NameIndex)) || !nameIndex->sanitize(&sc)) {
941                 fini();
942                 return;
943             }
944 
945             topDictIndex = &StructAtOffset<CFF1TopDictIndex>(nameIndex, nameIndex->get_size());
946             if ((topDictIndex == &Null(CFF1TopDictIndex)) || !topDictIndex->sanitize(&sc) ||
947                 (topDictIndex->count == 0)) {
948                 fini();
949                 return;
950             }
951 
952             { /* parse top dict */
953                 const byte_str_t topDictStr = (*topDictIndex)[0];
954                 if (unlikely(!topDictStr.sanitize(&sc))) {
955                     fini();
956                     return;
957                 }
958                 cff1_top_dict_interpreter_t top_interp;
959                 top_interp.env.init(topDictStr);
960                 topDict.init();
961                 if (unlikely(!top_interp.interpret(topDict))) {
962                     fini();
963                     return;
964                 }
965             }
966 
967             if (is_predef_charset())
968                 charset = &Null(Charset);
969             else {
970                 charset = &StructAtOffsetOrNull<Charset>(cff, topDict.CharsetOffset);
971                 if (unlikely((charset == &Null(Charset)) || !charset->sanitize(&sc))) {
972                     fini();
973                     return;
974                 }
975             }
976 
977             fdCount = 1;
978             if (is_CID()) {
979                 fdArray = &StructAtOffsetOrNull<CFF1FDArray>(cff, topDict.FDArrayOffset);
980                 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect>(cff, topDict.FDSelectOffset);
981                 if (unlikely((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize(&sc) ||
982                              (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize(&sc, fdArray->count))) {
983                     fini();
984                     return;
985                 }
986 
987                 fdCount = fdArray->count;
988             } else {
989                 fdArray = &Null(CFF1FDArray);
990                 fdSelect = &Null(CFF1FDSelect);
991             }
992 
993             encoding = &Null(Encoding);
994             if (is_CID()) {
995                 if (unlikely(charset == &Null(Charset))) {
996                     fini();
997                     return;
998                 }
999             } else {
1000                 if (!is_predef_encoding()) {
1001                     encoding = &StructAtOffsetOrNull<Encoding>(cff, topDict.EncodingOffset);
1002                     if (unlikely((encoding == &Null(Encoding)) || !encoding->sanitize(&sc))) {
1003                         fini();
1004                         return;
1005                     }
1006                 }
1007             }
1008 
1009             stringIndex = &StructAtOffset<CFF1StringIndex>(topDictIndex, topDictIndex->get_size());
1010             if ((stringIndex == &Null(CFF1StringIndex)) || !stringIndex->sanitize(&sc)) {
1011                 fini();
1012                 return;
1013             }
1014 
1015             globalSubrs = &StructAtOffset<CFF1Subrs>(stringIndex, stringIndex->get_size());
1016             if ((globalSubrs != &Null(CFF1Subrs)) && !globalSubrs->sanitize(&sc)) {
1017                 fini();
1018                 return;
1019             }
1020 
1021             charStrings = &StructAtOffsetOrNull<CFF1CharStrings>(cff, topDict.charStringsOffset);
1022 
1023             if ((charStrings == &Null(CFF1CharStrings)) || unlikely(!charStrings->sanitize(&sc))) {
1024                 fini();
1025                 return;
1026             }
1027 
1028             num_glyphs = charStrings->count;
1029             if (num_glyphs != sc.get_num_glyphs()) {
1030                 fini();
1031                 return;
1032             }
1033 
1034             privateDicts.resize(fdCount);
1035             for (unsigned int i = 0; i < fdCount; i++)
1036                 privateDicts[i].init();
1037 
1038             // parse CID font dicts and gather private dicts
1039             if (is_CID()) {
1040                 for (unsigned int i = 0; i < fdCount; i++) {
1041                     byte_str_t fontDictStr = (*fdArray)[i];
1042                     if (unlikely(!fontDictStr.sanitize(&sc))) {
1043                         fini();
1044                         return;
1045                     }
1046                     cff1_font_dict_values_t *font;
1047                     cff1_font_dict_interpreter_t font_interp;
1048                     font_interp.env.init(fontDictStr);
1049                     font = fontDicts.push();
1050                     if (unlikely(font == &Crap(cff1_font_dict_values_t))) {
1051                         fini();
1052                         return;
1053                     }
1054                     font->init();
1055                     if (unlikely(!font_interp.interpret(*font))) {
1056                         fini();
1057                         return;
1058                     }
1059                     PRIVDICTVAL *priv = &privateDicts[i];
1060                     const byte_str_t privDictStr(StructAtOffset<UnsizedByteStr>(cff, font->privateDictInfo.offset),
1061                                                  font->privateDictInfo.size);
1062                     if (unlikely(!privDictStr.sanitize(&sc))) {
1063                         fini();
1064                         return;
1065                     }
1066                     dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1067                     priv_interp.env.init(privDictStr);
1068                     priv->init();
1069                     if (unlikely(!priv_interp.interpret(*priv))) {
1070                         fini();
1071                         return;
1072                     }
1073 
1074                     priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs>(&privDictStr, priv->subrsOffset);
1075                     if (priv->localSubrs != &Null(CFF1Subrs) && unlikely(!priv->localSubrs->sanitize(&sc))) {
1076                         fini();
1077                         return;
1078                     }
1079                 }
1080             } else /* non-CID */
1081             {
1082                 cff1_top_dict_values_t *font = &topDict;
1083                 PRIVDICTVAL *priv = &privateDicts[0];
1084 
1085                 const byte_str_t privDictStr(StructAtOffset<UnsizedByteStr>(cff, font->privateDictInfo.offset),
1086                                              font->privateDictInfo.size);
1087                 if (unlikely(!privDictStr.sanitize(&sc))) {
1088                     fini();
1089                     return;
1090                 }
1091                 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1092                 priv_interp.env.init(privDictStr);
1093                 priv->init();
1094                 if (unlikely(!priv_interp.interpret(*priv))) {
1095                     fini();
1096                     return;
1097                 }
1098 
1099                 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs>(&privDictStr, priv->subrsOffset);
1100                 if (priv->localSubrs != &Null(CFF1Subrs) && unlikely(!priv->localSubrs->sanitize(&sc))) {
1101                     fini();
1102                     return;
1103                 }
1104             }
1105         }
1106 
finiOT::cff1::accelerator_templ_t1107         void fini()
1108         {
1109             sc.end_processing();
1110             topDict.fini();
1111             fontDicts.fini_deep();
1112             privateDicts.fini_deep();
1113             hb_blob_destroy(blob);
1114             blob = nullptr;
1115         }
1116 
is_validOT::cff1::accelerator_templ_t1117         bool is_valid() const
1118         {
1119             return blob;
1120         }
is_CIDOT::cff1::accelerator_templ_t1121         bool is_CID() const
1122         {
1123             return topDict.is_CID();
1124         }
1125 
is_predef_charsetOT::cff1::accelerator_templ_t1126         bool is_predef_charset() const
1127         {
1128             return topDict.CharsetOffset <= ExpertSubsetCharset;
1129         }
1130 
std_code_to_glyphOT::cff1::accelerator_templ_t1131         unsigned int std_code_to_glyph(hb_codepoint_t code) const
1132         {
1133             hb_codepoint_t sid = lookup_standard_encoding_for_sid(code);
1134             if (unlikely(sid == CFF_UNDEF_SID))
1135                 return 0;
1136 
1137             if (charset != &Null(Charset))
1138                 return charset->get_glyph(sid, num_glyphs);
1139             else if ((topDict.CharsetOffset == ISOAdobeCharset) && (code <= 228 /*zcaron*/))
1140                 return sid;
1141             return 0;
1142         }
1143 
is_predef_encodingOT::cff1::accelerator_templ_t1144         bool is_predef_encoding() const
1145         {
1146             return topDict.EncodingOffset <= ExpertEncoding;
1147         }
1148 
glyph_to_codeOT::cff1::accelerator_templ_t1149         hb_codepoint_t glyph_to_code(hb_codepoint_t glyph) const
1150         {
1151             if (encoding != &Null(Encoding))
1152                 return encoding->get_code(glyph);
1153             else {
1154                 hb_codepoint_t sid = glyph_to_sid(glyph);
1155                 if (sid == 0)
1156                     return 0;
1157                 hb_codepoint_t code = 0;
1158                 switch (topDict.EncodingOffset) {
1159                 case StandardEncoding:
1160                     code = lookup_standard_encoding_for_code(sid);
1161                     break;
1162                 case ExpertEncoding:
1163                     code = lookup_expert_encoding_for_code(sid);
1164                     break;
1165                 default:
1166                     break;
1167                 }
1168                 return code;
1169             }
1170         }
1171 
glyph_to_sidOT::cff1::accelerator_templ_t1172         hb_codepoint_t glyph_to_sid(hb_codepoint_t glyph) const
1173         {
1174             if (charset != &Null(Charset))
1175                 return charset->get_sid(glyph, num_glyphs);
1176             else {
1177                 hb_codepoint_t sid = 0;
1178                 switch (topDict.CharsetOffset) {
1179                 case ISOAdobeCharset:
1180                     if (glyph <= 228 /*zcaron*/)
1181                         sid = glyph;
1182                     break;
1183                 case ExpertCharset:
1184                     sid = lookup_expert_charset_for_sid(glyph);
1185                     break;
1186                 case ExpertSubsetCharset:
1187                     sid = lookup_expert_subset_charset_for_sid(glyph);
1188                     break;
1189                 default:
1190                     break;
1191                 }
1192                 return sid;
1193             }
1194         }
1195 
sid_to_glyphOT::cff1::accelerator_templ_t1196         hb_codepoint_t sid_to_glyph(hb_codepoint_t sid) const
1197         {
1198             if (charset != &Null(Charset))
1199                 return charset->get_glyph(sid, num_glyphs);
1200             else {
1201                 hb_codepoint_t glyph = 0;
1202                 switch (topDict.CharsetOffset) {
1203                 case ISOAdobeCharset:
1204                     if (sid <= 228 /*zcaron*/)
1205                         glyph = sid;
1206                     break;
1207                 case ExpertCharset:
1208                     glyph = lookup_expert_charset_for_glyph(sid);
1209                     break;
1210                 case ExpertSubsetCharset:
1211                     glyph = lookup_expert_subset_charset_for_glyph(sid);
1212                     break;
1213                 default:
1214                     break;
1215                 }
1216                 return glyph;
1217             }
1218         }
1219 
1220     protected:
1221         hb_blob_t *blob;
1222         hb_sanitize_context_t sc;
1223 
1224     public:
1225         const Encoding *encoding;
1226         const Charset *charset;
1227         const CFF1NameIndex *nameIndex;
1228         const CFF1TopDictIndex *topDictIndex;
1229         const CFF1StringIndex *stringIndex;
1230         const CFF1Subrs *globalSubrs;
1231         const CFF1CharStrings *charStrings;
1232         const CFF1FDArray *fdArray;
1233         const CFF1FDSelect *fdSelect;
1234         unsigned int fdCount;
1235 
1236         cff1_top_dict_values_t topDict;
1237         hb_vector_t<cff1_font_dict_values_t> fontDicts;
1238         hb_vector_t<PRIVDICTVAL> privateDicts;
1239 
1240         unsigned int num_glyphs;
1241     };
1242 
1243     struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1244     {
initOT::cff1::accelerator_t1245         void init(hb_face_t *face)
1246         {
1247             SUPER::init(face);
1248 
1249             if (!is_valid())
1250                 return;
1251             if (is_CID())
1252                 return;
1253 
1254             /* fill glyph_names */
1255             for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) {
1256                 hb_codepoint_t sid = glyph_to_sid(gid);
1257                 gname_t gname;
1258                 gname.sid = sid;
1259                 if (sid < cff1_std_strings_length)
1260                     gname.name = cff1_std_strings(sid);
1261                 else {
1262                     byte_str_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
1263                     gname.name = hb_bytes_t((const char *)ustr.arrayZ, ustr.length);
1264                 }
1265                 if (unlikely(!gname.name.arrayZ)) {
1266                     fini();
1267                     return;
1268                 }
1269                 glyph_names.push(gname);
1270             }
1271             glyph_names.qsort();
1272         }
1273 
finiOT::cff1::accelerator_t1274         void fini()
1275         {
1276             glyph_names.fini();
1277 
1278             SUPER::fini();
1279         }
1280 
get_glyph_nameOT::cff1::accelerator_t1281         bool get_glyph_name(hb_codepoint_t glyph, char *buf, unsigned int buf_len) const
1282         {
1283             if (!buf)
1284                 return true;
1285             if (unlikely(!is_valid()))
1286                 return false;
1287             if (is_CID())
1288                 return false;
1289             hb_codepoint_t sid = glyph_to_sid(glyph);
1290             const char *str;
1291             size_t str_len;
1292             if (sid < cff1_std_strings_length) {
1293                 hb_bytes_t byte_str = cff1_std_strings(sid);
1294                 str = byte_str.arrayZ;
1295                 str_len = byte_str.length;
1296             } else {
1297                 byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
1298                 str = (const char *)ubyte_str.arrayZ;
1299                 str_len = ubyte_str.length;
1300             }
1301             if (!str_len)
1302                 return false;
1303             unsigned int len = hb_min(buf_len - 1, str_len);
1304             strncpy(buf, (const char *)str, len);
1305             buf[len] = '\0';
1306             return true;
1307         }
1308 
get_glyph_from_nameOT::cff1::accelerator_t1309         bool get_glyph_from_name(const char *name, int len, hb_codepoint_t *glyph) const
1310         {
1311             if (len < 0)
1312                 len = strlen(name);
1313             if (unlikely(!len))
1314                 return false;
1315 
1316             gname_t key = {hb_bytes_t(name, len), 0};
1317             const gname_t *gname = glyph_names.bsearch(key);
1318             if (!gname)
1319                 return false;
1320             hb_codepoint_t gid = sid_to_glyph(gname->sid);
1321             if (!gid && gname->sid)
1322                 return false;
1323             *glyph = gid;
1324             return true;
1325         }
1326 
1327         HB_INTERNAL bool get_extents(hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1328         HB_INTERNAL bool get_seac_components(hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
1329 
1330     private:
1331         struct gname_t
1332         {
1333             hb_bytes_t name;
1334             uint16_t sid;
1335 
cmpOT::cff1::accelerator_t::gname_t1336             static int cmp(const void *a_, const void *b_)
1337             {
1338                 const gname_t *a = (const gname_t *)a_;
1339                 const gname_t *b = (const gname_t *)b_;
1340                 int minlen = hb_min(a->name.length, b->name.length);
1341                 int ret = strncmp(a->name.arrayZ, b->name.arrayZ, minlen);
1342                 if (ret)
1343                     return ret;
1344                 return a->name.length - b->name.length;
1345             }
1346 
cmpOT::cff1::accelerator_t::gname_t1347             int cmp(const gname_t &a) const
1348             {
1349                 return cmp(&a, this);
1350             }
1351         };
1352 
1353         hb_sorted_vector_t<gname_t> glyph_names;
1354 
1355         typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
1356     };
1357 
1358     struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t>
1359     {
1360     };
1361 
1362 protected:
1363     HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code(hb_codepoint_t sid);
1364     HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code(hb_codepoint_t sid);
1365     HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid(hb_codepoint_t glyph);
1366     HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid(hb_codepoint_t glyph);
1367     HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph(hb_codepoint_t sid);
1368     HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph(hb_codepoint_t sid);
1369     HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid(hb_codepoint_t code);
1370 
1371 public:
1372     FixedVersion<HBUINT8> version;              /* Version of CFF table. set to 0x0100u */
1373     OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
1374     HBUINT8 offSize;                            /* offset size (unused?) */
1375 
1376 public:
1377     DEFINE_SIZE_STATIC(4);
1378 };
1379 
1380 struct cff1_accelerator_t : cff1::accelerator_t
1381 {
1382 };
1383 } /* namespace OT */
1384 
1385 #endif /* HB_OT_CFF1_TABLE_HH */
1386