xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-ot-cff1-table.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
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 CFF1Index          CFF1CharStrings;
55 typedef Subrs<HBUINT16>    CFF1Subrs;
56 
57 struct CFF1FDSelect : FDSelect {};
58 
59 /* Encoding */
60 struct Encoding0 {
sanitizeCFF::Encoding061   bool sanitize (hb_sanitize_context_t *c) const
62   {
63     TRACE_SANITIZE (this);
64     return_trace (codes.sanitize (c));
65   }
66 
get_codeCFF::Encoding067   hb_codepoint_t get_code (hb_codepoint_t glyph) const
68   {
69     assert (glyph > 0);
70     glyph--;
71     if (glyph < nCodes ())
72     {
73       return (hb_codepoint_t)codes[glyph];
74     }
75     else
76       return CFF_UNDEF_CODE;
77   }
78 
nCodesCFF::Encoding079   HBUINT8 &nCodes () { return codes.len; }
nCodesCFF::Encoding080   HBUINT8 nCodes () const { return codes.len; }
81 
82   ArrayOf<HBUINT8, HBUINT8> codes;
83 
84   DEFINE_SIZE_ARRAY_SIZED (1, codes);
85 };
86 
87 struct Encoding1_Range {
sanitizeCFF::Encoding1_Range88   bool sanitize (hb_sanitize_context_t *c) const
89   {
90     TRACE_SANITIZE (this);
91     return_trace (c->check_struct (this));
92   }
93 
94   HBUINT8   first;
95   HBUINT8   nLeft;
96 
97   DEFINE_SIZE_STATIC (2);
98 };
99 
100 struct Encoding1 {
sanitizeCFF::Encoding1101   bool sanitize (hb_sanitize_context_t *c) const
102   {
103     TRACE_SANITIZE (this);
104     return_trace (ranges.sanitize (c));
105   }
106 
get_codeCFF::Encoding1107   hb_codepoint_t get_code (hb_codepoint_t glyph) const
108   {
109     /* TODO: Add cache like get_sid. */
110     assert (glyph > 0);
111     glyph--;
112     for (unsigned int i = 0; i < nRanges (); i++)
113     {
114       if (glyph <= ranges[i].nLeft)
115       {
116 	hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
117 	return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
118       }
119       glyph -= (ranges[i].nLeft + 1);
120     }
121     return CFF_UNDEF_CODE;
122   }
123 
nRangesCFF::Encoding1124   HBUINT8 &nRanges () { return ranges.len; }
nRangesCFF::Encoding1125   HBUINT8 nRanges () const { return ranges.len; }
126 
127   ArrayOf<Encoding1_Range, HBUINT8> ranges;
128 
129   DEFINE_SIZE_ARRAY_SIZED (1, ranges);
130 };
131 
132 struct SuppEncoding {
sanitizeCFF::SuppEncoding133   bool sanitize (hb_sanitize_context_t *c) const
134   {
135     TRACE_SANITIZE (this);
136     return_trace (c->check_struct (this));
137   }
138 
139   HBUINT8   code;
140   HBUINT16  glyph;
141 
142   DEFINE_SIZE_STATIC (3);
143 };
144 
145 struct CFF1SuppEncData {
sanitizeCFF::CFF1SuppEncData146   bool sanitize (hb_sanitize_context_t *c) const
147   {
148     TRACE_SANITIZE (this);
149     return_trace (supps.sanitize (c));
150   }
151 
get_codesCFF::CFF1SuppEncData152   void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
153   {
154     for (unsigned int i = 0; i < nSups (); i++)
155       if (sid == supps[i].glyph)
156 	codes.push (supps[i].code);
157   }
158 
nSupsCFF::CFF1SuppEncData159   HBUINT8 &nSups () { return supps.len; }
nSupsCFF::CFF1SuppEncData160   HBUINT8 nSups () const { return supps.len; }
161 
162   ArrayOf<SuppEncoding, HBUINT8> supps;
163 
164   DEFINE_SIZE_ARRAY_SIZED (1, supps);
165 };
166 
167 struct Encoding
168 {
169   /* serialize a fullset Encoding */
serializeCFF::Encoding170   bool serialize (hb_serialize_context_t *c, const Encoding &src)
171   {
172     TRACE_SERIALIZE (this);
173     return_trace (c->embed (src));
174   }
175 
176   /* serialize a subset Encoding */
serializeCFF::Encoding177   bool serialize (hb_serialize_context_t *c,
178 		  uint8_t format,
179 		  unsigned int enc_count,
180 		  const hb_vector_t<code_pair_t>& code_ranges,
181 		  const hb_vector_t<code_pair_t>& supp_codes)
182   {
183     TRACE_SERIALIZE (this);
184     Encoding *dest = c->extend_min (this);
185     if (unlikely (!dest)) return_trace (false);
186     dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
187     switch (format) {
188     case 0:
189     {
190       Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
191       if (unlikely (!fmt0)) return_trace (false);
192       fmt0->nCodes () = enc_count;
193       unsigned int glyph = 0;
194       for (unsigned int i = 0; i < code_ranges.length; i++)
195       {
196 	hb_codepoint_t code = code_ranges[i].code;
197 	for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
198 	  fmt0->codes[glyph++] = code++;
199 	if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
200 	  return_trace (false);
201       }
202     }
203     break;
204 
205     case 1:
206     {
207       Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
208       if (unlikely (!fmt1)) return_trace (false);
209       fmt1->nRanges () = code_ranges.length;
210       for (unsigned int i = 0; i < code_ranges.length; i++)
211       {
212 	if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
213 	  return_trace (false);
214 	fmt1->ranges[i].first = code_ranges[i].code;
215 	fmt1->ranges[i].nLeft = code_ranges[i].glyph;
216       }
217     }
218     break;
219 
220     }
221 
222     if (supp_codes.length)
223     {
224       CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
225       if (unlikely (!suppData)) return_trace (false);
226       suppData->nSups () = supp_codes.length;
227       for (unsigned int i = 0; i < supp_codes.length; i++)
228       {
229 	suppData->supps[i].code = supp_codes[i].code;
230 	suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
231       }
232     }
233 
234     return_trace (true);
235   }
236 
get_sizeCFF::Encoding237   unsigned int get_size () const
238   {
239     unsigned int size = min_size;
240     switch (table_format ())
241     {
242     case 0: hb_barrier (); size += u.format0.get_size (); break;
243     case 1: hb_barrier (); size += u.format1.get_size (); break;
244     }
245     if (has_supplement ())
246       size += suppEncData ().get_size ();
247     return size;
248   }
249 
get_codeCFF::Encoding250   hb_codepoint_t get_code (hb_codepoint_t glyph) const
251   {
252     switch (table_format ())
253     {
254     case 0: hb_barrier (); return u.format0.get_code (glyph);
255     case 1: hb_barrier (); return u.format1.get_code (glyph);
256     default:return 0;
257     }
258   }
259 
table_formatCFF::Encoding260   uint8_t table_format () const { return format & 0x7F; }
has_supplementCFF::Encoding261   bool  has_supplement () const { return format & 0x80; }
262 
get_supplement_codesCFF::Encoding263   void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
264   {
265     codes.resize (0);
266     if (has_supplement ())
267       suppEncData().get_codes (sid, codes);
268   }
269 
sanitizeCFF::Encoding270   bool sanitize (hb_sanitize_context_t *c) const
271   {
272     TRACE_SANITIZE (this);
273     if (unlikely (!c->check_struct (this)))
274       return_trace (false);
275     hb_barrier ();
276 
277     switch (table_format ())
278     {
279     case 0: hb_barrier (); if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
280     case 1: hb_barrier (); if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
281     default:return_trace (false);
282     }
283     return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
284   }
285 
286   protected:
suppEncDataCFF::Encoding287   const CFF1SuppEncData &suppEncData () const
288   {
289     switch (table_format ())
290     {
291     case 0: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
292     case 1: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
293     default:return Null (CFF1SuppEncData);
294     }
295   }
296 
297   public:
298   HBUINT8	format;
299   union {
300   Encoding0	format0;
301   Encoding1	format1;
302   } u;
303   /* CFF1SuppEncData  suppEncData; */
304 
305   DEFINE_SIZE_MIN (1);
306 };
307 
308 /* Charset */
309 struct Charset0
310 {
sanitizeCFF::Charset0311   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
312   {
313     TRACE_SANITIZE (this);
314     if (num_charset_entries) *num_charset_entries = num_glyphs;
315     return_trace (sids.sanitize (c, num_glyphs - 1));
316   }
317 
get_sidCFF::Charset0318   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
319   {
320     if (unlikely (glyph >= num_glyphs)) return 0;
321     if (unlikely (glyph == 0))
322       return 0;
323     else
324       return sids[glyph - 1];
325   }
326 
collect_glyph_to_sid_mapCFF::Charset0327   void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
328   {
329     mapping->resize (num_glyphs, false);
330     for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
331       mapping->arrayZ[gid] = {sids[gid - 1], gid};
332   }
333 
get_glyphCFF::Charset0334   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
335   {
336     if (sid == 0)
337       return 0;
338 
339     for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
340     {
341       if (sids[glyph-1] == sid)
342 	return glyph;
343     }
344     return 0;
345   }
346 
get_sizeCFF::Charset0347   static unsigned int get_size (unsigned int num_glyphs)
348   {
349     assert (num_glyphs > 0);
350     return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1);
351   }
352 
353   UnsizedArrayOf<HBUINT16> sids;
354 
355   DEFINE_SIZE_ARRAY(0, sids);
356 };
357 
358 template <typename TYPE>
359 struct Charset_Range {
sanitizeCFF::Charset_Range360   bool sanitize (hb_sanitize_context_t *c) const
361   {
362     TRACE_SANITIZE (this);
363     return_trace (c->check_struct (this));
364   }
365 
366   HBUINT16  first;
367   TYPE      nLeft;
368 
369   DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
370 };
371 
372 template <typename TYPE>
373 struct Charset1_2 {
sanitizeCFF::Charset1_2374   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
375   {
376     TRACE_SANITIZE (this);
377     num_glyphs--;
378     unsigned i;
379     for (i = 0; num_glyphs > 0; i++)
380     {
381       if (unlikely (!(ranges[i].sanitize (c) &&
382 		      hb_barrier () &&
383 		      (num_glyphs >= ranges[i].nLeft + 1))))
384 	return_trace (false);
385       num_glyphs -= (ranges[i].nLeft + 1);
386     }
387     if (num_charset_entries)
388       *num_charset_entries = i;
389     return_trace (true);
390   }
391 
get_sidCFF::Charset1_2392   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs,
393 			  code_pair_t *cache = nullptr) const
394   {
395     if (unlikely (glyph >= num_glyphs)) return 0;
396     unsigned i;
397     hb_codepoint_t start_glyph;
398     if (cache && likely (cache->glyph <= glyph))
399     {
400       i = cache->code;
401       start_glyph = cache->glyph;
402     }
403     else
404     {
405       if (unlikely (glyph == 0)) return 0;
406       i = 0;
407       start_glyph = 1;
408     }
409     glyph -= start_glyph;
410     for (;; i++)
411     {
412       unsigned count = ranges[i].nLeft;
413       if (glyph <= count)
414       {
415         if (cache)
416 	  *cache = {i, start_glyph};
417 	return ranges[i].first + glyph;
418       }
419       count++;
420       start_glyph += count;
421       glyph -= count;
422     }
423 
424     return 0;
425   }
426 
collect_glyph_to_sid_mapCFF::Charset1_2427   void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
428   {
429     mapping->resize (num_glyphs, false);
430     hb_codepoint_t gid = 1;
431     if (gid >= num_glyphs)
432       return;
433     for (unsigned i = 0;; i++)
434     {
435       hb_codepoint_t sid = ranges[i].first;
436       unsigned count = ranges[i].nLeft + 1;
437       unsigned last = gid + count;
438       for (unsigned j = 0; j < count; j++)
439 	mapping->arrayZ[gid++] = {sid++, last - 1};
440 
441       if (gid >= num_glyphs)
442         break;
443     }
444   }
445 
get_glyphCFF::Charset1_2446   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
447   {
448     if (sid == 0) return 0;
449     hb_codepoint_t  glyph = 1;
450     for (unsigned int i = 0;; i++)
451     {
452       if (glyph >= num_glyphs)
453 	return 0;
454       if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
455 	return glyph + (sid - ranges[i].first);
456       glyph += (ranges[i].nLeft + 1);
457     }
458 
459     return 0;
460   }
461 
get_sizeCFF::Charset1_2462   unsigned int get_size (unsigned int num_glyphs) const
463   {
464     int glyph = (int) num_glyphs;
465     unsigned num_ranges = 0;
466 
467     assert (glyph > 0);
468     glyph--;
469     for (unsigned int i = 0; glyph > 0; i++)
470     {
471       glyph -= (ranges[i].nLeft + 1);
472       num_ranges++;
473     }
474 
475     return get_size_for_ranges (num_ranges);
476   }
477 
get_size_for_rangesCFF::Charset1_2478   static unsigned int get_size_for_ranges (unsigned int num_ranges)
479   {
480     return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges);
481   }
482 
483   UnsizedArrayOf<Charset_Range<TYPE>> ranges;
484 
485   DEFINE_SIZE_ARRAY (0, ranges);
486 };
487 
488 typedef Charset1_2<HBUINT8>     Charset1;
489 typedef Charset1_2<HBUINT16>    Charset2;
490 typedef Charset_Range<HBUINT8>  Charset1_Range;
491 typedef Charset_Range<HBUINT16> Charset2_Range;
492 
493 struct Charset
494 {
495   /* serialize a fullset Charset */
serializeCFF::Charset496   bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
497   {
498     TRACE_SERIALIZE (this);
499     return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs)));
500   }
501 
502   /* serialize a subset Charset */
serializeCFF::Charset503   bool serialize (hb_serialize_context_t *c,
504 		  uint8_t format,
505 		  unsigned int num_glyphs,
506 		  const hb_vector_t<code_pair_t>& sid_ranges)
507   {
508     TRACE_SERIALIZE (this);
509     Charset *dest = c->extend_min (this);
510     if (unlikely (!dest)) return_trace (false);
511     dest->format = format;
512     switch (format)
513     {
514     case 0:
515     {
516       Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false);
517       if (unlikely (!fmt0)) return_trace (false);
518       unsigned int glyph = 0;
519       for (unsigned int i = 0; i < sid_ranges.length; i++)
520       {
521 	hb_codepoint_t sid = sid_ranges.arrayZ[i].code;
522 	for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--)
523 	  fmt0->sids[glyph++] = sid++;
524       }
525     }
526     break;
527 
528     case 1:
529     {
530       Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false);
531       if (unlikely (!fmt1)) return_trace (false);
532       hb_codepoint_t all_glyphs = 0;
533       for (unsigned int i = 0; i < sid_ranges.length; i++)
534       {
535         auto &_ = sid_ranges.arrayZ[i];
536         all_glyphs |= _.glyph;
537 	fmt1->ranges[i].first = _.code;
538 	fmt1->ranges[i].nLeft = _.glyph;
539       }
540       if (unlikely (!(all_glyphs <= 0xFF)))
541 	return_trace (false);
542     }
543     break;
544 
545     case 2:
546     {
547       Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false);
548       if (unlikely (!fmt2)) return_trace (false);
549       hb_codepoint_t all_glyphs = 0;
550       for (unsigned int i = 0; i < sid_ranges.length; i++)
551       {
552         auto &_ = sid_ranges.arrayZ[i];
553         all_glyphs |= _.glyph;
554 	fmt2->ranges[i].first = _.code;
555 	fmt2->ranges[i].nLeft = _.glyph;
556       }
557       if (unlikely (!(all_glyphs <= 0xFFFF)))
558 	return_trace (false);
559     }
560     break;
561 
562     }
563     return_trace (true);
564   }
565 
get_sizeCFF::Charset566   unsigned int get_size (unsigned int num_glyphs) const
567   {
568     switch (format)
569     {
570     case 0: hb_barrier (); return min_size + u.format0.get_size (num_glyphs);
571     case 1: hb_barrier (); return min_size + u.format1.get_size (num_glyphs);
572     case 2: hb_barrier (); return min_size + u.format2.get_size (num_glyphs);
573     default:return 0;
574     }
575   }
576 
get_sidCFF::Charset577   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs,
578 			  code_pair_t *cache = nullptr) const
579   {
580     switch (format)
581     {
582     case 0: hb_barrier (); return u.format0.get_sid (glyph, num_glyphs);
583     case 1: hb_barrier (); return u.format1.get_sid (glyph, num_glyphs, cache);
584     case 2: hb_barrier (); return u.format2.get_sid (glyph, num_glyphs, cache);
585     default:return 0;
586     }
587   }
588 
collect_glyph_to_sid_mapCFF::Charset589   void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
590   {
591     switch (format)
592     {
593     case 0: hb_barrier (); u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
594     case 1: hb_barrier (); u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
595     case 2: hb_barrier (); u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
596     default:return;
597     }
598   }
599 
get_glyphCFF::Charset600   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
601   {
602     switch (format)
603     {
604     case 0: hb_barrier (); return u.format0.get_glyph (sid, num_glyphs);
605     case 1: hb_barrier (); return u.format1.get_glyph (sid, num_glyphs);
606     case 2: hb_barrier (); return u.format2.get_glyph (sid, num_glyphs);
607     default:return 0;
608     }
609   }
610 
sanitizeCFF::Charset611   bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const
612   {
613     TRACE_SANITIZE (this);
614     if (unlikely (!c->check_struct (this)))
615       return_trace (false);
616     hb_barrier ();
617 
618     switch (format)
619     {
620     case 0: hb_barrier (); return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
621     case 1: hb_barrier (); return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
622     case 2: hb_barrier (); return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
623     default:return_trace (false);
624     }
625   }
626 
627   HBUINT8       format;
628   union {
629     Charset0    format0;
630     Charset1    format1;
631     Charset2    format2;
632   } u;
633 
634   DEFINE_SIZE_MIN (1);
635 };
636 
637 struct CFF1StringIndex : CFF1Index
638 {
serializeCFF::CFF1StringIndex639   bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
640 		  const hb_vector_t<unsigned> &sidmap)
641   {
642     TRACE_SERIALIZE (this);
643     if (unlikely ((strings.count == 0) || (sidmap.length == 0)))
644     {
645       if (unlikely (!c->extend_min (this->count)))
646 	return_trace (false);
647       count = 0;
648       return_trace (true);
649     }
650 
651     if (unlikely (sidmap.in_error ())) return_trace (false);
652 
653     // Save this in a vector since serialize() iterates it twice.
654     hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap)
655 					 | hb_map (strings));
656 
657     if (unlikely (bytesArray.in_error ())) return_trace (false);
658 
659     bool result = CFF1Index::serialize (c, bytesArray);
660     return_trace (result);
661   }
662 };
663 
664 struct cff1_top_dict_interp_env_t : num_interp_env_t
665 {
cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t666   cff1_top_dict_interp_env_t ()
667     : num_interp_env_t(), prev_offset(0), last_offset(0) {}
cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t668   cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes)
669     : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {}
670 
671   unsigned int prev_offset;
672   unsigned int last_offset;
673 };
674 
675 struct name_dict_values_t
676 {
677   enum name_dict_val_index_t
678   {
679       version,
680       notice,
681       copyright,
682       fullName,
683       familyName,
684       weight,
685       postscript,
686       fontName,
687       baseFontName,
688       registry,
689       ordering,
690 
691       ValCount
692   };
693 
initCFF::name_dict_values_t694   void init ()
695   {
696     for (unsigned int i = 0; i < ValCount; i++)
697       values[i] = CFF_UNDEF_SID;
698   }
699 
operator []CFF::name_dict_values_t700   unsigned int& operator[] (unsigned int i)
701   { assert (i < ValCount); return values[i]; }
702 
operator []CFF::name_dict_values_t703   unsigned int operator[] (unsigned int i) const
704   { assert (i < ValCount); return values[i]; }
705 
name_op_to_indexCFF::name_dict_values_t706   static enum name_dict_val_index_t name_op_to_index (op_code_t op)
707   {
708     switch (op) {
709       default: // can't happen - just make some compiler happy
710       case OpCode_version:
711 	return version;
712       case OpCode_Notice:
713 	return notice;
714       case OpCode_Copyright:
715 	return copyright;
716       case OpCode_FullName:
717 	return fullName;
718       case OpCode_FamilyName:
719 	return familyName;
720       case OpCode_Weight:
721 	return weight;
722       case OpCode_PostScript:
723 	return postscript;
724       case OpCode_FontName:
725 	return fontName;
726       case OpCode_BaseFontName:
727 	return baseFontName;
728     }
729   }
730 
731   unsigned int  values[ValCount];
732 };
733 
734 struct cff1_top_dict_val_t : op_str_t
735 {
736   unsigned int  last_arg_offset;
737 };
738 
739 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
740 {
initCFF::cff1_top_dict_values_t741   void init ()
742   {
743     top_dict_values_t<cff1_top_dict_val_t>::init ();
744 
745     nameSIDs.init ();
746     ros_supplement = 0;
747     cidCount = 8720;
748     EncodingOffset = 0;
749     CharsetOffset = 0;
750     FDSelectOffset = 0;
751     privateDictInfo.init ();
752   }
finiCFF::cff1_top_dict_values_t753   void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
754 
is_CIDCFF::cff1_top_dict_values_t755   bool is_CID () const
756   { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
757 
758   name_dict_values_t  nameSIDs;
759   unsigned int    ros_supplement_offset;
760   unsigned int    ros_supplement;
761   unsigned int    cidCount;
762 
763   int             EncodingOffset;
764   int             CharsetOffset;
765   int             FDSelectOffset;
766   table_info_t    privateDictInfo;
767 };
768 
769 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
770 {
process_opCFF::cff1_top_dict_opset_t771   static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
772   {
773     cff1_top_dict_val_t  val;
774     val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
775 
776     switch (op) {
777       case OpCode_version:
778       case OpCode_Notice:
779       case OpCode_Copyright:
780       case OpCode_FullName:
781       case OpCode_FontName:
782       case OpCode_FamilyName:
783       case OpCode_Weight:
784       case OpCode_PostScript:
785       case OpCode_BaseFontName:
786 	dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
787 	env.clear_args ();
788 	break;
789       case OpCode_isFixedPitch:
790       case OpCode_ItalicAngle:
791       case OpCode_UnderlinePosition:
792       case OpCode_UnderlineThickness:
793       case OpCode_PaintType:
794       case OpCode_CharstringType:
795       case OpCode_UniqueID:
796       case OpCode_StrokeWidth:
797       case OpCode_SyntheticBase:
798       case OpCode_CIDFontVersion:
799       case OpCode_CIDFontRevision:
800       case OpCode_CIDFontType:
801       case OpCode_UIDBase:
802       case OpCode_FontBBox:
803       case OpCode_XUID:
804       case OpCode_BaseFontBlend:
805 	env.clear_args ();
806 	break;
807 
808       case OpCode_CIDCount:
809 	dictval.cidCount = env.argStack.pop_uint ();
810 	env.clear_args ();
811 	break;
812 
813       case OpCode_ROS:
814 	dictval.ros_supplement = env.argStack.pop_uint ();
815 	dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
816 	dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
817 	env.clear_args ();
818 	break;
819 
820       case OpCode_Encoding:
821 	dictval.EncodingOffset = env.argStack.pop_int ();
822 	env.clear_args ();
823 	if (unlikely (dictval.EncodingOffset == 0)) return;
824 	break;
825 
826       case OpCode_charset:
827 	dictval.CharsetOffset = env.argStack.pop_int ();
828 	env.clear_args ();
829 	if (unlikely (dictval.CharsetOffset == 0)) return;
830 	break;
831 
832       case OpCode_FDSelect:
833 	dictval.FDSelectOffset = env.argStack.pop_int ();
834 	env.clear_args ();
835 	break;
836 
837       case OpCode_Private:
838 	dictval.privateDictInfo.offset = env.argStack.pop_int ();
839 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
840 	env.clear_args ();
841 	break;
842 
843       default:
844 	env.last_offset = env.str_ref.get_offset ();
845 	top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
846 	/* Record this operand below if stack is empty, otherwise done */
847 	if (!env.argStack.is_empty ()) return;
848 	break;
849     }
850 
851     if (unlikely (env.in_error ())) return;
852 
853     dictval.add_op (op, env.str_ref, val);
854   }
855 };
856 
857 struct cff1_font_dict_values_t : dict_values_t<op_str_t>
858 {
initCFF::cff1_font_dict_values_t859   void init ()
860   {
861     dict_values_t<op_str_t>::init ();
862     privateDictInfo.init ();
863     fontName = CFF_UNDEF_SID;
864   }
finiCFF::cff1_font_dict_values_t865   void fini () { dict_values_t<op_str_t>::fini (); }
866 
867   table_info_t       privateDictInfo;
868   unsigned int    fontName;
869 };
870 
871 struct cff1_font_dict_opset_t : dict_opset_t
872 {
process_opCFF::cff1_font_dict_opset_t873   static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
874   {
875     switch (op) {
876       case OpCode_FontName:
877 	dictval.fontName = env.argStack.pop_uint ();
878 	env.clear_args ();
879 	break;
880       case OpCode_FontMatrix:
881       case OpCode_PaintType:
882 	env.clear_args ();
883 	break;
884       case OpCode_Private:
885 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
886 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
887 	env.clear_args ();
888 	break;
889 
890       default:
891 	dict_opset_t::process_op (op, env);
892 	if (!env.argStack.is_empty ()) return;
893 	break;
894     }
895 
896     if (unlikely (env.in_error ())) return;
897 
898     dictval.add_op (op, env.str_ref);
899   }
900 };
901 
902 template <typename VAL>
903 struct cff1_private_dict_values_base_t : dict_values_t<VAL>
904 {
initCFF::cff1_private_dict_values_base_t905   void init ()
906   {
907     dict_values_t<VAL>::init ();
908     subrsOffset = 0;
909     localSubrs = &Null (CFF1Subrs);
910   }
finiCFF::cff1_private_dict_values_base_t911   void fini () { dict_values_t<VAL>::fini (); }
912 
913   int                 subrsOffset;
914   const CFF1Subrs    *localSubrs;
915 };
916 
917 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
918 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
919 
920 struct cff1_private_dict_opset_t : dict_opset_t
921 {
process_opCFF::cff1_private_dict_opset_t922   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
923   {
924     num_dict_val_t val;
925     val.init ();
926 
927     switch (op) {
928       case OpCode_BlueValues:
929       case OpCode_OtherBlues:
930       case OpCode_FamilyBlues:
931       case OpCode_FamilyOtherBlues:
932       case OpCode_StemSnapH:
933       case OpCode_StemSnapV:
934       case OpCode_StdHW:
935       case OpCode_StdVW:
936       case OpCode_BlueScale:
937       case OpCode_BlueShift:
938       case OpCode_BlueFuzz:
939       case OpCode_ForceBold:
940       case OpCode_LanguageGroup:
941       case OpCode_ExpansionFactor:
942       case OpCode_initialRandomSeed:
943       case OpCode_defaultWidthX:
944       case OpCode_nominalWidthX:
945 	env.clear_args ();
946 	break;
947       case OpCode_Subrs:
948 	dictval.subrsOffset = env.argStack.pop_int ();
949 	env.clear_args ();
950 	break;
951 
952       default:
953 	dict_opset_t::process_op (op, env);
954 	if (!env.argStack.is_empty ()) return;
955 	break;
956     }
957 
958     if (unlikely (env.in_error ())) return;
959 
960     dictval.add_op (op, env.str_ref, val);
961   }
962 };
963 
964 struct cff1_private_dict_opset_subset_t : dict_opset_t
965 {
process_opCFF::cff1_private_dict_opset_subset_t966   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
967   {
968     switch (op) {
969       case OpCode_BlueValues:
970       case OpCode_OtherBlues:
971       case OpCode_FamilyBlues:
972       case OpCode_FamilyOtherBlues:
973       case OpCode_StemSnapH:
974       case OpCode_StemSnapV:
975       case OpCode_StdHW:
976       case OpCode_StdVW:
977       case OpCode_BlueScale:
978       case OpCode_BlueShift:
979       case OpCode_BlueFuzz:
980       case OpCode_ForceBold:
981       case OpCode_LanguageGroup:
982       case OpCode_ExpansionFactor:
983       case OpCode_initialRandomSeed:
984       case OpCode_defaultWidthX:
985       case OpCode_nominalWidthX:
986 	env.clear_args ();
987 	break;
988 
989       case OpCode_Subrs:
990 	dictval.subrsOffset = env.argStack.pop_int ();
991 	env.clear_args ();
992 	break;
993 
994       default:
995 	dict_opset_t::process_op (op, env);
996 	if (!env.argStack.is_empty ()) return;
997 	break;
998     }
999 
1000     if (unlikely (env.in_error ())) return;
1001 
1002     dictval.add_op (op, env.str_ref);
1003   }
1004 };
1005 
1006 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;
1007 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
1008 
1009 typedef CFF1Index CFF1NameIndex;
1010 typedef CFF1Index CFF1TopDictIndex;
1011 
1012 struct cff1_font_dict_values_mod_t
1013 {
cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t1014   cff1_font_dict_values_mod_t() { init (); }
1015 
initCFF::cff1_font_dict_values_mod_t1016   void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
1017 
initCFF::cff1_font_dict_values_mod_t1018   void init (const cff1_font_dict_values_t *base_,
1019 	     unsigned int fontName_)
1020   {
1021     base = base_;
1022     fontName = fontName_;
1023     privateDictInfo.init ();
1024   }
1025 
get_countCFF::cff1_font_dict_values_mod_t1026   unsigned get_count () const { return base->get_count (); }
1027 
operator []CFF::cff1_font_dict_values_mod_t1028   const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
1029 
1030   const cff1_font_dict_values_t    *base;
1031   table_info_t		   privateDictInfo;
1032   unsigned int		fontName;
1033 };
1034 
1035 struct CFF1FDArray : FDArray<HBUINT16>
1036 {
1037   /* FDArray::serialize() requires this partial specialization to compile */
1038   template <typename ITER, typename OP_SERIALIZER>
serializeCFF::CFF1FDArray1039   bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
1040   { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
1041 };
1042 
1043 } /* namespace CFF */
1044 
1045 namespace OT {
1046 
1047 using namespace CFF;
1048 
1049 struct cff1
1050 {
1051   static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1;
1052 
sanitizeOT::cff11053   bool sanitize (hb_sanitize_context_t *c) const
1054   {
1055     TRACE_SANITIZE (this);
1056     return_trace (c->check_struct (this) &&
1057 		  hb_barrier () &&
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       hb_barrier ();
1089 
1090       topDictIndex = &StructAtOffsetOrNull<CFF1TopDictIndex> (nameIndex, nameIndex->get_size (), sc);
1091       if (topDictIndex == &Null (CFF1TopDictIndex) || (topDictIndex->count == 0))
1092         goto fail;
1093       hb_barrier ();
1094 
1095       { /* parse top dict */
1096 	const hb_ubytes_t topDictStr = (*topDictIndex)[0];
1097 	if (unlikely (!topDictStr.sanitize (&sc)))   goto fail;
1098 	hb_barrier ();
1099 	cff1_top_dict_interp_env_t env (topDictStr);
1100 	cff1_top_dict_interpreter_t top_interp (env);
1101 	if (unlikely (!top_interp.interpret (topDict)))   goto fail;
1102       }
1103 
1104       if (is_predef_charset ())
1105 	charset = &Null (Charset);
1106       else
1107       {
1108 	charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset, sc, &num_charset_entries);
1109 	if (unlikely (charset == &Null (Charset)))   goto fail;
1110       }
1111 
1112       fdCount = 1;
1113       if (is_CID ())
1114       {
1115 	fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset, sc);
1116 	fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset, sc, fdArray->count);
1117 	if (unlikely (fdArray == &Null (CFF1FDArray) ||
1118 		      fdSelect == &Null (CFF1FDSelect)))
1119 	  goto fail;
1120 
1121 	fdCount = fdArray->count;
1122       }
1123       else
1124       {
1125 	fdArray = &Null (CFF1FDArray);
1126 	fdSelect = &Null (CFF1FDSelect);
1127       }
1128 
1129       encoding = &Null (Encoding);
1130       if (is_CID ())
1131       {
1132 	if (unlikely (charset == &Null (Charset)))   goto fail;
1133       }
1134       else
1135       {
1136 	if (!is_predef_encoding ())
1137 	{
1138 	  encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset, sc);
1139 	  if (unlikely (encoding == &Null (Encoding)))   goto fail;
1140 	}
1141       }
1142 
1143       stringIndex = &StructAtOffsetOrNull<CFF1StringIndex> (topDictIndex, topDictIndex->get_size (), sc);
1144       if (stringIndex == &Null (CFF1StringIndex))
1145         goto fail;
1146 
1147       globalSubrs = &StructAtOffsetOrNull<CFF1Subrs> (stringIndex, stringIndex->get_size (), sc);
1148       charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset, sc);
1149       if (charStrings == &Null (CFF1CharStrings))
1150         goto fail;
1151 
1152       num_glyphs = charStrings->count;
1153       if (num_glyphs != sc.get_num_glyphs ())
1154         goto fail;
1155 
1156       if (unlikely (!privateDicts.resize (fdCount)))
1157         goto fail;
1158       for (unsigned int i = 0; i < fdCount; i++)
1159 	privateDicts[i].init ();
1160 
1161       // parse CID font dicts and gather private dicts
1162       if (is_CID ())
1163       {
1164 	for (unsigned int i = 0; i < fdCount; i++)
1165 	{
1166 	  hb_ubytes_t fontDictStr = (*fdArray)[i];
1167 	  if (unlikely (!fontDictStr.sanitize (&sc)))   goto fail;
1168 	  hb_barrier ();
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 = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
1179 	  if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) 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, sc);
1186 	}
1187       }
1188       else  /* non-CID */
1189       {
1190 	cff1_top_dict_values_t *font = &topDict;
1191 	PRIVDICTVAL *priv = &privateDicts[0];
1192 
1193 	const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
1194 	if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
1195 	num_interp_env_t env (privDictStr);
1196 	dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
1197 	priv->init ();
1198 	if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
1199 
1200 	priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc);
1201 	hb_barrier ();
1202       }
1203 
1204       return;
1205 
1206       fail:
1207         _fini ();
1208     }
~accelerator_templ_tOT::cff1::accelerator_templ_t1209     ~accelerator_templ_t () { _fini (); }
_finiOT::cff1::accelerator_templ_t1210     void _fini ()
1211     {
1212       sc.end_processing ();
1213       topDict.fini ();
1214       fontDicts.fini ();
1215       privateDicts.fini ();
1216       hb_blob_destroy (blob);
1217       blob = nullptr;
1218     }
1219 
get_blobOT::cff1::accelerator_templ_t1220     hb_blob_t *get_blob () const { return blob; }
1221 
is_validOT::cff1::accelerator_templ_t1222     bool is_valid () const { return blob; }
is_CIDOT::cff1::accelerator_templ_t1223     bool   is_CID () const { return topDict.is_CID (); }
1224 
is_predef_charsetOT::cff1::accelerator_templ_t1225     bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1226 
std_code_to_glyphOT::cff1::accelerator_templ_t1227     unsigned int std_code_to_glyph (hb_codepoint_t code) const
1228     {
1229       hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1230       if (unlikely (sid == CFF_UNDEF_SID))
1231 	return 0;
1232 
1233       if (charset != &Null (Charset))
1234 	return charset->get_glyph (sid, num_glyphs);
1235       else if ((topDict.CharsetOffset == ISOAdobeCharset)
1236 	      && (code <= 228 /*zcaron*/)) return sid;
1237       return 0;
1238     }
1239 
is_predef_encodingOT::cff1::accelerator_templ_t1240     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1241 
glyph_to_codeOT::cff1::accelerator_templ_t1242     hb_codepoint_t glyph_to_code (hb_codepoint_t glyph,
1243 				  code_pair_t *glyph_to_sid_cache = nullptr) const
1244     {
1245       if (encoding != &Null (Encoding))
1246 	return encoding->get_code (glyph);
1247       else
1248       {
1249 	hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache);
1250 	if (sid == 0) return 0;
1251 	hb_codepoint_t code = 0;
1252 	switch (topDict.EncodingOffset)
1253 	{
1254 	case StandardEncoding:
1255 	  code = lookup_standard_encoding_for_code (sid);
1256 	  break;
1257 	case ExpertEncoding:
1258 	  code = lookup_expert_encoding_for_code (sid);
1259 	  break;
1260 	default:
1261 	  break;
1262 	}
1263 	return code;
1264       }
1265     }
1266 
create_glyph_to_sid_mapOT::cff1::accelerator_templ_t1267     glyph_to_sid_map_t *create_glyph_to_sid_map () const
1268     {
1269       if (charset != &Null (Charset))
1270       {
1271 	auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t));
1272 	if (unlikely (!mapping)) return nullptr;
1273 	mapping = new (mapping) glyph_to_sid_map_t ();
1274 	mapping->push (code_pair_t {0, 1});
1275 	charset->collect_glyph_to_sid_map (mapping, num_glyphs);
1276 	return mapping;
1277       }
1278       else
1279 	return nullptr;
1280     }
1281 
glyph_to_sidOT::cff1::accelerator_templ_t1282     hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph,
1283 				 code_pair_t *cache = nullptr) const
1284     {
1285       if (charset != &Null (Charset))
1286 	return charset->get_sid (glyph, num_glyphs, cache);
1287       else
1288       {
1289 	hb_codepoint_t sid = 0;
1290 	switch (topDict.CharsetOffset)
1291 	{
1292 	  case ISOAdobeCharset:
1293 	    if (glyph <= 228 /*zcaron*/) sid = glyph;
1294 	    break;
1295 	  case ExpertCharset:
1296 	    sid = lookup_expert_charset_for_sid (glyph);
1297 	    break;
1298 	  case ExpertSubsetCharset:
1299 	      sid = lookup_expert_subset_charset_for_sid (glyph);
1300 	    break;
1301 	  default:
1302 	    break;
1303 	}
1304 	return sid;
1305       }
1306     }
1307 
sid_to_glyphOT::cff1::accelerator_templ_t1308     hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
1309     {
1310       if (charset != &Null (Charset))
1311 	return charset->get_glyph (sid, num_glyphs);
1312       else
1313       {
1314 	hb_codepoint_t glyph = 0;
1315 	switch (topDict.CharsetOffset)
1316 	{
1317 	  case ISOAdobeCharset:
1318 	    if (sid <= 228 /*zcaron*/) glyph = sid;
1319 	    break;
1320 	  case ExpertCharset:
1321 	    glyph = lookup_expert_charset_for_glyph (sid);
1322 	    break;
1323 	  case ExpertSubsetCharset:
1324 	    glyph = lookup_expert_subset_charset_for_glyph (sid);
1325 	    break;
1326 	  default:
1327 	    break;
1328 	}
1329 	return glyph;
1330       }
1331     }
1332 
1333     protected:
1334     hb_sanitize_context_t   sc;
1335 
1336     public:
1337     hb_blob_t               *blob = nullptr;
1338     const Encoding	    *encoding = nullptr;
1339     const Charset	    *charset = nullptr;
1340     const CFF1NameIndex     *nameIndex = nullptr;
1341     const CFF1TopDictIndex  *topDictIndex = nullptr;
1342     const CFF1StringIndex   *stringIndex = nullptr;
1343     const CFF1Subrs	    *globalSubrs = nullptr;
1344     const CFF1CharStrings   *charStrings = nullptr;
1345     const CFF1FDArray       *fdArray = nullptr;
1346     const CFF1FDSelect      *fdSelect = nullptr;
1347     unsigned int	     fdCount = 0;
1348 
1349     cff1_top_dict_values_t   topDict;
1350     hb_vector_t<cff1_font_dict_values_t>
1351 			     fontDicts;
1352     hb_vector_t<PRIVDICTVAL> privateDicts;
1353 
1354     unsigned int	     num_glyphs = 0;
1355     unsigned int	     num_charset_entries = 0;
1356   };
1357 
1358   struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1359   {
accelerator_tOT::cff1::accelerator_t1360     accelerator_t (hb_face_t *face) : SUPER (face)
1361     {
1362       glyph_names.set_relaxed (nullptr);
1363 
1364       if (!is_valid ()) return;
1365       if (is_CID ()) return;
1366     }
~accelerator_tOT::cff1::accelerator_t1367     ~accelerator_t ()
1368     {
1369       hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed ();
1370       if (names)
1371       {
1372 	names->fini ();
1373 	hb_free (names);
1374       }
1375     }
1376 
get_glyph_nameOT::cff1::accelerator_t1377     bool get_glyph_name (hb_codepoint_t glyph,
1378 			 char *buf, unsigned int buf_len) const
1379     {
1380       if (unlikely (glyph >= num_glyphs)) return false;
1381       if (unlikely (!is_valid ())) return false;
1382       if (is_CID()) return false;
1383       if (unlikely (!buf_len)) return true;
1384       hb_codepoint_t sid = glyph_to_sid (glyph);
1385       const char *str;
1386       size_t str_len;
1387       if (sid < cff1_std_strings_length)
1388       {
1389 	hb_bytes_t byte_str = cff1_std_strings (sid);
1390 	str = byte_str.arrayZ;
1391 	str_len = byte_str.length;
1392       }
1393       else
1394       {
1395 	hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
1396 	str = (const char *)ubyte_str.arrayZ;
1397 	str_len = ubyte_str.length;
1398       }
1399       if (!str_len) return false;
1400       unsigned int len = hb_min (buf_len - 1, str_len);
1401       strncpy (buf, (const char*)str, len);
1402       buf[len] = '\0';
1403       return true;
1404     }
1405 
get_glyph_from_nameOT::cff1::accelerator_t1406     bool get_glyph_from_name (const char *name, int len,
1407 			      hb_codepoint_t *glyph) const
1408     {
1409       if (unlikely (!is_valid ())) return false;
1410       if (is_CID()) return false;
1411       if (len < 0) len = strlen (name);
1412       if (unlikely (!len)) return false;
1413 
1414     retry:
1415       hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire ();
1416       if (unlikely (!names))
1417       {
1418 	names = (hb_sorted_vector_t<gname_t> *) hb_calloc (1, sizeof (hb_sorted_vector_t<gname_t>));
1419 	if (likely (names))
1420 	{
1421 	  names->init ();
1422 	  /* TODO */
1423 
1424 	  /* fill glyph names */
1425 	  code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
1426 	  for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
1427 	  {
1428 	    hb_codepoint_t	sid = glyph_to_sid (gid, &glyph_to_sid_cache);
1429 	    gname_t	gname;
1430 	    gname.sid = sid;
1431 	    if (sid < cff1_std_strings_length)
1432 	      gname.name = cff1_std_strings (sid);
1433 	    else
1434 	    {
1435 	      hb_ubytes_t	ustr = (*stringIndex)[sid - cff1_std_strings_length];
1436 	      gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length);
1437 	    }
1438 	    if (unlikely (!gname.name.arrayZ))
1439 	      gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */
1440 	    names->push (gname);
1441 	  }
1442 	  names->qsort ();
1443 	}
1444 	if (unlikely (!glyph_names.cmpexch (nullptr, names)))
1445 	{
1446 	  if (names)
1447 	  {
1448 	    names->fini ();
1449 	    hb_free (names);
1450 	  }
1451 	  goto retry;
1452 	}
1453       }
1454 
1455       gname_t key = { hb_bytes_t (name, len), 0 };
1456       const gname_t *gname = names ? names->bsearch (key) : nullptr;
1457       if (!gname) return false;
1458       hb_codepoint_t gid = sid_to_glyph (gname->sid);
1459       if (!gid && gname->sid) return false;
1460       *glyph = gid;
1461       return true;
1462     }
1463 
1464     HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1465     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;
1466     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
1467 
1468     private:
1469     struct gname_t
1470     {
1471       hb_bytes_t	name;
1472       uint16_t		sid;
1473 
cmpOT::cff1::accelerator_t::gname_t1474       static int cmp (const void *a_, const void *b_)
1475       {
1476 	const gname_t *a = (const gname_t *)a_;
1477 	const gname_t *b = (const gname_t *)b_;
1478 	unsigned minlen = hb_min (a->name.length, b->name.length);
1479 	int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
1480 	if (ret) return ret;
1481 	return a->name.length - b->name.length;
1482       }
1483 
cmpOT::cff1::accelerator_t::gname_t1484       int cmp (const gname_t &a) const { return cmp (&a, this); }
1485     };
1486 
1487     mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
1488 
1489     typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
1490   };
1491 
1492   struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t>
1493   {
accelerator_subset_tOT::cff1::accelerator_subset_t1494     accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
~accelerator_subset_tOT::cff1::accelerator_subset_t1495     ~accelerator_subset_t ()
1496     {
1497       if (cff_accelerator)
1498 	cff_subset_accelerator_t::destroy (cff_accelerator);
1499     }
1500 
1501     HB_INTERNAL bool subset (hb_subset_context_t *c) const;
1502     HB_INTERNAL bool serialize (hb_serialize_context_t *c,
1503 				struct cff1_subset_plan &plan) const;
1504     HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
1505 
1506     mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
1507 
1508     typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER;
1509   };
1510 
1511   protected:
1512   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
1513   HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
1514   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
1515   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
1516   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
1517   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
1518   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
1519 
1520   public:
1521   FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
1522   NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
1523   HBUINT8	       offSize;	  /* offset size (unused?) */
1524 
1525   public:
1526   DEFINE_SIZE_STATIC (4);
1527 };
1528 
1529 struct cff1_accelerator_t : cff1::accelerator_t {
cff1_accelerator_tOT::cff1_accelerator_t1530   cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
1531 };
1532 
1533 struct cff1_subset_accelerator_t : cff1::accelerator_subset_t {
cff1_subset_accelerator_tOT::cff1_subset_accelerator_t1534   cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {}
1535 };
1536 
1537 } /* namespace OT */
1538 
1539 #endif /* HB_OT_CFF1_TABLE_HH */
1540