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