• 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-cff1.hh"
32 #include "hb-draw.hh"
33 
34 #define HB_STRING_ARRAY_NAME cff1_std_strings
35 #define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh"
36 #include "hb-string-array.hh"
37 #undef HB_STRING_ARRAY_LIST
38 #undef HB_STRING_ARRAY_NAME
39 
40 namespace CFF {
41 
42 /*
43  * CFF -- Compact Font Format (CFF)
44  * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
45  */
46 #define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
47 
48 #define CFF_UNDEF_SID   CFF_UNDEF_CODE
49 
50 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
51 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
52 
53 typedef CFFIndex<HBUINT16>  CFF1Index;
54 template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
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     assert (glyph > 0);
113     glyph--;
114     for (unsigned int i = 0; i < nRanges (); i++)
115     {
116       if (glyph <= ranges[i].nLeft)
117       {
118 	hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
119 	return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
120       }
121       glyph -= (ranges[i].nLeft + 1);
122     }
123     return CFF_UNDEF_CODE;
124   }
125 
nRangesCFF::Encoding1126   HBUINT8 &nRanges () { return ranges.len; }
nRangesCFF::Encoding1127   HBUINT8 nRanges () const { return ranges.len; }
128 
129   ArrayOf<Encoding1_Range, HBUINT8> ranges;
130 
131   DEFINE_SIZE_ARRAY_SIZED (1, ranges);
132 };
133 
134 struct SuppEncoding {
sanitizeCFF::SuppEncoding135   bool sanitize (hb_sanitize_context_t *c) const
136   {
137     TRACE_SANITIZE (this);
138     return_trace (c->check_struct (this));
139   }
140 
141   HBUINT8   code;
142   HBUINT16  glyph;
143 
144   DEFINE_SIZE_STATIC (3);
145 };
146 
147 struct CFF1SuppEncData {
sanitizeCFF::CFF1SuppEncData148   bool sanitize (hb_sanitize_context_t *c) const
149   {
150     TRACE_SANITIZE (this);
151     return_trace (supps.sanitize (c));
152   }
153 
get_codesCFF::CFF1SuppEncData154   void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
155   {
156     for (unsigned int i = 0; i < nSups (); i++)
157       if (sid == supps[i].glyph)
158 	codes.push (supps[i].code);
159   }
160 
nSupsCFF::CFF1SuppEncData161   HBUINT8 &nSups () { return supps.len; }
nSupsCFF::CFF1SuppEncData162   HBUINT8 nSups () const { return supps.len; }
163 
164   ArrayOf<SuppEncoding, HBUINT8> supps;
165 
166   DEFINE_SIZE_ARRAY_SIZED (1, supps);
167 };
168 
169 struct Encoding
170 {
171   /* serialize a fullset Encoding */
serializeCFF::Encoding172   bool serialize (hb_serialize_context_t *c, const Encoding &src)
173   {
174     TRACE_SERIALIZE (this);
175     unsigned int size = src.get_size ();
176     Encoding *dest = c->allocate_size<Encoding> (size);
177     if (unlikely (!dest)) return_trace (false);
178     hb_memcpy (dest, &src, size);
179     return_trace (true);
180   }
181 
182   /* serialize a subset Encoding */
serializeCFF::Encoding183   bool serialize (hb_serialize_context_t *c,
184 		  uint8_t format,
185 		  unsigned int enc_count,
186 		  const hb_vector_t<code_pair_t>& code_ranges,
187 		  const hb_vector_t<code_pair_t>& supp_codes)
188   {
189     TRACE_SERIALIZE (this);
190     Encoding *dest = c->extend_min (this);
191     if (unlikely (!dest)) return_trace (false);
192     dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
193     switch (format) {
194     case 0:
195     {
196       Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
197       if (unlikely (!fmt0)) return_trace (false);
198       fmt0->nCodes () = enc_count;
199       unsigned int glyph = 0;
200       for (unsigned int i = 0; i < code_ranges.length; i++)
201       {
202 	hb_codepoint_t code = code_ranges[i].code;
203 	for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
204 	  fmt0->codes[glyph++] = code++;
205 	if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
206 	  return_trace (false);
207       }
208     }
209     break;
210 
211     case 1:
212     {
213       Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
214       if (unlikely (!fmt1)) return_trace (false);
215       fmt1->nRanges () = code_ranges.length;
216       for (unsigned int i = 0; i < code_ranges.length; i++)
217       {
218 	if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
219 	  return_trace (false);
220 	fmt1->ranges[i].first = code_ranges[i].code;
221 	fmt1->ranges[i].nLeft = code_ranges[i].glyph;
222       }
223     }
224     break;
225 
226     }
227 
228     if (supp_codes.length)
229     {
230       CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
231       if (unlikely (!suppData)) return_trace (false);
232       suppData->nSups () = supp_codes.length;
233       for (unsigned int i = 0; i < supp_codes.length; i++)
234       {
235 	suppData->supps[i].code = supp_codes[i].code;
236 	suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
237       }
238     }
239 
240     return_trace (true);
241   }
242 
get_sizeCFF::Encoding243   unsigned int get_size () const
244   {
245     unsigned int size = min_size;
246     switch (table_format ())
247     {
248     case 0: size += u.format0.get_size (); break;
249     case 1: size += u.format1.get_size (); break;
250     }
251     if (has_supplement ())
252       size += suppEncData ().get_size ();
253     return size;
254   }
255 
get_codeCFF::Encoding256   hb_codepoint_t get_code (hb_codepoint_t glyph) const
257   {
258     switch (table_format ())
259     {
260     case 0: return u.format0.get_code (glyph);
261     case 1: return u.format1.get_code (glyph);
262     default:return 0;
263     }
264   }
265 
table_formatCFF::Encoding266   uint8_t table_format () const { return format & 0x7F; }
has_supplementCFF::Encoding267   bool  has_supplement () const { return format & 0x80; }
268 
get_supplement_codesCFF::Encoding269   void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
270   {
271     codes.resize (0);
272     if (has_supplement ())
273       suppEncData().get_codes (sid, codes);
274   }
275 
sanitizeCFF::Encoding276   bool sanitize (hb_sanitize_context_t *c) const
277   {
278     TRACE_SANITIZE (this);
279     if (unlikely (!c->check_struct (this)))
280       return_trace (false);
281 
282     switch (table_format ())
283     {
284     case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
285     case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
286     default:return_trace (false);
287     }
288     return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
289   }
290 
291   protected:
suppEncDataCFF::Encoding292   const CFF1SuppEncData &suppEncData () const
293   {
294     switch (table_format ())
295     {
296     case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
297     case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
298     default:return Null (CFF1SuppEncData);
299     }
300   }
301 
302   public:
303   HBUINT8	format;
304   union {
305   Encoding0	format0;
306   Encoding1	format1;
307   } u;
308   /* CFF1SuppEncData  suppEncData; */
309 
310   DEFINE_SIZE_MIN (1);
311 };
312 
313 /* Charset */
314 struct Charset0 {
sanitizeCFF::Charset0315   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
316   {
317     TRACE_SANITIZE (this);
318     return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
319   }
320 
get_sidCFF::Charset0321   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
322   {
323     if (unlikely (glyph >= num_glyphs)) return 0;
324     if (glyph == 0)
325       return 0;
326     else
327       return sids[glyph - 1];
328   }
329 
collect_glyph_to_sid_mapCFF::Charset0330   void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
331   {
332     for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
333       mapping->set (gid, sids[gid - 1]);
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   unsigned int get_size (unsigned int num_glyphs) const
350   {
351     assert (num_glyphs > 0);
352     return HBUINT16::static_size * (num_glyphs - 1);
353   }
354 
355   HBUINT16  sids[HB_VAR_ARRAY];
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) const
377   {
378     TRACE_SANITIZE (this);
379     if (unlikely (!c->check_struct (this)))
380       return_trace (false);
381     num_glyphs--;
382     for (unsigned int i = 0; num_glyphs > 0; i++)
383     {
384       if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
385 	return_trace (false);
386       num_glyphs -= (ranges[i].nLeft + 1);
387     }
388     return_trace (true);
389   }
390 
get_sidCFF::Charset1_2391   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
392   {
393     if (unlikely (glyph >= num_glyphs)) return 0;
394     if (glyph == 0) return 0;
395     glyph--;
396     for (unsigned int i = 0;; i++)
397     {
398       if (glyph <= ranges[i].nLeft)
399 	return (hb_codepoint_t) ranges[i].first + glyph;
400       glyph -= (ranges[i].nLeft + 1);
401     }
402 
403     return 0;
404   }
405 
collect_glyph_to_sid_mapCFF::Charset1_2406   void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
407   {
408     hb_codepoint_t gid = 1;
409     if (gid >= num_glyphs)
410       return;
411     for (unsigned i = 0;; i++)
412     {
413       hb_codepoint_t sid = ranges[i].first;
414       unsigned count = ranges[i].nLeft + 1;
415       for (unsigned j = 0; j < count; j++)
416 	mapping->set (gid++, sid++);
417 
418       if (gid >= num_glyphs)
419         break;
420     }
421   }
422 
get_glyphCFF::Charset1_2423   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
424   {
425     if (sid == 0) return 0;
426     hb_codepoint_t  glyph = 1;
427     for (unsigned int i = 0;; i++)
428     {
429       if (glyph >= num_glyphs)
430 	return 0;
431       if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
432 	return glyph + (sid - ranges[i].first);
433       glyph += (ranges[i].nLeft + 1);
434     }
435 
436     return 0;
437   }
438 
get_sizeCFF::Charset1_2439   unsigned int get_size (unsigned int num_glyphs) const
440   {
441     unsigned int size = HBUINT8::static_size;
442     int glyph = (int)num_glyphs;
443 
444     assert (glyph > 0);
445     glyph--;
446     for (unsigned int i = 0; glyph > 0; i++)
447     {
448       glyph -= (ranges[i].nLeft + 1);
449       size += Charset_Range<TYPE>::static_size;
450     }
451 
452     return size;
453   }
454 
455   Charset_Range<TYPE>   ranges[HB_VAR_ARRAY];
456 
457   DEFINE_SIZE_ARRAY (0, ranges);
458 };
459 
460 typedef Charset1_2<HBUINT8>     Charset1;
461 typedef Charset1_2<HBUINT16>    Charset2;
462 typedef Charset_Range<HBUINT8>  Charset1_Range;
463 typedef Charset_Range<HBUINT16> Charset2_Range;
464 
465 struct Charset
466 {
467   /* serialize a fullset Charset */
serializeCFF::Charset468   bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
469   {
470     TRACE_SERIALIZE (this);
471     unsigned int size = src.get_size (num_glyphs);
472     Charset *dest = c->allocate_size<Charset> (size);
473     if (unlikely (!dest)) return_trace (false);
474     hb_memcpy (dest, &src, size);
475     return_trace (true);
476   }
477 
478   /* serialize a subset Charset */
serializeCFF::Charset479   bool serialize (hb_serialize_context_t *c,
480 		  uint8_t format,
481 		  unsigned int num_glyphs,
482 		  const hb_vector_t<code_pair_t>& sid_ranges)
483   {
484     TRACE_SERIALIZE (this);
485     Charset *dest = c->extend_min (this);
486     if (unlikely (!dest)) return_trace (false);
487     dest->format = format;
488     switch (format)
489     {
490     case 0:
491     {
492       Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
493       if (unlikely (!fmt0)) return_trace (false);
494       unsigned int glyph = 0;
495       for (unsigned int i = 0; i < sid_ranges.length; i++)
496       {
497 	hb_codepoint_t sid = sid_ranges[i].code;
498 	for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
499 	  fmt0->sids[glyph++] = sid++;
500       }
501     }
502     break;
503 
504     case 1:
505     {
506       Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
507       if (unlikely (!fmt1)) return_trace (false);
508       for (unsigned int i = 0; i < sid_ranges.length; i++)
509       {
510 	if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
511 	  return_trace (false);
512 	fmt1->ranges[i].first = sid_ranges[i].code;
513 	fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
514       }
515     }
516     break;
517 
518     case 2:
519     {
520       Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
521       if (unlikely (!fmt2)) return_trace (false);
522       for (unsigned int i = 0; i < sid_ranges.length; i++)
523       {
524 	if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
525 	  return_trace (false);
526 	fmt2->ranges[i].first = sid_ranges[i].code;
527 	fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
528       }
529     }
530     break;
531 
532     }
533     return_trace (true);
534   }
535 
get_sizeCFF::Charset536   unsigned int get_size (unsigned int num_glyphs) const
537   {
538     switch (format)
539     {
540     case 0: return min_size + u.format0.get_size (num_glyphs);
541     case 1: return min_size + u.format1.get_size (num_glyphs);
542     case 2: return min_size + u.format2.get_size (num_glyphs);
543     default:return 0;
544     }
545   }
546 
get_sidCFF::Charset547   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
548   {
549     switch (format)
550     {
551     case 0: return u.format0.get_sid (glyph, num_glyphs);
552     case 1: return u.format1.get_sid (glyph, num_glyphs);
553     case 2: return u.format2.get_sid (glyph, num_glyphs);
554     default:return 0;
555     }
556   }
557 
collect_glyph_to_sid_mapCFF::Charset558   void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
559   {
560     switch (format)
561     {
562     case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
563     case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
564     case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
565     default:return;
566     }
567   }
568 
get_glyphCFF::Charset569   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
570   {
571     switch (format)
572     {
573     case 0: return u.format0.get_glyph (sid, num_glyphs);
574     case 1: return u.format1.get_glyph (sid, num_glyphs);
575     case 2: return u.format2.get_glyph (sid, num_glyphs);
576     default:return 0;
577     }
578   }
579 
sanitizeCFF::Charset580   bool sanitize (hb_sanitize_context_t *c) const
581   {
582     TRACE_SANITIZE (this);
583     if (unlikely (!c->check_struct (this)))
584       return_trace (false);
585 
586     switch (format)
587     {
588     case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
589     case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
590     case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
591     default:return_trace (false);
592     }
593   }
594 
595   HBUINT8       format;
596   union {
597     Charset0    format0;
598     Charset1    format1;
599     Charset2    format2;
600   } u;
601 
602   DEFINE_SIZE_MIN (1);
603 };
604 
605 struct CFF1StringIndex : CFF1Index
606 {
serializeCFF::CFF1StringIndex607   bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
608 		  const hb_inc_bimap_t &sidmap)
609   {
610     TRACE_SERIALIZE (this);
611     if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
612     {
613       if (unlikely (!c->extend_min (this->count)))
614 	return_trace (false);
615       count = 0;
616       return_trace (true);
617     }
618 
619     byte_str_array_t bytesArray;
620     if (!bytesArray.resize (sidmap.get_population ()))
621       return_trace (false);
622     for (unsigned int i = 0; i < strings.count; i++)
623     {
624       hb_codepoint_t  j = sidmap[i];
625       if (j != HB_MAP_VALUE_INVALID)
626 	bytesArray[j] = strings[i];
627     }
628 
629     bool result = CFF1Index::serialize (c, bytesArray);
630     return_trace (result);
631   }
632 };
633 
634 struct cff1_top_dict_interp_env_t : num_interp_env_t
635 {
cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t636   cff1_top_dict_interp_env_t ()
637     : num_interp_env_t(), prev_offset(0), last_offset(0) {}
cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t638   cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes)
639     : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {}
640 
641   unsigned int prev_offset;
642   unsigned int last_offset;
643 };
644 
645 struct name_dict_values_t
646 {
647   enum name_dict_val_index_t
648   {
649       version,
650       notice,
651       copyright,
652       fullName,
653       familyName,
654       weight,
655       postscript,
656       fontName,
657       baseFontName,
658       registry,
659       ordering,
660 
661       ValCount
662   };
663 
initCFF::name_dict_values_t664   void init ()
665   {
666     for (unsigned int i = 0; i < ValCount; i++)
667       values[i] = CFF_UNDEF_SID;
668   }
669 
operator []CFF::name_dict_values_t670   unsigned int& operator[] (unsigned int i)
671   { assert (i < ValCount); return values[i]; }
672 
operator []CFF::name_dict_values_t673   unsigned int operator[] (unsigned int i) const
674   { assert (i < ValCount); return values[i]; }
675 
name_op_to_indexCFF::name_dict_values_t676   static enum name_dict_val_index_t name_op_to_index (op_code_t op)
677   {
678     switch (op) {
679       default: // can't happen - just make some compiler happy
680       case OpCode_version:
681 	return version;
682       case OpCode_Notice:
683 	return notice;
684       case OpCode_Copyright:
685 	return copyright;
686       case OpCode_FullName:
687 	return fullName;
688       case OpCode_FamilyName:
689 	return familyName;
690       case OpCode_Weight:
691 	return weight;
692       case OpCode_PostScript:
693 	return postscript;
694       case OpCode_FontName:
695 	return fontName;
696       case OpCode_BaseFontName:
697 	return baseFontName;
698     }
699   }
700 
701   unsigned int  values[ValCount];
702 };
703 
704 struct cff1_top_dict_val_t : op_str_t
705 {
706   unsigned int  last_arg_offset;
707 };
708 
709 struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
710 {
initCFF::cff1_top_dict_values_t711   void init ()
712   {
713     top_dict_values_t<cff1_top_dict_val_t>::init ();
714 
715     nameSIDs.init ();
716     ros_supplement = 0;
717     cidCount = 8720;
718     EncodingOffset = 0;
719     CharsetOffset = 0;
720     FDSelectOffset = 0;
721     privateDictInfo.init ();
722   }
finiCFF::cff1_top_dict_values_t723   void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
724 
is_CIDCFF::cff1_top_dict_values_t725   bool is_CID () const
726   { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
727 
728   name_dict_values_t  nameSIDs;
729   unsigned int    ros_supplement_offset;
730   unsigned int    ros_supplement;
731   unsigned int    cidCount;
732 
733   unsigned int    EncodingOffset;
734   unsigned int    CharsetOffset;
735   unsigned int    FDSelectOffset;
736   table_info_t    privateDictInfo;
737 };
738 
739 struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
740 {
process_opCFF::cff1_top_dict_opset_t741   static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
742   {
743     cff1_top_dict_val_t  val;
744     val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
745 
746     switch (op) {
747       case OpCode_version:
748       case OpCode_Notice:
749       case OpCode_Copyright:
750       case OpCode_FullName:
751       case OpCode_FontName:
752       case OpCode_FamilyName:
753       case OpCode_Weight:
754       case OpCode_PostScript:
755       case OpCode_BaseFontName:
756 	dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
757 	env.clear_args ();
758 	break;
759       case OpCode_isFixedPitch:
760       case OpCode_ItalicAngle:
761       case OpCode_UnderlinePosition:
762       case OpCode_UnderlineThickness:
763       case OpCode_PaintType:
764       case OpCode_CharstringType:
765       case OpCode_UniqueID:
766       case OpCode_StrokeWidth:
767       case OpCode_SyntheticBase:
768       case OpCode_CIDFontVersion:
769       case OpCode_CIDFontRevision:
770       case OpCode_CIDFontType:
771       case OpCode_UIDBase:
772       case OpCode_FontBBox:
773       case OpCode_XUID:
774       case OpCode_BaseFontBlend:
775 	env.clear_args ();
776 	break;
777 
778       case OpCode_CIDCount:
779 	dictval.cidCount = env.argStack.pop_uint ();
780 	env.clear_args ();
781 	break;
782 
783       case OpCode_ROS:
784 	dictval.ros_supplement = env.argStack.pop_uint ();
785 	dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
786 	dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
787 	env.clear_args ();
788 	break;
789 
790       case OpCode_Encoding:
791 	dictval.EncodingOffset = env.argStack.pop_uint ();
792 	env.clear_args ();
793 	if (unlikely (dictval.EncodingOffset == 0)) return;
794 	break;
795 
796       case OpCode_charset:
797 	dictval.CharsetOffset = env.argStack.pop_uint ();
798 	env.clear_args ();
799 	if (unlikely (dictval.CharsetOffset == 0)) return;
800 	break;
801 
802       case OpCode_FDSelect:
803 	dictval.FDSelectOffset = env.argStack.pop_uint ();
804 	env.clear_args ();
805 	break;
806 
807       case OpCode_Private:
808 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
809 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
810 	env.clear_args ();
811 	break;
812 
813       default:
814 	env.last_offset = env.str_ref.get_offset ();
815 	top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
816 	/* Record this operand below if stack is empty, otherwise done */
817 	if (!env.argStack.is_empty ()) return;
818 	break;
819     }
820 
821     if (unlikely (env.in_error ())) return;
822 
823     dictval.add_op (op, env.str_ref, val);
824   }
825 };
826 
827 struct cff1_font_dict_values_t : dict_values_t<op_str_t>
828 {
initCFF::cff1_font_dict_values_t829   void init ()
830   {
831     dict_values_t<op_str_t>::init ();
832     privateDictInfo.init ();
833     fontName = CFF_UNDEF_SID;
834   }
finiCFF::cff1_font_dict_values_t835   void fini () { dict_values_t<op_str_t>::fini (); }
836 
837   table_info_t       privateDictInfo;
838   unsigned int    fontName;
839 };
840 
841 struct cff1_font_dict_opset_t : dict_opset_t
842 {
process_opCFF::cff1_font_dict_opset_t843   static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
844   {
845     switch (op) {
846       case OpCode_FontName:
847 	dictval.fontName = env.argStack.pop_uint ();
848 	env.clear_args ();
849 	break;
850       case OpCode_FontMatrix:
851       case OpCode_PaintType:
852 	env.clear_args ();
853 	break;
854       case OpCode_Private:
855 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
856 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
857 	env.clear_args ();
858 	break;
859 
860       default:
861 	dict_opset_t::process_op (op, env);
862 	if (!env.argStack.is_empty ()) return;
863 	break;
864     }
865 
866     if (unlikely (env.in_error ())) return;
867 
868     dictval.add_op (op, env.str_ref);
869   }
870 };
871 
872 template <typename VAL>
873 struct cff1_private_dict_values_base_t : dict_values_t<VAL>
874 {
initCFF::cff1_private_dict_values_base_t875   void init ()
876   {
877     dict_values_t<VAL>::init ();
878     subrsOffset = 0;
879     localSubrs = &Null (CFF1Subrs);
880   }
finiCFF::cff1_private_dict_values_base_t881   void fini () { dict_values_t<VAL>::fini (); }
882 
883   unsigned int      subrsOffset;
884   const CFF1Subrs    *localSubrs;
885 };
886 
887 typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
888 typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
889 
890 struct cff1_private_dict_opset_t : dict_opset_t
891 {
process_opCFF::cff1_private_dict_opset_t892   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
893   {
894     num_dict_val_t val;
895     val.init ();
896 
897     switch (op) {
898       case OpCode_BlueValues:
899       case OpCode_OtherBlues:
900       case OpCode_FamilyBlues:
901       case OpCode_FamilyOtherBlues:
902       case OpCode_StemSnapH:
903       case OpCode_StemSnapV:
904 	env.clear_args ();
905 	break;
906       case OpCode_StdHW:
907       case OpCode_StdVW:
908       case OpCode_BlueScale:
909       case OpCode_BlueShift:
910       case OpCode_BlueFuzz:
911       case OpCode_ForceBold:
912       case OpCode_LanguageGroup:
913       case OpCode_ExpansionFactor:
914       case OpCode_initialRandomSeed:
915       case OpCode_defaultWidthX:
916       case OpCode_nominalWidthX:
917 	val.single_val = env.argStack.pop_num ();
918 	env.clear_args ();
919 	break;
920       case OpCode_Subrs:
921 	dictval.subrsOffset = env.argStack.pop_uint ();
922 	env.clear_args ();
923 	break;
924 
925       default:
926 	dict_opset_t::process_op (op, env);
927 	if (!env.argStack.is_empty ()) return;
928 	break;
929     }
930 
931     if (unlikely (env.in_error ())) return;
932 
933     dictval.add_op (op, env.str_ref, val);
934   }
935 };
936 
937 struct cff1_private_dict_opset_subset : dict_opset_t
938 {
process_opCFF::cff1_private_dict_opset_subset939   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
940   {
941     switch (op) {
942       case OpCode_BlueValues:
943       case OpCode_OtherBlues:
944       case OpCode_FamilyBlues:
945       case OpCode_FamilyOtherBlues:
946       case OpCode_StemSnapH:
947       case OpCode_StemSnapV:
948       case OpCode_StdHW:
949       case OpCode_StdVW:
950       case OpCode_BlueScale:
951       case OpCode_BlueShift:
952       case OpCode_BlueFuzz:
953       case OpCode_ForceBold:
954       case OpCode_LanguageGroup:
955       case OpCode_ExpansionFactor:
956       case OpCode_initialRandomSeed:
957       case OpCode_defaultWidthX:
958       case OpCode_nominalWidthX:
959 	env.clear_args ();
960 	break;
961 
962       case OpCode_Subrs:
963 	dictval.subrsOffset = env.argStack.pop_uint ();
964 	env.clear_args ();
965 	break;
966 
967       default:
968 	dict_opset_t::process_op (op, env);
969 	if (!env.argStack.is_empty ()) return;
970 	break;
971     }
972 
973     if (unlikely (env.in_error ())) return;
974 
975     dictval.add_op (op, env.str_ref);
976   }
977 };
978 
979 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;
980 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
981 
982 typedef CFF1Index CFF1NameIndex;
983 typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
984 
985 struct cff1_font_dict_values_mod_t
986 {
cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t987   cff1_font_dict_values_mod_t() { init (); }
988 
initCFF::cff1_font_dict_values_mod_t989   void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
990 
initCFF::cff1_font_dict_values_mod_t991   void init (const cff1_font_dict_values_t *base_,
992 	     unsigned int fontName_)
993   {
994     base = base_;
995     fontName = fontName_;
996     privateDictInfo.init ();
997   }
998 
get_countCFF::cff1_font_dict_values_mod_t999   unsigned get_count () const { return base->get_count (); }
1000 
operator []CFF::cff1_font_dict_values_mod_t1001   const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
1002 
1003   const cff1_font_dict_values_t    *base;
1004   table_info_t		   privateDictInfo;
1005   unsigned int		fontName;
1006 };
1007 
1008 struct CFF1FDArray : FDArray<HBUINT16>
1009 {
1010   /* FDArray::serialize() requires this partial specialization to compile */
1011   template <typename ITER, typename OP_SERIALIZER>
serializeCFF::CFF1FDArray1012   bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
1013   { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
1014 };
1015 
1016 } /* namespace CFF */
1017 
1018 namespace OT {
1019 
1020 using namespace CFF;
1021 
1022 struct cff1
1023 {
1024   static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
1025 
sanitizeOT::cff11026   bool sanitize (hb_sanitize_context_t *c) const
1027   {
1028     TRACE_SANITIZE (this);
1029     return_trace (c->check_struct (this) &&
1030 		  likely (version.major == 1));
1031   }
1032 
1033   template <typename PRIVOPSET, typename PRIVDICTVAL>
1034   struct accelerator_templ_t
1035   {
initOT::cff1::accelerator_templ_t1036     void init (hb_face_t *face)
1037     {
1038       topDict.init ();
1039       fontDicts.init ();
1040       privateDicts.init ();
1041 
1042       this->blob = sc.reference_table<cff1> (face);
1043 
1044       /* setup for run-time santization */
1045       sc.init (this->blob);
1046       sc.start_processing ();
1047 
1048       const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
1049 
1050       if (cff == &Null (OT::cff1))
1051       { fini (); return; }
1052 
1053       nameIndex = &cff->nameIndex (cff);
1054       if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
1055       { fini (); return; }
1056 
1057       topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
1058       if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
1059       { fini (); return; }
1060 
1061       { /* parse top dict */
1062 	const hb_ubytes_t topDictStr = (*topDictIndex)[0];
1063 	if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
1064 	cff1_top_dict_interp_env_t env (topDictStr);
1065 	cff1_top_dict_interpreter_t top_interp (env);
1066 	if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
1067       }
1068 
1069       if (is_predef_charset ())
1070 	charset = &Null (Charset);
1071       else
1072       {
1073 	charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
1074 	if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
1075       }
1076 
1077       fdCount = 1;
1078       if (is_CID ())
1079       {
1080 	fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
1081 	fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
1082 	if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
1083 	    (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
1084 	{ fini (); return; }
1085 
1086 	fdCount = fdArray->count;
1087       }
1088       else
1089       {
1090 	fdArray = &Null (CFF1FDArray);
1091 	fdSelect = &Null (CFF1FDSelect);
1092       }
1093 
1094       encoding = &Null (Encoding);
1095       if (is_CID ())
1096       {
1097 	if (unlikely (charset == &Null (Charset))) { fini (); return; }
1098       }
1099       else
1100       {
1101 	if (!is_predef_encoding ())
1102 	{
1103 	  encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
1104 	  if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
1105 	}
1106       }
1107 
1108       stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
1109       if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
1110       { fini (); return; }
1111 
1112       globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
1113       if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
1114       { fini (); return; }
1115 
1116       charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
1117 
1118       if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
1119       { fini (); return; }
1120 
1121       num_glyphs = charStrings->count;
1122       if (num_glyphs != sc.get_num_glyphs ())
1123       { fini (); return; }
1124 
1125       if (unlikely (!privateDicts.resize (fdCount)))
1126       { fini (); return; }
1127       for (unsigned int i = 0; i < fdCount; i++)
1128 	privateDicts[i].init ();
1129 
1130       // parse CID font dicts and gather private dicts
1131       if (is_CID ())
1132       {
1133 	for (unsigned int i = 0; i < fdCount; i++)
1134 	{
1135 	  hb_ubytes_t fontDictStr = (*fdArray)[i];
1136 	  if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
1137 	  cff1_font_dict_values_t *font;
1138 	  cff1_top_dict_interp_env_t env (fontDictStr);
1139 	  cff1_font_dict_interpreter_t font_interp (env);
1140 	  font = fontDicts.push ();
1141 	  if (unlikely (fontDicts.in_error ())) { fini (); return; }
1142 
1143 	  font->init ();
1144 	  if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
1145 	  PRIVDICTVAL *priv = &privateDicts[i];
1146 	  const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
1147 	  if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1148 	  num_interp_env_t env2 (privDictStr);
1149 	  dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
1150 	  priv->init ();
1151 	  if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1152 
1153 	  priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1154 	  if (priv->localSubrs != &Null (CFF1Subrs) &&
1155 	      unlikely (!priv->localSubrs->sanitize (&sc)))
1156 	  { fini (); return; }
1157 	}
1158       }
1159       else  /* non-CID */
1160       {
1161 	cff1_top_dict_values_t *font = &topDict;
1162 	PRIVDICTVAL *priv = &privateDicts[0];
1163 
1164 	const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
1165 	if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1166 	num_interp_env_t env (privDictStr);
1167 	dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
1168 	priv->init ();
1169 	if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1170 
1171 	priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1172 	if (priv->localSubrs != &Null (CFF1Subrs) &&
1173 	    unlikely (!priv->localSubrs->sanitize (&sc)))
1174 	{ fini (); return; }
1175       }
1176     }
1177 
finiOT::cff1::accelerator_templ_t1178     void fini ()
1179     {
1180       sc.end_processing ();
1181       topDict.fini ();
1182       fontDicts.fini ();
1183       privateDicts.fini ();
1184       hb_blob_destroy (blob);
1185       blob = nullptr;
1186     }
1187 
is_validOT::cff1::accelerator_templ_t1188     bool is_valid () const { return blob; }
is_CIDOT::cff1::accelerator_templ_t1189     bool   is_CID () const { return topDict.is_CID (); }
1190 
is_predef_charsetOT::cff1::accelerator_templ_t1191     bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1192 
std_code_to_glyphOT::cff1::accelerator_templ_t1193     unsigned int std_code_to_glyph (hb_codepoint_t code) const
1194     {
1195       hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1196       if (unlikely (sid == CFF_UNDEF_SID))
1197 	return 0;
1198 
1199       if (charset != &Null (Charset))
1200 	return charset->get_glyph (sid, num_glyphs);
1201       else if ((topDict.CharsetOffset == ISOAdobeCharset)
1202 	      && (code <= 228 /*zcaron*/)) return sid;
1203       return 0;
1204     }
1205 
is_predef_encodingOT::cff1::accelerator_templ_t1206     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1207 
glyph_to_codeOT::cff1::accelerator_templ_t1208     hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
1209     {
1210       if (encoding != &Null (Encoding))
1211 	return encoding->get_code (glyph);
1212       else
1213       {
1214 	hb_codepoint_t sid = glyph_to_sid (glyph);
1215 	if (sid == 0) return 0;
1216 	hb_codepoint_t code = 0;
1217 	switch (topDict.EncodingOffset)
1218 	{
1219 	case StandardEncoding:
1220 	  code = lookup_standard_encoding_for_code (sid);
1221 	  break;
1222 	case ExpertEncoding:
1223 	  code = lookup_expert_encoding_for_code (sid);
1224 	  break;
1225 	default:
1226 	  break;
1227 	}
1228 	return code;
1229       }
1230     }
1231 
create_glyph_to_sid_mapOT::cff1::accelerator_templ_t1232     hb_map_t *create_glyph_to_sid_map () const
1233     {
1234       if (charset != &Null (Charset))
1235       {
1236 	hb_map_t *mapping = hb_map_create ();
1237 	mapping->set (0, 0);
1238 	charset->collect_glyph_to_sid_map (mapping, num_glyphs);
1239 	return mapping;
1240       }
1241       else
1242 	return nullptr;
1243     }
1244 
glyph_to_sidOT::cff1::accelerator_templ_t1245     hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
1246     {
1247       if (charset != &Null (Charset))
1248 	return charset->get_sid (glyph, num_glyphs);
1249       else
1250       {
1251 	hb_codepoint_t sid = 0;
1252 	switch (topDict.CharsetOffset)
1253 	{
1254 	  case ISOAdobeCharset:
1255 	    if (glyph <= 228 /*zcaron*/) sid = glyph;
1256 	    break;
1257 	  case ExpertCharset:
1258 	    sid = lookup_expert_charset_for_sid (glyph);
1259 	    break;
1260 	  case ExpertSubsetCharset:
1261 	      sid = lookup_expert_subset_charset_for_sid (glyph);
1262 	    break;
1263 	  default:
1264 	    break;
1265 	}
1266 	return sid;
1267       }
1268     }
1269 
sid_to_glyphOT::cff1::accelerator_templ_t1270     hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
1271     {
1272       if (charset != &Null (Charset))
1273 	return charset->get_glyph (sid, num_glyphs);
1274       else
1275       {
1276 	hb_codepoint_t glyph = 0;
1277 	switch (topDict.CharsetOffset)
1278 	{
1279 	  case ISOAdobeCharset:
1280 	    if (sid <= 228 /*zcaron*/) glyph = sid;
1281 	    break;
1282 	  case ExpertCharset:
1283 	    glyph = lookup_expert_charset_for_glyph (sid);
1284 	    break;
1285 	  case ExpertSubsetCharset:
1286 	    glyph = lookup_expert_subset_charset_for_glyph (sid);
1287 	    break;
1288 	  default:
1289 	    break;
1290 	}
1291 	return glyph;
1292       }
1293     }
1294 
1295     protected:
1296     hb_sanitize_context_t   sc;
1297 
1298     public:
1299     hb_blob_t               *blob = nullptr;
1300     const Encoding	    *encoding = nullptr;
1301     const Charset	    *charset = nullptr;
1302     const CFF1NameIndex     *nameIndex = nullptr;
1303     const CFF1TopDictIndex  *topDictIndex = nullptr;
1304     const CFF1StringIndex   *stringIndex = nullptr;
1305     const CFF1Subrs	    *globalSubrs = nullptr;
1306     const CFF1CharStrings   *charStrings = nullptr;
1307     const CFF1FDArray       *fdArray = nullptr;
1308     const CFF1FDSelect      *fdSelect = nullptr;
1309     unsigned int	     fdCount = 0;
1310 
1311     cff1_top_dict_values_t   topDict;
1312     hb_vector_t<cff1_font_dict_values_t>
1313 			     fontDicts;
1314     hb_vector_t<PRIVDICTVAL> privateDicts;
1315 
1316     unsigned int	     num_glyphs = 0;
1317   };
1318 
1319   struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1320   {
accelerator_tOT::cff1::accelerator_t1321     accelerator_t (hb_face_t *face)
1322     {
1323       SUPER::init (face);
1324 
1325       glyph_names.set_relaxed (nullptr);
1326 
1327       if (!is_valid ()) return;
1328       if (is_CID ()) return;
1329 
1330     }
~accelerator_tOT::cff1::accelerator_t1331     ~accelerator_t ()
1332     {
1333       hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed ();
1334       if (names)
1335       {
1336 	names->fini ();
1337 	hb_free (names);
1338       }
1339 
1340       SUPER::fini ();
1341     }
1342 
get_glyph_nameOT::cff1::accelerator_t1343     bool get_glyph_name (hb_codepoint_t glyph,
1344 			 char *buf, unsigned int buf_len) const
1345     {
1346       if (unlikely (!is_valid ())) return false;
1347       if (is_CID()) return false;
1348       if (unlikely (!buf_len)) return true;
1349       hb_codepoint_t sid = glyph_to_sid (glyph);
1350       const char *str;
1351       size_t str_len;
1352       if (sid < cff1_std_strings_length)
1353       {
1354 	hb_bytes_t byte_str = cff1_std_strings (sid);
1355 	str = byte_str.arrayZ;
1356 	str_len = byte_str.length;
1357       }
1358       else
1359       {
1360 	hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
1361 	str = (const char *)ubyte_str.arrayZ;
1362 	str_len = ubyte_str.length;
1363       }
1364       if (!str_len) return false;
1365       unsigned int len = hb_min (buf_len - 1, str_len);
1366       strncpy (buf, (const char*)str, len);
1367       buf[len] = '\0';
1368       return true;
1369     }
1370 
get_glyph_from_nameOT::cff1::accelerator_t1371     bool get_glyph_from_name (const char *name, int len,
1372 			      hb_codepoint_t *glyph) const
1373     {
1374       if (unlikely (!is_valid ())) return false;
1375       if (is_CID()) return false;
1376       if (len < 0) len = strlen (name);
1377       if (unlikely (!len)) return false;
1378 
1379     retry:
1380       hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire ();
1381       if (unlikely (!names))
1382       {
1383 	names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
1384 	if (likely (names))
1385 	{
1386 	  names->init ();
1387 	  /* TODO */
1388 
1389 	  /* fill glyph names */
1390 	  for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
1391 	  {
1392 	    hb_codepoint_t	sid = glyph_to_sid (gid);
1393 	    gname_t	gname;
1394 	    gname.sid = sid;
1395 	    if (sid < cff1_std_strings_length)
1396 	      gname.name = cff1_std_strings (sid);
1397 	    else
1398 	    {
1399 	      hb_ubytes_t	ustr = (*stringIndex)[sid - cff1_std_strings_length];
1400 	      gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length);
1401 	    }
1402 	    if (unlikely (!gname.name.arrayZ))
1403 	      gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */
1404 	    names->push (gname);
1405 	  }
1406 	  names->qsort ();
1407 	}
1408 	if (unlikely (!glyph_names.cmpexch (nullptr, names)))
1409 	{
1410 	  if (names)
1411 	  {
1412 	    names->fini ();
1413 	    hb_free (names);
1414 	  }
1415 	  goto retry;
1416 	}
1417       }
1418 
1419       gname_t key = { hb_bytes_t (name, len), 0 };
1420       const gname_t *gname = names ? names->bsearch (key) : nullptr;
1421       if (!gname) return false;
1422       hb_codepoint_t gid = sid_to_glyph (gname->sid);
1423       if (!gid && gname->sid) return false;
1424       *glyph = gid;
1425       return true;
1426     }
1427 
1428     HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1429     HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
1430     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
1431 
1432     private:
1433     struct gname_t
1434     {
1435       hb_bytes_t	name;
1436       uint16_t		sid;
1437 
cmpOT::cff1::accelerator_t::gname_t1438       static int cmp (const void *a_, const void *b_)
1439       {
1440 	const gname_t *a = (const gname_t *)a_;
1441 	const gname_t *b = (const gname_t *)b_;
1442 	unsigned minlen = hb_min (a->name.length, b->name.length);
1443 	int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
1444 	if (ret) return ret;
1445 	return a->name.length - b->name.length;
1446       }
1447 
cmpOT::cff1::accelerator_t::gname_t1448       int cmp (const gname_t &a) const { return cmp (&a, this); }
1449     };
1450 
1451     mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
1452 
1453     typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
1454   };
1455 
1456   struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {};
1457 
subsetOT::cff11458   bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); }
1459 
1460   protected:
1461   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
1462   HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
1463   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
1464   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
1465   HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
1466   HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
1467   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
1468 
1469   public:
1470   FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
1471   NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
1472   HBUINT8	       offSize;	  /* offset size (unused?) */
1473 
1474   public:
1475   DEFINE_SIZE_STATIC (4);
1476 };
1477 
1478 struct cff1_accelerator_t : cff1::accelerator_t {
cff1_accelerator_tOT::cff1_accelerator_t1479   cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
1480 };
1481 
1482 } /* namespace OT */
1483 
1484 #endif /* HB_OT_CFF1_TABLE_HH */
1485