• 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-cff-common.hh"
31 #include "hb-subset-cff-common.hh"
32 #include "hb-draw.hh"
33 #include "hb-paint.hh"
34 
35 #define HB_STRING_ARRAY_NAME cff1_std_strings
36 #define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh"
37 #include "hb-string-array.hh"
38 #undef HB_STRING_ARRAY_LIST
39 #undef HB_STRING_ARRAY_NAME
40 
41 namespace CFF {
42 
43 /*
44  * CFF -- Compact Font Format (CFF)
45  * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
46  */
47 #define HB_OT_TAG_CFF1 HB_TAG('C','F','F',' ')
48 
49 #define CFF_UNDEF_SID   CFF_UNDEF_CODE
50 
51 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
52 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
53 
54 typedef CFFIndex<HBUINT16>  CFF1Index;
55 
56 typedef CFFIndex<HBUINT16> CFF1Index;
57 typedef CFF1Index          CFF1CharStrings;
58 typedef Subrs<HBUINT16>    CFF1Subrs;
59 
60 struct CFF1FDSelect : FDSelect {};
61 
62 /* Encoding */
63 struct Encoding0 {
sanitizeCFF::Encoding064   bool sanitize (hb_sanitize_context_t *c) const
65   {
66     TRACE_SANITIZE (this);
67     return_trace (codes.sanitize (c));
68   }
69 
get_codeCFF::Encoding070   hb_codepoint_t get_code (hb_codepoint_t glyph) const
71   {
72     assert (glyph > 0);
73     glyph--;
74     if (glyph < nCodes ())
75     {
76       return (hb_codepoint_t)codes[glyph];
77     }
78     else
79       return CFF_UNDEF_CODE;
80   }
81 
nCodesCFF::Encoding082   HBUINT8 &nCodes () { return codes.len; }
nCodesCFF::Encoding083   HBUINT8 nCodes () const { return codes.len; }
84 
85   ArrayOf<HBUINT8, HBUINT8> codes;
86 
87   DEFINE_SIZE_ARRAY_SIZED (1, codes);
88 };
89 
90 struct Encoding1_Range {
sanitizeCFF::Encoding1_Range91   bool sanitize (hb_sanitize_context_t *c) const
92   {
93     TRACE_SANITIZE (this);
94     return_trace (c->check_struct (this));
95   }
96 
97   HBUINT8   first;
98   HBUINT8   nLeft;
99 
100   DEFINE_SIZE_STATIC (2);
101 };
102 
103 struct Encoding1 {
sanitizeCFF::Encoding1104   bool sanitize (hb_sanitize_context_t *c) const
105   {
106     TRACE_SANITIZE (this);
107     return_trace (ranges.sanitize (c));
108   }
109 
get_codeCFF::Encoding1110   hb_codepoint_t get_code (hb_codepoint_t glyph) const
111   {
112     /* TODO: Add cache like get_sid. */
113     assert (glyph > 0);
114     glyph--;
115     for (unsigned int i = 0; i < nRanges (); i++)
116     {
117       if (glyph <= ranges[i].nLeft)
118       {
119 	hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
120 	return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
121       }
122       glyph -= (ranges[i].nLeft + 1);
123     }
124     return CFF_UNDEF_CODE;
125   }
126 
nRangesCFF::Encoding1127   HBUINT8 &nRanges () { return ranges.len; }
nRangesCFF::Encoding1128   HBUINT8 nRanges () const { return ranges.len; }
129 
130   ArrayOf<Encoding1_Range, HBUINT8> ranges;
131 
132   DEFINE_SIZE_ARRAY_SIZED (1, ranges);
133 };
134 
135 struct SuppEncoding {
sanitizeCFF::SuppEncoding136   bool sanitize (hb_sanitize_context_t *c) const
137   {
138     TRACE_SANITIZE (this);
139     return_trace (c->check_struct (this));
140   }
141 
142   HBUINT8   code;
143   HBUINT16  glyph;
144 
145   DEFINE_SIZE_STATIC (3);
146 };
147 
148 struct CFF1SuppEncData {
sanitizeCFF::CFF1SuppEncData149   bool sanitize (hb_sanitize_context_t *c) const
150   {
151     TRACE_SANITIZE (this);
152     return_trace (supps.sanitize (c));
153   }
154 
get_codesCFF::CFF1SuppEncData155   void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
156   {
157     for (unsigned int i = 0; i < nSups (); i++)
158       if (sid == supps[i].glyph)
159 	codes.push (supps[i].code);
160   }
161 
nSupsCFF::CFF1SuppEncData162   HBUINT8 &nSups () { return supps.len; }
nSupsCFF::CFF1SuppEncData163   HBUINT8 nSups () const { return supps.len; }
164 
165   ArrayOf<SuppEncoding, HBUINT8> supps;
166 
167   DEFINE_SIZE_ARRAY_SIZED (1, supps);
168 };
169 
170 struct Encoding
171 {
172   /* serialize a fullset Encoding */
serializeCFF::Encoding173   bool serialize (hb_serialize_context_t *c, const Encoding &src)
174   {
175     TRACE_SERIALIZE (this);
176     return_trace (c->embed (src));
177   }
178 
179   /* serialize a subset Encoding */
serializeCFF::Encoding180   bool serialize (hb_serialize_context_t *c,
181 		  uint8_t format,
182 		  unsigned int enc_count,
183 		  const hb_vector_t<code_pair_t>& code_ranges,
184 		  const hb_vector_t<code_pair_t>& supp_codes)
185   {
186     TRACE_SERIALIZE (this);
187     Encoding *dest = c->extend_min (this);
188     if (unlikely (!dest)) return_trace (false);
189     dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
190     switch (format) {
191     case 0:
192     {
193       Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
194       if (unlikely (!fmt0)) return_trace (false);
195       fmt0->nCodes () = enc_count;
196       unsigned int glyph = 0;
197       for (unsigned int i = 0; i < code_ranges.length; i++)
198       {
199 	hb_codepoint_t code = code_ranges[i].code;
200 	for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
201 	  fmt0->codes[glyph++] = code++;
202 	if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
203 	  return_trace (false);
204       }
205     }
206     break;
207 
208     case 1:
209     {
210       Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
211       if (unlikely (!fmt1)) return_trace (false);
212       fmt1->nRanges () = code_ranges.length;
213       for (unsigned int i = 0; i < code_ranges.length; i++)
214       {
215 	if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
216 	  return_trace (false);
217 	fmt1->ranges[i].first = code_ranges[i].code;
218 	fmt1->ranges[i].nLeft = code_ranges[i].glyph;
219       }
220     }
221     break;
222 
223     }
224 
225     if (supp_codes.length)
226     {
227       CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
228       if (unlikely (!suppData)) return_trace (false);
229       suppData->nSups () = supp_codes.length;
230       for (unsigned int i = 0; i < supp_codes.length; i++)
231       {
232 	suppData->supps[i].code = supp_codes[i].code;
233 	suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
234       }
235     }
236 
237     return_trace (true);
238   }
239 
get_sizeCFF::Encoding240   unsigned int get_size () const
241   {
242     unsigned int size = min_size;
243     switch (table_format ())
244     {
245     case 0: size += u.format0.get_size (); break;
246     case 1: size += u.format1.get_size (); break;
247     }
248     if (has_supplement ())
249       size += suppEncData ().get_size ();
250     return size;
251   }
252 
get_codeCFF::Encoding253   hb_codepoint_t get_code (hb_codepoint_t glyph) const
254   {
255     switch (table_format ())
256     {
257     case 0: return u.format0.get_code (glyph);
258     case 1: return u.format1.get_code (glyph);
259     default:return 0;
260     }
261   }
262 
table_formatCFF::Encoding263   uint8_t table_format () const { return format & 0x7F; }
has_supplementCFF::Encoding264   bool  has_supplement () const { return format & 0x80; }
265 
get_supplement_codesCFF::Encoding266   void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
267   {
268     codes.resize (0);
269     if (has_supplement ())
270       suppEncData().get_codes (sid, codes);
271   }
272 
sanitizeCFF::Encoding273   bool sanitize (hb_sanitize_context_t *c) const
274   {
275     TRACE_SANITIZE (this);
276     if (unlikely (!c->check_struct (this)))
277       return_trace (false);
278 
279     switch (table_format ())
280     {
281     case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
282     case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
283     default:return_trace (false);
284     }
285     return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
286   }
287 
288   protected:
suppEncDataCFF::Encoding289   const CFF1SuppEncData &suppEncData () const
290   {
291     switch (table_format ())
292     {
293     case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
294     case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
295     default:return Null (CFF1SuppEncData);
296     }
297   }
298 
299   public:
300   HBUINT8	format;
301   union {
302   Encoding0	format0;
303   Encoding1	format1;
304   } u;
305   /* CFF1SuppEncData  suppEncData; */
306 
307   DEFINE_SIZE_MIN (1);
308 };
309 
310 /* Charset */
311 struct Charset0
312 {
sanitizeCFF::Charset0313   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
314   {
315     TRACE_SANITIZE (this);
316     if (num_charset_entries) *num_charset_entries = num_glyphs;
317     return_trace (sids.sanitize (c, num_glyphs - 1));
318   }
319 
get_sidCFF::Charset0320   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
321   {
322     if (unlikely (glyph >= num_glyphs)) return 0;
323     if (unlikely (glyph == 0))
324       return 0;
325     else
326       return sids[glyph - 1];
327   }
328 
collect_glyph_to_sid_mapCFF::Charset0329   void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
330   {
331     mapping->resize (num_glyphs, false);
332     for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
333       mapping->arrayZ[gid] = {sids[gid - 1], gid};
334   }
335 
get_glyphCFF::Charset0336   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
337   {
338     if (sid == 0)
339       return 0;
340 
341     for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
342     {
343       if (sids[glyph-1] == sid)
344 	return glyph;
345     }
346     return 0;
347   }
348 
get_sizeCFF::Charset0349   static unsigned int get_size (unsigned int num_glyphs)
350   {
351     assert (num_glyphs > 0);
352     return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1);
353   }
354 
355   UnsizedArrayOf<HBUINT16> sids;
356 
357   DEFINE_SIZE_ARRAY(0, sids);
358 };
359 
360 template <typename TYPE>
361 struct Charset_Range {
sanitizeCFF::Charset_Range362   bool sanitize (hb_sanitize_context_t *c) const
363   {
364     TRACE_SANITIZE (this);
365     return_trace (c->check_struct (this));
366   }
367 
368   HBUINT16  first;
369   TYPE      nLeft;
370 
371   DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
372 };
373 
374 template <typename TYPE>
375 struct Charset1_2 {
sanitizeCFF::Charset1_2376   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
377   {
378     TRACE_SANITIZE (this);
379     if (unlikely (!c->check_struct (this)))
380       return_trace (false);
381     num_glyphs--;
382     unsigned i;
383     for (i = 0; num_glyphs > 0; i++)
384     {
385       if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
386 	return_trace (false);
387       num_glyphs -= (ranges[i].nLeft + 1);
388     }
389     if (num_charset_entries)
390       *num_charset_entries = i;
391     return_trace (true);
392   }
393 
get_sidCFF::Charset1_2394   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs,
395 			  code_pair_t *cache = nullptr) const
396   {
397     if (unlikely (glyph >= num_glyphs)) return 0;
398     unsigned i;
399     hb_codepoint_t start_glyph;
400     if (cache && likely (cache->glyph <= glyph))
401     {
402       i = cache->code;
403       start_glyph = cache->glyph;
404     }
405     else
406     {
407       if (unlikely (glyph == 0)) return 0;
408       i = 0;
409       start_glyph = 1;
410     }
411     glyph -= start_glyph;
412     for (;; i++)
413     {
414       unsigned count = ranges[i].nLeft;
415       if (glyph <= count)
416       {
417         if (cache)
418 	  *cache = {i, start_glyph};
419 	return ranges[i].first + glyph;
420       }
421       count++;
422       start_glyph += count;
423       glyph -= count;
424     }
425 
426     return 0;
427   }
428 
collect_glyph_to_sid_mapCFF::Charset1_2429   void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
430   {
431     mapping->resize (num_glyphs, false);
432     hb_codepoint_t gid = 1;
433     if (gid >= num_glyphs)
434       return;
435     for (unsigned i = 0;; i++)
436     {
437       hb_codepoint_t sid = ranges[i].first;
438       unsigned count = ranges[i].nLeft + 1;
439       unsigned last = gid + count;
440       for (unsigned j = 0; j < count; j++)
441 	mapping->arrayZ[gid++] = {sid++, last - 1};
442 
443       if (gid >= num_glyphs)
444         break;
445     }
446   }
447 
get_glyphCFF::Charset1_2448   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
449   {
450     if (sid == 0) return 0;
451     hb_codepoint_t  glyph = 1;
452     for (unsigned int i = 0;; i++)
453     {
454       if (glyph >= num_glyphs)
455 	return 0;
456       if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
457 	return glyph + (sid - ranges[i].first);
458       glyph += (ranges[i].nLeft + 1);
459     }
460 
461     return 0;
462   }
463 
get_sizeCFF::Charset1_2464   unsigned int get_size (unsigned int num_glyphs) const
465   {
466     int glyph = (int) num_glyphs;
467     unsigned num_ranges = 0;
468 
469     assert (glyph > 0);
470     glyph--;
471     for (unsigned int i = 0; glyph > 0; i++)
472     {
473       glyph -= (ranges[i].nLeft + 1);
474       num_ranges++;
475     }
476 
477     return get_size_for_ranges (num_ranges);
478   }
479 
get_size_for_rangesCFF::Charset1_2480   static unsigned int get_size_for_ranges (unsigned int num_ranges)
481   {
482     return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges);
483   }
484 
485   UnsizedArrayOf<Charset_Range<TYPE>> ranges;
486 
487   DEFINE_SIZE_ARRAY (0, ranges);
488 };
489 
490 typedef Charset1_2<HBUINT8>     Charset1;
491 typedef Charset1_2<HBUINT16>    Charset2;
492 typedef Charset_Range<HBUINT8>  Charset1_Range;
493 typedef Charset_Range<HBUINT16> Charset2_Range;
494 
495 struct Charset
496 {
497   /* serialize a fullset Charset */
serializeCFF::Charset498   bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
499   {
500     TRACE_SERIALIZE (this);
501     return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs)));
502   }
503 
504   /* serialize a subset Charset */
serializeCFF::Charset505   bool serialize (hb_serialize_context_t *c,
506 		  uint8_t format,
507 		  unsigned int num_glyphs,
508 		  const hb_vector_t<code_pair_t>& sid_ranges)
509   {
510     TRACE_SERIALIZE (this);
511     Charset *dest = c->extend_min (this);
512     if (unlikely (!dest)) return_trace (false);
513     dest->format = format;
514     switch (format)
515     {
516     case 0:
517     {
518       Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false);
519       if (unlikely (!fmt0)) return_trace (false);
520       unsigned int glyph = 0;
521       for (unsigned int i = 0; i < sid_ranges.length; i++)
522       {
523 	hb_codepoint_t sid = sid_ranges.arrayZ[i].code;
524 	for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--)
525 	  fmt0->sids[glyph++] = sid++;
526       }
527     }
528     break;
529 
530     case 1:
531     {
532       Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false);
533       if (unlikely (!fmt1)) return_trace (false);
534       hb_codepoint_t all_glyphs = 0;
535       for (unsigned int i = 0; i < sid_ranges.length; i++)
536       {
537         auto &_ = sid_ranges.arrayZ[i];
538         all_glyphs |= _.glyph;
539 	fmt1->ranges[i].first = _.code;
540 	fmt1->ranges[i].nLeft = _.glyph;
541       }
542       if (unlikely (!(all_glyphs <= 0xFF)))
543 	return_trace (false);
544     }
545     break;
546 
547     case 2:
548     {
549       Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false);
550       if (unlikely (!fmt2)) return_trace (false);
551       hb_codepoint_t all_glyphs = 0;
552       for (unsigned int i = 0; i < sid_ranges.length; i++)
553       {
554         auto &_ = sid_ranges.arrayZ[i];
555         all_glyphs |= _.glyph;
556 	fmt2->ranges[i].first = _.code;
557 	fmt2->ranges[i].nLeft = _.glyph;
558       }
559       if (unlikely (!(all_glyphs <= 0xFFFF)))
560 	return_trace (false);
561     }
562     break;
563 
564     }
565     return_trace (true);
566   }
567 
get_sizeCFF::Charset568   unsigned int get_size (unsigned int num_glyphs) const
569   {
570     switch (format)
571     {
572     case 0: return min_size + u.format0.get_size (num_glyphs);
573     case 1: return min_size + u.format1.get_size (num_glyphs);
574     case 2: return min_size + u.format2.get_size (num_glyphs);
575     default:return 0;
576     }
577   }
578 
get_sidCFF::Charset579   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs,
580 			  code_pair_t *cache = nullptr) const
581   {
582     switch (format)
583     {
584     case 0: return u.format0.get_sid (glyph, num_glyphs);
585     case 1: return u.format1.get_sid (glyph, num_glyphs, cache);
586     case 2: return u.format2.get_sid (glyph, num_glyphs, cache);
587     default:return 0;
588     }
589   }
590 
collect_glyph_to_sid_mapCFF::Charset591   void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
592   {
593     switch (format)
594     {
595     case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
596     case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
597     case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
598     default:return;
599     }
600   }
601 
get_glyphCFF::Charset602   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
603   {
604     switch (format)
605     {
606     case 0: return u.format0.get_glyph (sid, num_glyphs);
607     case 1: return u.format1.get_glyph (sid, num_glyphs);
608     case 2: return u.format2.get_glyph (sid, num_glyphs);
609     default:return 0;
610     }
611   }
612 
sanitizeCFF::Charset613   bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const
614   {
615     TRACE_SANITIZE (this);
616     if (unlikely (!c->check_struct (this)))
617       return_trace (false);
618 
619     switch (format)
620     {
621     case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
622     case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
623     case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
624     default:return_trace (false);
625     }
626   }
627 
628   HBUINT8       format;
629   union {
630     Charset0    format0;
631     Charset1    format1;
632     Charset2    format2;
633   } u;
634 
635   DEFINE_SIZE_MIN (1);
636 };
637 
638 struct CFF1StringIndex : CFF1Index
639 {
serializeCFF::CFF1StringIndex640   bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
641 		  const hb_vector_t<unsigned> &sidmap)
642   {
643     TRACE_SERIALIZE (this);
644     if (unlikely ((strings.count == 0) || (sidmap.length == 0)))
645     {
646       if (unlikely (!c->extend_min (this->count)))
647 	return_trace (false);
648       count = 0;
649       return_trace (true);
650     }
651 
652     if (unlikely (sidmap.in_error ())) return_trace (false);
653 
654     // Save this in a vector since serialize() iterates it twice.
655     hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap)
656 					 | hb_map (strings));
657 
658     if (unlikely (bytesArray.in_error ())) return_trace (false);
659 
660     bool result = CFF1Index::serialize (c, bytesArray);
661     return_trace (result);
662   }
663 };
664 
665 struct cff1_top_dict_interp_env_t : num_interp_env_t
666 {
cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t667   cff1_top_dict_interp_env_t ()
668     : num_interp_env_t(), prev_offset(0), last_offset(0) {}
cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t669   cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes)
670     : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {}
671 
672   unsigned int prev_offset;
673   unsigned int last_offset;
674 };
675 
676 struct name_dict_values_t
677 {
678   enum name_dict_val_index_t
679   {
680       version,
681       notice,
682       copyright,
683       fullName,
684       familyName,
685       weight,
686       postscript,
687       fontName,
688       baseFontName,
689       registry,
690       ordering,
691 
692       ValCount
693   };
694 
initCFF::name_dict_values_t695   void init ()
696   {
697     for (unsigned int i = 0; i < ValCount; i++)
698       values[i] = CFF_UNDEF_SID;
699   }
700 
operator []CFF::name_dict_values_t701   unsigned int& operator[] (unsigned int i)
702   { assert (i < ValCount); return values[i]; }
703 
operator []CFF::name_dict_values_t704   unsigned int operator[] (unsigned int i) const
705   { assert (i < ValCount); return values[i]; }
706 
name_op_to_indexCFF::name_dict_values_t707   static enum name_dict_val_index_t name_op_to_index (op_code_t op)
708   {
709     switch (op) {
710       default: // can't happen - just make some compiler happy
711       case OpCode_version:
712 	return version;
713       case OpCode_Notice:
714 	return notice;
715       case OpCode_Copyright:
716 	return copyright;
717       case OpCode_FullName:
718 	return fullName;
719       case OpCode_FamilyName:
720 	return familyName;
721       case OpCode_Weight:
722 	return weight;
723       case OpCode_PostScript:
724 	return postscript;
725       case OpCode_FontName:
726 	return fontName;
727       case OpCode_BaseFontName:
728 	return baseFontName;
729     }
730   }
731 
732   unsigned int  values[ValCount];
733 };
734 
735 struct cff1_top_dict_val_t : op_str_t
736 {
737   unsigned int  last_arg_offset;
738 };
739 
740 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
741 {
initCFF::cff1_top_dict_values_t742   void init ()
743   {
744     top_dict_values_t<cff1_top_dict_val_t>::init ();
745 
746     nameSIDs.init ();
747     ros_supplement = 0;
748     cidCount = 8720;
749     EncodingOffset = 0;
750     CharsetOffset = 0;
751     FDSelectOffset = 0;
752     privateDictInfo.init ();
753   }
finiCFF::cff1_top_dict_values_t754   void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
755 
is_CIDCFF::cff1_top_dict_values_t756   bool is_CID () const
757   { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
758 
759   name_dict_values_t  nameSIDs;
760   unsigned int    ros_supplement_offset;
761   unsigned int    ros_supplement;
762   unsigned int    cidCount;
763 
764   unsigned int    EncodingOffset;
765   unsigned int    CharsetOffset;
766   unsigned int    FDSelectOffset;
767   table_info_t    privateDictInfo;
768 };
769 
770 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
771 {
process_opCFF::cff1_top_dict_opset_t772   static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
773   {
774     cff1_top_dict_val_t  val;
775     val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
776 
777     switch (op) {
778       case OpCode_version:
779       case OpCode_Notice:
780       case OpCode_Copyright:
781       case OpCode_FullName:
782       case OpCode_FontName:
783       case OpCode_FamilyName:
784       case OpCode_Weight:
785       case OpCode_PostScript:
786       case OpCode_BaseFontName:
787 	dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
788 	env.clear_args ();
789 	break;
790       case OpCode_isFixedPitch:
791       case OpCode_ItalicAngle:
792       case OpCode_UnderlinePosition:
793       case OpCode_UnderlineThickness:
794       case OpCode_PaintType:
795       case OpCode_CharstringType:
796       case OpCode_UniqueID:
797       case OpCode_StrokeWidth:
798       case OpCode_SyntheticBase:
799       case OpCode_CIDFontVersion:
800       case OpCode_CIDFontRevision:
801       case OpCode_CIDFontType:
802       case OpCode_UIDBase:
803       case OpCode_FontBBox:
804       case OpCode_XUID:
805       case OpCode_BaseFontBlend:
806 	env.clear_args ();
807 	break;
808 
809       case OpCode_CIDCount:
810 	dictval.cidCount = env.argStack.pop_uint ();
811 	env.clear_args ();
812 	break;
813 
814       case OpCode_ROS:
815 	dictval.ros_supplement = env.argStack.pop_uint ();
816 	dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
817 	dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
818 	env.clear_args ();
819 	break;
820 
821       case OpCode_Encoding:
822 	dictval.EncodingOffset = env.argStack.pop_uint ();
823 	env.clear_args ();
824 	if (unlikely (dictval.EncodingOffset == 0)) return;
825 	break;
826 
827       case OpCode_charset:
828 	dictval.CharsetOffset = env.argStack.pop_uint ();
829 	env.clear_args ();
830 	if (unlikely (dictval.CharsetOffset == 0)) return;
831 	break;
832 
833       case OpCode_FDSelect:
834 	dictval.FDSelectOffset = env.argStack.pop_uint ();
835 	env.clear_args ();
836 	break;
837 
838       case OpCode_Private:
839 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
840 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
841 	env.clear_args ();
842 	break;
843 
844       default:
845 	env.last_offset = env.str_ref.get_offset ();
846 	top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
847 	/* Record this operand below if stack is empty, otherwise done */
848 	if (!env.argStack.is_empty ()) return;
849 	break;
850     }
851 
852     if (unlikely (env.in_error ())) return;
853 
854     dictval.add_op (op, env.str_ref, val);
855   }
856 };
857 
858 struct cff1_font_dict_values_t : dict_values_t<op_str_t>
859 {
initCFF::cff1_font_dict_values_t860   void init ()
861   {
862     dict_values_t<op_str_t>::init ();
863     privateDictInfo.init ();
864     fontName = CFF_UNDEF_SID;
865   }
finiCFF::cff1_font_dict_values_t866   void fini () { dict_values_t<op_str_t>::fini (); }
867 
868   table_info_t       privateDictInfo;
869   unsigned int    fontName;
870 };
871 
872 struct cff1_font_dict_opset_t : dict_opset_t
873 {
process_opCFF::cff1_font_dict_opset_t874   static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
875   {
876     switch (op) {
877       case OpCode_FontName:
878 	dictval.fontName = env.argStack.pop_uint ();
879 	env.clear_args ();
880 	break;
881       case OpCode_FontMatrix:
882       case OpCode_PaintType:
883 	env.clear_args ();
884 	break;
885       case OpCode_Private:
886 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
887 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
888 	env.clear_args ();
889 	break;
890 
891       default:
892 	dict_opset_t::process_op (op, env);
893 	if (!env.argStack.is_empty ()) return;
894 	break;
895     }
896 
897     if (unlikely (env.in_error ())) return;
898 
899     dictval.add_op (op, env.str_ref);
900   }
901 };
902 
903 template <typename VAL>
904 struct cff1_private_dict_values_base_t : dict_values_t<VAL>
905 {
initCFF::cff1_private_dict_values_base_t906   void init ()
907   {
908     dict_values_t<VAL>::init ();
909     subrsOffset = 0;
910     localSubrs = &Null (CFF1Subrs);
911   }
finiCFF::cff1_private_dict_values_base_t912   void fini () { dict_values_t<VAL>::fini (); }
913 
914   unsigned int      subrsOffset;
915   const CFF1Subrs    *localSubrs;
916 };
917 
918 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
919 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
920 
921 struct cff1_private_dict_opset_t : dict_opset_t
922 {
process_opCFF::cff1_private_dict_opset_t923   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
924   {
925     num_dict_val_t val;
926     val.init ();
927 
928     switch (op) {
929       case OpCode_BlueValues:
930       case OpCode_OtherBlues:
931       case OpCode_FamilyBlues:
932       case OpCode_FamilyOtherBlues:
933       case OpCode_StemSnapH:
934       case OpCode_StemSnapV:
935       case OpCode_StdHW:
936       case OpCode_StdVW:
937       case OpCode_BlueScale:
938       case OpCode_BlueShift:
939       case OpCode_BlueFuzz:
940       case OpCode_ForceBold:
941       case OpCode_LanguageGroup:
942       case OpCode_ExpansionFactor:
943       case OpCode_initialRandomSeed:
944       case OpCode_defaultWidthX:
945       case OpCode_nominalWidthX:
946 	env.clear_args ();
947 	break;
948       case OpCode_Subrs:
949 	dictval.subrsOffset = env.argStack.pop_uint ();
950 	env.clear_args ();
951 	break;
952 
953       default:
954 	dict_opset_t::process_op (op, env);
955 	if (!env.argStack.is_empty ()) return;
956 	break;
957     }
958 
959     if (unlikely (env.in_error ())) return;
960 
961     dictval.add_op (op, env.str_ref, val);
962   }
963 };
964 
965 struct cff1_private_dict_opset_subset_t : dict_opset_t
966 {
process_opCFF::cff1_private_dict_opset_subset_t967   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
968   {
969     switch (op) {
970       case OpCode_BlueValues:
971       case OpCode_OtherBlues:
972       case OpCode_FamilyBlues:
973       case OpCode_FamilyOtherBlues:
974       case OpCode_StemSnapH:
975       case OpCode_StemSnapV:
976       case OpCode_StdHW:
977       case OpCode_StdVW:
978       case OpCode_BlueScale:
979       case OpCode_BlueShift:
980       case OpCode_BlueFuzz:
981       case OpCode_ForceBold:
982       case OpCode_LanguageGroup:
983       case OpCode_ExpansionFactor:
984       case OpCode_initialRandomSeed:
985       case OpCode_defaultWidthX:
986       case OpCode_nominalWidthX:
987 	env.clear_args ();
988 	break;
989 
990       case OpCode_Subrs:
991 	dictval.subrsOffset = env.argStack.pop_uint ();
992 	env.clear_args ();
993 	break;
994 
995       default:
996 	dict_opset_t::process_op (op, env);
997 	if (!env.argStack.is_empty ()) return;
998 	break;
999     }
1000 
1001     if (unlikely (env.in_error ())) return;
1002 
1003     dictval.add_op (op, env.str_ref);
1004   }
1005 };
1006 
1007 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;
1008 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
1009 
1010 typedef CFF1Index CFF1NameIndex;
1011 typedef CFF1Index CFF1TopDictIndex;
1012 
1013 struct cff1_font_dict_values_mod_t
1014 {
cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t1015   cff1_font_dict_values_mod_t() { init (); }
1016 
initCFF::cff1_font_dict_values_mod_t1017   void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
1018 
initCFF::cff1_font_dict_values_mod_t1019   void init (const cff1_font_dict_values_t *base_,
1020 	     unsigned int fontName_)
1021   {
1022     base = base_;
1023     fontName = fontName_;
1024     privateDictInfo.init ();
1025   }
1026 
get_countCFF::cff1_font_dict_values_mod_t1027   unsigned get_count () const { return base->get_count (); }
1028 
operator []CFF::cff1_font_dict_values_mod_t1029   const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
1030 
1031   const cff1_font_dict_values_t    *base;
1032   table_info_t		   privateDictInfo;
1033   unsigned int		fontName;
1034 };
1035 
1036 struct CFF1FDArray : FDArray<HBUINT16>
1037 {
1038   /* FDArray::serialize() requires this partial specialization to compile */
1039   template <typename ITER, typename OP_SERIALIZER>
serializeCFF::CFF1FDArray1040   bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
1041   { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
1042 };
1043 
1044 } /* namespace CFF */
1045 
1046 namespace OT {
1047 
1048 using namespace CFF;
1049 
1050 struct cff1
1051 {
1052   static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1;
1053 
sanitizeOT::cff11054   bool sanitize (hb_sanitize_context_t *c) const
1055   {
1056     TRACE_SANITIZE (this);
1057     return_trace (c->check_struct (this) &&
1058 		  likely (version.major == 1));
1059   }
1060 
1061   template <typename PRIVOPSET, typename PRIVDICTVAL>
1062   struct accelerator_templ_t
1063   {
1064     static constexpr hb_tag_t tableTag = cff1::tableTag;
1065 
accelerator_templ_tOT::cff1::accelerator_templ_t1066     accelerator_templ_t (hb_face_t *face)
1067     {
1068       if (!face) return;
1069 
1070       topDict.init ();
1071       fontDicts.init ();
1072       privateDicts.init ();
1073 
1074       this->blob = sc.reference_table<cff1> (face);
1075 
1076       /* setup for run-time santization */
1077       sc.init (this->blob);
1078       sc.start_processing ();
1079 
1080       const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
1081 
1082       if (cff == &Null (OT::cff1))
1083         goto fail;
1084 
1085       nameIndex = &cff->nameIndex (cff);
1086       if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
1087         goto fail;
1088 
1089       topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
1090       if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
1091         goto fail;
1092 
1093       { /* parse top dict */
1094 	const hb_ubytes_t topDictStr = (*topDictIndex)[0];
1095 	if (unlikely (!topDictStr.sanitize (&sc)))   goto fail;
1096 	cff1_top_dict_interp_env_t env (topDictStr);
1097 	cff1_top_dict_interpreter_t top_interp (env);
1098 	if (unlikely (!top_interp.interpret (topDict)))   goto fail;
1099       }
1100 
1101       if (is_predef_charset ())
1102 	charset = &Null (Charset);
1103       else
1104       {
1105 	charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
1106 	if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries)))   goto fail;
1107       }
1108 
1109       fdCount = 1;
1110       if (is_CID ())
1111       {
1112 	fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
1113 	fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
1114 	if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
1115 	    (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
1116 	  goto fail;
1117 
1118 	fdCount = fdArray->count;
1119       }
1120       else
1121       {
1122 	fdArray = &Null (CFF1FDArray);
1123 	fdSelect = &Null (CFF1FDSelect);
1124       }
1125 
1126       encoding = &Null (Encoding);
1127       if (is_CID ())
1128       {
1129 	if (unlikely (charset == &Null (Charset)))   goto fail;
1130       }
1131       else
1132       {
1133 	if (!is_predef_encoding ())
1134 	{
1135 	  encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
1136 	  if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc)))   goto fail;
1137 	}
1138       }
1139 
1140       stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
1141       if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
1142         goto fail;
1143 
1144       globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
1145       if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
1146         goto fail;
1147 
1148       charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
1149 
1150       if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
1151         goto fail;
1152 
1153       num_glyphs = charStrings->count;
1154       if (num_glyphs != sc.get_num_glyphs ())
1155         goto fail;
1156 
1157       if (unlikely (!privateDicts.resize (fdCount)))
1158         goto fail;
1159       for (unsigned int i = 0; i < fdCount; i++)
1160 	privateDicts[i].init ();
1161 
1162       // parse CID font dicts and gather private dicts
1163       if (is_CID ())
1164       {
1165 	for (unsigned int i = 0; i < fdCount; i++)
1166 	{
1167 	  hb_ubytes_t fontDictStr = (*fdArray)[i];
1168 	  if (unlikely (!fontDictStr.sanitize (&sc)))   goto fail;
1169 	  cff1_font_dict_values_t *font;
1170 	  cff1_top_dict_interp_env_t env (fontDictStr);
1171 	  cff1_font_dict_interpreter_t font_interp (env);
1172 	  font = fontDicts.push ();
1173 	  if (unlikely (fontDicts.in_error ()))   goto fail;
1174 
1175 	  font->init ();
1176 	  if (unlikely (!font_interp.interpret (*font)))   goto fail;
1177 	  PRIVDICTVAL *priv = &privateDicts[i];
1178 	  const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
1179 	  if (unlikely (!privDictStr.sanitize (&sc)))   goto fail;
1180 	  num_interp_env_t env2 (privDictStr);
1181 	  dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
1182 	  priv->init ();
1183 	  if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
1184 
1185 	  priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1186 	  if (priv->localSubrs != &Null (CFF1Subrs) &&
1187 	      unlikely (!priv->localSubrs->sanitize (&sc)))
1188 	    goto fail;
1189 	}
1190       }
1191       else  /* non-CID */
1192       {
1193 	cff1_top_dict_values_t *font = &topDict;
1194 	PRIVDICTVAL *priv = &privateDicts[0];
1195 
1196 	const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
1197 	if (unlikely (!privDictStr.sanitize (&sc)))   goto fail;
1198 	num_interp_env_t env (privDictStr);
1199 	dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
1200 	priv->init ();
1201 	if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
1202 
1203 	priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1204 	if (priv->localSubrs != &Null (CFF1Subrs) &&
1205 	    unlikely (!priv->localSubrs->sanitize (&sc)))
1206 	  goto fail;
1207       }
1208 
1209       return;
1210 
1211       fail:
1212         _fini ();
1213     }
~accelerator_templ_tOT::cff1::accelerator_templ_t1214     ~accelerator_templ_t () { _fini (); }
_finiOT::cff1::accelerator_templ_t1215     void _fini ()
1216     {
1217       sc.end_processing ();
1218       topDict.fini ();
1219       fontDicts.fini ();
1220       privateDicts.fini ();
1221       hb_blob_destroy (blob);
1222       blob = nullptr;
1223     }
1224 
get_blobOT::cff1::accelerator_templ_t1225     hb_blob_t *get_blob () const { return blob; }
1226 
is_validOT::cff1::accelerator_templ_t1227     bool is_valid () const { return blob; }
is_CIDOT::cff1::accelerator_templ_t1228     bool   is_CID () const { return topDict.is_CID (); }
1229 
is_predef_charsetOT::cff1::accelerator_templ_t1230     bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1231 
std_code_to_glyphOT::cff1::accelerator_templ_t1232     unsigned int std_code_to_glyph (hb_codepoint_t code) const
1233     {
1234       hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1235       if (unlikely (sid == CFF_UNDEF_SID))
1236 	return 0;
1237 
1238       if (charset != &Null (Charset))
1239 	return charset->get_glyph (sid, num_glyphs);
1240       else if ((topDict.CharsetOffset == ISOAdobeCharset)
1241 	      && (code <= 228 /*zcaron*/)) return sid;
1242       return 0;
1243     }
1244 
is_predef_encodingOT::cff1::accelerator_templ_t1245     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1246 
glyph_to_codeOT::cff1::accelerator_templ_t1247     hb_codepoint_t glyph_to_code (hb_codepoint_t glyph,
1248 				  code_pair_t *glyph_to_sid_cache = nullptr) const
1249     {
1250       if (encoding != &Null (Encoding))
1251 	return encoding->get_code (glyph);
1252       else
1253       {
1254 	hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache);
1255 	if (sid == 0) return 0;
1256 	hb_codepoint_t code = 0;
1257 	switch (topDict.EncodingOffset)
1258 	{
1259 	case StandardEncoding:
1260 	  code = lookup_standard_encoding_for_code (sid);
1261 	  break;
1262 	case ExpertEncoding:
1263 	  code = lookup_expert_encoding_for_code (sid);
1264 	  break;
1265 	default:
1266 	  break;
1267 	}
1268 	return code;
1269       }
1270     }
1271 
create_glyph_to_sid_mapOT::cff1::accelerator_templ_t1272     glyph_to_sid_map_t *create_glyph_to_sid_map () const
1273     {
1274       if (charset != &Null (Charset))
1275       {
1276 	auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t));
1277 	if (unlikely (!mapping)) return nullptr;
1278 	mapping = new (mapping) glyph_to_sid_map_t ();
1279 	mapping->push (code_pair_t {0, 1});
1280 	charset->collect_glyph_to_sid_map (mapping, num_glyphs);
1281 	return mapping;
1282       }
1283       else
1284 	return nullptr;
1285     }
1286 
glyph_to_sidOT::cff1::accelerator_templ_t1287     hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph,
1288 				 code_pair_t *cache = nullptr) const
1289     {
1290       if (charset != &Null (Charset))
1291 	return charset->get_sid (glyph, num_glyphs, cache);
1292       else
1293       {
1294 	hb_codepoint_t sid = 0;
1295 	switch (topDict.CharsetOffset)
1296 	{
1297 	  case ISOAdobeCharset:
1298 	    if (glyph <= 228 /*zcaron*/) sid = glyph;
1299 	    break;
1300 	  case ExpertCharset:
1301 	    sid = lookup_expert_charset_for_sid (glyph);
1302 	    break;
1303 	  case ExpertSubsetCharset:
1304 	      sid = lookup_expert_subset_charset_for_sid (glyph);
1305 	    break;
1306 	  default:
1307 	    break;
1308 	}
1309 	return sid;
1310       }
1311     }
1312 
sid_to_glyphOT::cff1::accelerator_templ_t1313     hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
1314     {
1315       if (charset != &Null (Charset))
1316 	return charset->get_glyph (sid, num_glyphs);
1317       else
1318       {
1319 	hb_codepoint_t glyph = 0;
1320 	switch (topDict.CharsetOffset)
1321 	{
1322 	  case ISOAdobeCharset:
1323 	    if (sid <= 228 /*zcaron*/) glyph = sid;
1324 	    break;
1325 	  case ExpertCharset:
1326 	    glyph = lookup_expert_charset_for_glyph (sid);
1327 	    break;
1328 	  case ExpertSubsetCharset:
1329 	    glyph = lookup_expert_subset_charset_for_glyph (sid);
1330 	    break;
1331 	  default:
1332 	    break;
1333 	}
1334 	return glyph;
1335       }
1336     }
1337 
1338     protected:
1339     hb_sanitize_context_t   sc;
1340 
1341     public:
1342     hb_blob_t               *blob = nullptr;
1343     const Encoding	    *encoding = nullptr;
1344     const Charset	    *charset = nullptr;
1345     const CFF1NameIndex     *nameIndex = nullptr;
1346     const CFF1TopDictIndex  *topDictIndex = nullptr;
1347     const CFF1StringIndex   *stringIndex = nullptr;
1348     const CFF1Subrs	    *globalSubrs = nullptr;
1349     const CFF1CharStrings   *charStrings = nullptr;
1350     const CFF1FDArray       *fdArray = nullptr;
1351     const CFF1FDSelect      *fdSelect = nullptr;
1352     unsigned int	     fdCount = 0;
1353 
1354     cff1_top_dict_values_t   topDict;
1355     hb_vector_t<cff1_font_dict_values_t>
1356 			     fontDicts;
1357     hb_vector_t<PRIVDICTVAL> privateDicts;
1358 
1359     unsigned int	     num_glyphs = 0;
1360     unsigned int	     num_charset_entries = 0;
1361   };
1362 
1363   struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1364   {
accelerator_tOT::cff1::accelerator_t1365     accelerator_t (hb_face_t *face) : SUPER (face)
1366     {
1367       glyph_names.set_relaxed (nullptr);
1368 
1369       if (!is_valid ()) return;
1370       if (is_CID ()) return;
1371     }
~accelerator_tOT::cff1::accelerator_t1372     ~accelerator_t ()
1373     {
1374       hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed ();
1375       if (names)
1376       {
1377 	names->fini ();
1378 	hb_free (names);
1379       }
1380     }
1381 
get_glyph_nameOT::cff1::accelerator_t1382     bool get_glyph_name (hb_codepoint_t glyph,
1383 			 char *buf, unsigned int buf_len) const
1384     {
1385       if (unlikely (glyph >= num_glyphs)) return false;
1386       if (unlikely (!is_valid ())) return false;
1387       if (is_CID()) return false;
1388       if (unlikely (!buf_len)) return true;
1389       hb_codepoint_t sid = glyph_to_sid (glyph);
1390       const char *str;
1391       size_t str_len;
1392       if (sid < cff1_std_strings_length)
1393       {
1394 	hb_bytes_t byte_str = cff1_std_strings (sid);
1395 	str = byte_str.arrayZ;
1396 	str_len = byte_str.length;
1397       }
1398       else
1399       {
1400 	hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
1401 	str = (const char *)ubyte_str.arrayZ;
1402 	str_len = ubyte_str.length;
1403       }
1404       if (!str_len) return false;
1405       unsigned int len = hb_min (buf_len - 1, str_len);
1406       strncpy (buf, (const char*)str, len);
1407       buf[len] = '\0';
1408       return true;
1409     }
1410 
get_glyph_from_nameOT::cff1::accelerator_t1411     bool get_glyph_from_name (const char *name, int len,
1412 			      hb_codepoint_t *glyph) const
1413     {
1414       if (unlikely (!is_valid ())) return false;
1415       if (is_CID()) return false;
1416       if (len < 0) len = strlen (name);
1417       if (unlikely (!len)) return false;
1418 
1419     retry:
1420       hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire ();
1421       if (unlikely (!names))
1422       {
1423 	names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
1424 	if (likely (names))
1425 	{
1426 	  names->init ();
1427 	  /* TODO */
1428 
1429 	  /* fill glyph names */
1430 	  code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
1431 	  for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
1432 	  {
1433 	    hb_codepoint_t	sid = glyph_to_sid (gid, &glyph_to_sid_cache);
1434 	    gname_t	gname;
1435 	    gname.sid = sid;
1436 	    if (sid < cff1_std_strings_length)
1437 	      gname.name = cff1_std_strings (sid);
1438 	    else
1439 	    {
1440 	      hb_ubytes_t	ustr = (*stringIndex)[sid - cff1_std_strings_length];
1441 	      gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length);
1442 	    }
1443 	    if (unlikely (!gname.name.arrayZ))
1444 	      gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */
1445 	    names->push (gname);
1446 	  }
1447 	  names->qsort ();
1448 	}
1449 	if (unlikely (!glyph_names.cmpexch (nullptr, names)))
1450 	{
1451 	  if (names)
1452 	  {
1453 	    names->fini ();
1454 	    hb_free (names);
1455 	  }
1456 	  goto retry;
1457 	}
1458       }
1459 
1460       gname_t key = { hb_bytes_t (name, len), 0 };
1461       const gname_t *gname = names ? names->bsearch (key) : nullptr;
1462       if (!gname) return false;
1463       hb_codepoint_t gid = sid_to_glyph (gname->sid);
1464       if (!gid && gname->sid) return false;
1465       *glyph = gid;
1466       return true;
1467     }
1468 
1469     HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1470     HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
1471     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
1472 
1473     private:
1474     struct gname_t
1475     {
1476       hb_bytes_t	name;
1477       uint16_t		sid;
1478 
cmpOT::cff1::accelerator_t::gname_t1479       static int cmp (const void *a_, const void *b_)
1480       {
1481 	const gname_t *a = (const gname_t *)a_;
1482 	const gname_t *b = (const gname_t *)b_;
1483 	unsigned minlen = hb_min (a->name.length, b->name.length);
1484 	int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
1485 	if (ret) return ret;
1486 	return a->name.length - b->name.length;
1487       }
1488 
cmpOT::cff1::accelerator_t::gname_t1489       int cmp (const gname_t &a) const { return cmp (&a, this); }
1490     };
1491 
1492     mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
1493 
1494     typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
1495   };
1496 
1497   struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t>
1498   {
accelerator_subset_tOT::cff1::accelerator_subset_t1499     accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
~accelerator_subset_tOT::cff1::accelerator_subset_t1500     ~accelerator_subset_t ()
1501     {
1502       if (cff_accelerator)
1503 	cff_subset_accelerator_t::destroy (cff_accelerator);
1504     }
1505 
1506     HB_INTERNAL bool subset (hb_subset_context_t *c) const;
1507     HB_INTERNAL bool serialize (hb_serialize_context_t *c,
1508 				struct cff1_subset_plan &plan) const;
1509     HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
1510 
1511     mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
1512 
1513     typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER;
1514   };
1515 
1516   protected:
1517   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
1518   HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
1519   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
1520   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
1521   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
1522   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
1523   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
1524 
1525   public:
1526   FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
1527   NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
1528   HBUINT8	       offSize;	  /* offset size (unused?) */
1529 
1530   public:
1531   DEFINE_SIZE_STATIC (4);
1532 };
1533 
1534 struct cff1_accelerator_t : cff1::accelerator_t {
cff1_accelerator_tOT::cff1_accelerator_t1535   cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
1536 };
1537 
1538 struct cff1_subset_accelerator_t : cff1::accelerator_subset_t {
cff1_subset_accelerator_tOT::cff1_subset_accelerator_t1539   cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {}
1540 };
1541 
1542 } /* namespace OT */
1543 
1544 #endif /* HB_OT_CFF1_TABLE_HH */
1545