xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-ot-cff2-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_CFF2_TABLE_HH
28*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_CFF2_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 namespace CFF {
36*2d1272b8SAndroid Build Coastguard Worker 
37*2d1272b8SAndroid Build Coastguard Worker /*
38*2d1272b8SAndroid Build Coastguard Worker  * CFF2 -- Compact Font Format (CFF) Version 2
39*2d1272b8SAndroid Build Coastguard Worker  * https://docs.microsoft.com/en-us/typography/opentype/spec/cff2
40*2d1272b8SAndroid Build Coastguard Worker  */
41*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2')
42*2d1272b8SAndroid Build Coastguard Worker 
43*2d1272b8SAndroid Build Coastguard Worker typedef CFF2Index         CFF2CharStrings;
44*2d1272b8SAndroid Build Coastguard Worker typedef Subrs<HBUINT32>   CFF2Subrs;
45*2d1272b8SAndroid Build Coastguard Worker 
46*2d1272b8SAndroid Build Coastguard Worker typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
47*2d1272b8SAndroid Build Coastguard Worker typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
48*2d1272b8SAndroid Build Coastguard Worker 
49*2d1272b8SAndroid Build Coastguard Worker struct CFF2FDSelect
50*2d1272b8SAndroid Build Coastguard Worker {
serializeCFF::CFF2FDSelect51*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
52*2d1272b8SAndroid Build Coastguard Worker   {
53*2d1272b8SAndroid Build Coastguard Worker     TRACE_SERIALIZE (this);
54*2d1272b8SAndroid Build Coastguard Worker     unsigned int size = src.get_size (num_glyphs);
55*2d1272b8SAndroid Build Coastguard Worker     CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
56*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!dest)) return_trace (false);
57*2d1272b8SAndroid Build Coastguard Worker     hb_memcpy (dest, &src, size);
58*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
59*2d1272b8SAndroid Build Coastguard Worker   }
60*2d1272b8SAndroid Build Coastguard Worker 
get_sizeCFF::CFF2FDSelect61*2d1272b8SAndroid Build Coastguard Worker   unsigned int get_size (unsigned int num_glyphs) const
62*2d1272b8SAndroid Build Coastguard Worker   {
63*2d1272b8SAndroid Build Coastguard Worker     switch (format)
64*2d1272b8SAndroid Build Coastguard Worker     {
65*2d1272b8SAndroid Build Coastguard Worker     case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs);
66*2d1272b8SAndroid Build Coastguard Worker     case 3: hb_barrier (); return format.static_size + u.format3.get_size ();
67*2d1272b8SAndroid Build Coastguard Worker     case 4: hb_barrier (); return format.static_size + u.format4.get_size ();
68*2d1272b8SAndroid Build Coastguard Worker     default:return 0;
69*2d1272b8SAndroid Build Coastguard Worker     }
70*2d1272b8SAndroid Build Coastguard Worker   }
71*2d1272b8SAndroid Build Coastguard Worker 
get_fdCFF::CFF2FDSelect72*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
73*2d1272b8SAndroid Build Coastguard Worker   {
74*2d1272b8SAndroid Build Coastguard Worker     if (this == &Null (CFF2FDSelect))
75*2d1272b8SAndroid Build Coastguard Worker       return 0;
76*2d1272b8SAndroid Build Coastguard Worker 
77*2d1272b8SAndroid Build Coastguard Worker     switch (format)
78*2d1272b8SAndroid Build Coastguard Worker     {
79*2d1272b8SAndroid Build Coastguard Worker     case 0: hb_barrier (); return u.format0.get_fd (glyph);
80*2d1272b8SAndroid Build Coastguard Worker     case 3: hb_barrier (); return u.format3.get_fd (glyph);
81*2d1272b8SAndroid Build Coastguard Worker     case 4: hb_barrier (); return u.format4.get_fd (glyph);
82*2d1272b8SAndroid Build Coastguard Worker     default:return 0;
83*2d1272b8SAndroid Build Coastguard Worker     }
84*2d1272b8SAndroid Build Coastguard Worker   }
85*2d1272b8SAndroid Build Coastguard Worker 
sanitizeCFF::CFF2FDSelect86*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
87*2d1272b8SAndroid Build Coastguard Worker   {
88*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
89*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!c->check_struct (this)))
90*2d1272b8SAndroid Build Coastguard Worker       return_trace (false);
91*2d1272b8SAndroid Build Coastguard Worker     hb_barrier ();
92*2d1272b8SAndroid Build Coastguard Worker 
93*2d1272b8SAndroid Build Coastguard Worker     switch (format)
94*2d1272b8SAndroid Build Coastguard Worker     {
95*2d1272b8SAndroid Build Coastguard Worker     case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount));
96*2d1272b8SAndroid Build Coastguard Worker     case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount));
97*2d1272b8SAndroid Build Coastguard Worker     case 4: hb_barrier (); return_trace (u.format4.sanitize (c, fdcount));
98*2d1272b8SAndroid Build Coastguard Worker     default:return_trace (false);
99*2d1272b8SAndroid Build Coastguard Worker     }
100*2d1272b8SAndroid Build Coastguard Worker   }
101*2d1272b8SAndroid Build Coastguard Worker 
102*2d1272b8SAndroid Build Coastguard Worker   HBUINT8	format;
103*2d1272b8SAndroid Build Coastguard Worker   union {
104*2d1272b8SAndroid Build Coastguard Worker   FDSelect0	format0;
105*2d1272b8SAndroid Build Coastguard Worker   FDSelect3	format3;
106*2d1272b8SAndroid Build Coastguard Worker   FDSelect4	format4;
107*2d1272b8SAndroid Build Coastguard Worker   } u;
108*2d1272b8SAndroid Build Coastguard Worker   public:
109*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_MIN (2);
110*2d1272b8SAndroid Build Coastguard Worker };
111*2d1272b8SAndroid Build Coastguard Worker 
112*2d1272b8SAndroid Build Coastguard Worker struct CFF2ItemVariationStore
113*2d1272b8SAndroid Build Coastguard Worker {
sanitizeCFF::CFF2ItemVariationStore114*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c) const
115*2d1272b8SAndroid Build Coastguard Worker   {
116*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
117*2d1272b8SAndroid Build Coastguard Worker     return_trace (c->check_struct (this) &&
118*2d1272b8SAndroid Build Coastguard Worker 		  hb_barrier () &&
119*2d1272b8SAndroid Build Coastguard Worker 		  c->check_range (&varStore, size) &&
120*2d1272b8SAndroid Build Coastguard Worker 		  varStore.sanitize (c));
121*2d1272b8SAndroid Build Coastguard Worker   }
122*2d1272b8SAndroid Build Coastguard Worker 
serializeCFF::CFF2ItemVariationStore123*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c, const CFF2ItemVariationStore *varStore)
124*2d1272b8SAndroid Build Coastguard Worker   {
125*2d1272b8SAndroid Build Coastguard Worker     TRACE_SERIALIZE (this);
126*2d1272b8SAndroid Build Coastguard Worker     unsigned int size_ = varStore->get_size ();
127*2d1272b8SAndroid Build Coastguard Worker     CFF2ItemVariationStore *dest = c->allocate_size<CFF2ItemVariationStore> (size_);
128*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!dest)) return_trace (false);
129*2d1272b8SAndroid Build Coastguard Worker     hb_memcpy (dest, varStore, size_);
130*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
131*2d1272b8SAndroid Build Coastguard Worker   }
132*2d1272b8SAndroid Build Coastguard Worker 
get_sizeCFF::CFF2ItemVariationStore133*2d1272b8SAndroid Build Coastguard Worker   unsigned int get_size () const { return HBUINT16::static_size + size; }
134*2d1272b8SAndroid Build Coastguard Worker 
135*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	size;
136*2d1272b8SAndroid Build Coastguard Worker   ItemVariationStore  varStore;
137*2d1272b8SAndroid Build Coastguard Worker 
138*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_MIN (2 + ItemVariationStore::min_size);
139*2d1272b8SAndroid Build Coastguard Worker };
140*2d1272b8SAndroid Build Coastguard Worker 
141*2d1272b8SAndroid Build Coastguard Worker struct cff2_top_dict_values_t : top_dict_values_t<>
142*2d1272b8SAndroid Build Coastguard Worker {
initCFF::cff2_top_dict_values_t143*2d1272b8SAndroid Build Coastguard Worker   void init ()
144*2d1272b8SAndroid Build Coastguard Worker   {
145*2d1272b8SAndroid Build Coastguard Worker     top_dict_values_t<>::init ();
146*2d1272b8SAndroid Build Coastguard Worker     vstoreOffset = 0;
147*2d1272b8SAndroid Build Coastguard Worker     FDSelectOffset = 0;
148*2d1272b8SAndroid Build Coastguard Worker   }
finiCFF::cff2_top_dict_values_t149*2d1272b8SAndroid Build Coastguard Worker   void fini () { top_dict_values_t<>::fini (); }
150*2d1272b8SAndroid Build Coastguard Worker 
151*2d1272b8SAndroid Build Coastguard Worker   int  vstoreOffset;
152*2d1272b8SAndroid Build Coastguard Worker   int  FDSelectOffset;
153*2d1272b8SAndroid Build Coastguard Worker };
154*2d1272b8SAndroid Build Coastguard Worker 
155*2d1272b8SAndroid Build Coastguard Worker struct cff2_top_dict_opset_t : top_dict_opset_t<>
156*2d1272b8SAndroid Build Coastguard Worker {
process_opCFF::cff2_top_dict_opset_t157*2d1272b8SAndroid Build Coastguard Worker   static void process_op (op_code_t op, num_interp_env_t& env, cff2_top_dict_values_t& dictval)
158*2d1272b8SAndroid Build Coastguard Worker   {
159*2d1272b8SAndroid Build Coastguard Worker     switch (op) {
160*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FontMatrix:
161*2d1272b8SAndroid Build Coastguard Worker 	{
162*2d1272b8SAndroid Build Coastguard Worker 	  dict_val_t val;
163*2d1272b8SAndroid Build Coastguard Worker 	  val.init ();
164*2d1272b8SAndroid Build Coastguard Worker 	  dictval.add_op (op, env.str_ref);
165*2d1272b8SAndroid Build Coastguard Worker 	  env.clear_args ();
166*2d1272b8SAndroid Build Coastguard Worker 	}
167*2d1272b8SAndroid Build Coastguard Worker 	break;
168*2d1272b8SAndroid Build Coastguard Worker 
169*2d1272b8SAndroid Build Coastguard Worker       case OpCode_vstore:
170*2d1272b8SAndroid Build Coastguard Worker 	dictval.vstoreOffset = env.argStack.pop_int ();
171*2d1272b8SAndroid Build Coastguard Worker 	env.clear_args ();
172*2d1272b8SAndroid Build Coastguard Worker 	break;
173*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FDSelect:
174*2d1272b8SAndroid Build Coastguard Worker 	dictval.FDSelectOffset = env.argStack.pop_int ();
175*2d1272b8SAndroid Build Coastguard Worker 	env.clear_args ();
176*2d1272b8SAndroid Build Coastguard Worker 	break;
177*2d1272b8SAndroid Build Coastguard Worker 
178*2d1272b8SAndroid Build Coastguard Worker       default:
179*2d1272b8SAndroid Build Coastguard Worker 	SUPER::process_op (op, env, dictval);
180*2d1272b8SAndroid Build Coastguard Worker 	/* Record this operand below if stack is empty, otherwise done */
181*2d1272b8SAndroid Build Coastguard Worker 	if (!env.argStack.is_empty ()) return;
182*2d1272b8SAndroid Build Coastguard Worker     }
183*2d1272b8SAndroid Build Coastguard Worker 
184*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (env.in_error ())) return;
185*2d1272b8SAndroid Build Coastguard Worker 
186*2d1272b8SAndroid Build Coastguard Worker     dictval.add_op (op, env.str_ref);
187*2d1272b8SAndroid Build Coastguard Worker   }
188*2d1272b8SAndroid Build Coastguard Worker 
189*2d1272b8SAndroid Build Coastguard Worker   typedef top_dict_opset_t<> SUPER;
190*2d1272b8SAndroid Build Coastguard Worker };
191*2d1272b8SAndroid Build Coastguard Worker 
192*2d1272b8SAndroid Build Coastguard Worker struct cff2_font_dict_values_t : dict_values_t<op_str_t>
193*2d1272b8SAndroid Build Coastguard Worker {
initCFF::cff2_font_dict_values_t194*2d1272b8SAndroid Build Coastguard Worker   void init ()
195*2d1272b8SAndroid Build Coastguard Worker   {
196*2d1272b8SAndroid Build Coastguard Worker     dict_values_t<op_str_t>::init ();
197*2d1272b8SAndroid Build Coastguard Worker     privateDictInfo.init ();
198*2d1272b8SAndroid Build Coastguard Worker   }
finiCFF::cff2_font_dict_values_t199*2d1272b8SAndroid Build Coastguard Worker   void fini () { dict_values_t<op_str_t>::fini (); }
200*2d1272b8SAndroid Build Coastguard Worker 
201*2d1272b8SAndroid Build Coastguard Worker   table_info_t    privateDictInfo;
202*2d1272b8SAndroid Build Coastguard Worker };
203*2d1272b8SAndroid Build Coastguard Worker 
204*2d1272b8SAndroid Build Coastguard Worker struct cff2_font_dict_opset_t : dict_opset_t
205*2d1272b8SAndroid Build Coastguard Worker {
process_opCFF::cff2_font_dict_opset_t206*2d1272b8SAndroid Build Coastguard Worker   static void process_op (op_code_t op, num_interp_env_t& env, cff2_font_dict_values_t& dictval)
207*2d1272b8SAndroid Build Coastguard Worker   {
208*2d1272b8SAndroid Build Coastguard Worker     switch (op) {
209*2d1272b8SAndroid Build Coastguard Worker       case OpCode_Private:
210*2d1272b8SAndroid Build Coastguard Worker 	dictval.privateDictInfo.offset = env.argStack.pop_uint ();
211*2d1272b8SAndroid Build Coastguard Worker 	dictval.privateDictInfo.size = env.argStack.pop_uint ();
212*2d1272b8SAndroid Build Coastguard Worker 	env.clear_args ();
213*2d1272b8SAndroid Build Coastguard Worker 	break;
214*2d1272b8SAndroid Build Coastguard Worker 
215*2d1272b8SAndroid Build Coastguard Worker       default:
216*2d1272b8SAndroid Build Coastguard Worker 	SUPER::process_op (op, env);
217*2d1272b8SAndroid Build Coastguard Worker 	if (!env.argStack.is_empty ())
218*2d1272b8SAndroid Build Coastguard Worker 	  return;
219*2d1272b8SAndroid Build Coastguard Worker     }
220*2d1272b8SAndroid Build Coastguard Worker 
221*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (env.in_error ())) return;
222*2d1272b8SAndroid Build Coastguard Worker 
223*2d1272b8SAndroid Build Coastguard Worker     dictval.add_op (op, env.str_ref);
224*2d1272b8SAndroid Build Coastguard Worker   }
225*2d1272b8SAndroid Build Coastguard Worker 
226*2d1272b8SAndroid Build Coastguard Worker   private:
227*2d1272b8SAndroid Build Coastguard Worker   typedef dict_opset_t SUPER;
228*2d1272b8SAndroid Build Coastguard Worker };
229*2d1272b8SAndroid Build Coastguard Worker 
230*2d1272b8SAndroid Build Coastguard Worker template <typename VAL>
231*2d1272b8SAndroid Build Coastguard Worker struct cff2_private_dict_values_base_t : dict_values_t<VAL>
232*2d1272b8SAndroid Build Coastguard Worker {
initCFF::cff2_private_dict_values_base_t233*2d1272b8SAndroid Build Coastguard Worker   void init ()
234*2d1272b8SAndroid Build Coastguard Worker   {
235*2d1272b8SAndroid Build Coastguard Worker     dict_values_t<VAL>::init ();
236*2d1272b8SAndroid Build Coastguard Worker     subrsOffset = 0;
237*2d1272b8SAndroid Build Coastguard Worker     localSubrs = &Null (CFF2Subrs);
238*2d1272b8SAndroid Build Coastguard Worker     ivs = 0;
239*2d1272b8SAndroid Build Coastguard Worker   }
finiCFF::cff2_private_dict_values_base_t240*2d1272b8SAndroid Build Coastguard Worker   void fini () { dict_values_t<VAL>::fini (); }
241*2d1272b8SAndroid Build Coastguard Worker 
242*2d1272b8SAndroid Build Coastguard Worker   int                subrsOffset;
243*2d1272b8SAndroid Build Coastguard Worker   const CFF2Subrs   *localSubrs;
244*2d1272b8SAndroid Build Coastguard Worker   unsigned int      ivs;
245*2d1272b8SAndroid Build Coastguard Worker };
246*2d1272b8SAndroid Build Coastguard Worker 
247*2d1272b8SAndroid Build Coastguard Worker typedef cff2_private_dict_values_base_t<op_str_t> cff2_private_dict_values_subset_t;
248*2d1272b8SAndroid Build Coastguard Worker typedef cff2_private_dict_values_base_t<num_dict_val_t> cff2_private_dict_values_t;
249*2d1272b8SAndroid Build Coastguard Worker 
250*2d1272b8SAndroid Build Coastguard Worker struct cff2_priv_dict_interp_env_t : num_interp_env_t
251*2d1272b8SAndroid Build Coastguard Worker {
cff2_priv_dict_interp_env_tCFF::cff2_priv_dict_interp_env_t252*2d1272b8SAndroid Build Coastguard Worker   cff2_priv_dict_interp_env_t (const hb_ubytes_t &str) :
253*2d1272b8SAndroid Build Coastguard Worker     num_interp_env_t (str) {}
254*2d1272b8SAndroid Build Coastguard Worker 
process_vsindexCFF::cff2_priv_dict_interp_env_t255*2d1272b8SAndroid Build Coastguard Worker   void process_vsindex ()
256*2d1272b8SAndroid Build Coastguard Worker   {
257*2d1272b8SAndroid Build Coastguard Worker     if (likely (!seen_vsindex))
258*2d1272b8SAndroid Build Coastguard Worker     {
259*2d1272b8SAndroid Build Coastguard Worker       set_ivs (argStack.pop_uint ());
260*2d1272b8SAndroid Build Coastguard Worker     }
261*2d1272b8SAndroid Build Coastguard Worker     seen_vsindex = true;
262*2d1272b8SAndroid Build Coastguard Worker   }
263*2d1272b8SAndroid Build Coastguard Worker 
get_ivsCFF::cff2_priv_dict_interp_env_t264*2d1272b8SAndroid Build Coastguard Worker   unsigned int get_ivs () const { return ivs; }
set_ivsCFF::cff2_priv_dict_interp_env_t265*2d1272b8SAndroid Build Coastguard Worker   void	 set_ivs (unsigned int ivs_) { ivs = ivs_; }
266*2d1272b8SAndroid Build Coastguard Worker 
267*2d1272b8SAndroid Build Coastguard Worker   protected:
268*2d1272b8SAndroid Build Coastguard Worker   unsigned int  ivs = 0;
269*2d1272b8SAndroid Build Coastguard Worker   bool	  seen_vsindex = false;
270*2d1272b8SAndroid Build Coastguard Worker };
271*2d1272b8SAndroid Build Coastguard Worker 
272*2d1272b8SAndroid Build Coastguard Worker struct cff2_private_dict_opset_t : dict_opset_t
273*2d1272b8SAndroid Build Coastguard Worker {
process_opCFF::cff2_private_dict_opset_t274*2d1272b8SAndroid Build Coastguard Worker   static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_t& dictval)
275*2d1272b8SAndroid Build Coastguard Worker   {
276*2d1272b8SAndroid Build Coastguard Worker     num_dict_val_t val;
277*2d1272b8SAndroid Build Coastguard Worker     val.init ();
278*2d1272b8SAndroid Build Coastguard Worker 
279*2d1272b8SAndroid Build Coastguard Worker     switch (op) {
280*2d1272b8SAndroid Build Coastguard Worker       case OpCode_StdHW:
281*2d1272b8SAndroid Build Coastguard Worker       case OpCode_StdVW:
282*2d1272b8SAndroid Build Coastguard Worker       case OpCode_BlueScale:
283*2d1272b8SAndroid Build Coastguard Worker       case OpCode_BlueShift:
284*2d1272b8SAndroid Build Coastguard Worker       case OpCode_BlueFuzz:
285*2d1272b8SAndroid Build Coastguard Worker       case OpCode_ExpansionFactor:
286*2d1272b8SAndroid Build Coastguard Worker       case OpCode_LanguageGroup:
287*2d1272b8SAndroid Build Coastguard Worker       case OpCode_BlueValues:
288*2d1272b8SAndroid Build Coastguard Worker       case OpCode_OtherBlues:
289*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FamilyBlues:
290*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FamilyOtherBlues:
291*2d1272b8SAndroid Build Coastguard Worker       case OpCode_StemSnapH:
292*2d1272b8SAndroid Build Coastguard Worker       case OpCode_StemSnapV:
293*2d1272b8SAndroid Build Coastguard Worker 	env.clear_args ();
294*2d1272b8SAndroid Build Coastguard Worker 	break;
295*2d1272b8SAndroid Build Coastguard Worker       case OpCode_Subrs:
296*2d1272b8SAndroid Build Coastguard Worker 	dictval.subrsOffset = env.argStack.pop_int ();
297*2d1272b8SAndroid Build Coastguard Worker 	env.clear_args ();
298*2d1272b8SAndroid Build Coastguard Worker 	break;
299*2d1272b8SAndroid Build Coastguard Worker       case OpCode_vsindexdict:
300*2d1272b8SAndroid Build Coastguard Worker 	env.process_vsindex ();
301*2d1272b8SAndroid Build Coastguard Worker 	dictval.ivs = env.get_ivs ();
302*2d1272b8SAndroid Build Coastguard Worker 	env.clear_args ();
303*2d1272b8SAndroid Build Coastguard Worker 	break;
304*2d1272b8SAndroid Build Coastguard Worker       case OpCode_blenddict:
305*2d1272b8SAndroid Build Coastguard Worker 	break;
306*2d1272b8SAndroid Build Coastguard Worker 
307*2d1272b8SAndroid Build Coastguard Worker       default:
308*2d1272b8SAndroid Build Coastguard Worker 	dict_opset_t::process_op (op, env);
309*2d1272b8SAndroid Build Coastguard Worker 	if (!env.argStack.is_empty ()) return;
310*2d1272b8SAndroid Build Coastguard Worker 	break;
311*2d1272b8SAndroid Build Coastguard Worker     }
312*2d1272b8SAndroid Build Coastguard Worker 
313*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (env.in_error ())) return;
314*2d1272b8SAndroid Build Coastguard Worker 
315*2d1272b8SAndroid Build Coastguard Worker     dictval.add_op (op, env.str_ref, val);
316*2d1272b8SAndroid Build Coastguard Worker   }
317*2d1272b8SAndroid Build Coastguard Worker };
318*2d1272b8SAndroid Build Coastguard Worker 
319*2d1272b8SAndroid Build Coastguard Worker struct cff2_private_dict_opset_subset_t : dict_opset_t
320*2d1272b8SAndroid Build Coastguard Worker {
process_opCFF::cff2_private_dict_opset_subset_t321*2d1272b8SAndroid Build Coastguard Worker   static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_subset_t& dictval)
322*2d1272b8SAndroid Build Coastguard Worker   {
323*2d1272b8SAndroid Build Coastguard Worker     switch (op) {
324*2d1272b8SAndroid Build Coastguard Worker       case OpCode_BlueValues:
325*2d1272b8SAndroid Build Coastguard Worker       case OpCode_OtherBlues:
326*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FamilyBlues:
327*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FamilyOtherBlues:
328*2d1272b8SAndroid Build Coastguard Worker       case OpCode_StdHW:
329*2d1272b8SAndroid Build Coastguard Worker       case OpCode_StdVW:
330*2d1272b8SAndroid Build Coastguard Worker       case OpCode_BlueScale:
331*2d1272b8SAndroid Build Coastguard Worker       case OpCode_BlueShift:
332*2d1272b8SAndroid Build Coastguard Worker       case OpCode_BlueFuzz:
333*2d1272b8SAndroid Build Coastguard Worker       case OpCode_StemSnapH:
334*2d1272b8SAndroid Build Coastguard Worker       case OpCode_StemSnapV:
335*2d1272b8SAndroid Build Coastguard Worker       case OpCode_LanguageGroup:
336*2d1272b8SAndroid Build Coastguard Worker       case OpCode_ExpansionFactor:
337*2d1272b8SAndroid Build Coastguard Worker 	env.clear_args ();
338*2d1272b8SAndroid Build Coastguard Worker 	break;
339*2d1272b8SAndroid Build Coastguard Worker 
340*2d1272b8SAndroid Build Coastguard Worker       case OpCode_blenddict:
341*2d1272b8SAndroid Build Coastguard Worker 	env.clear_args ();
342*2d1272b8SAndroid Build Coastguard Worker 	return;
343*2d1272b8SAndroid Build Coastguard Worker 
344*2d1272b8SAndroid Build Coastguard Worker       case OpCode_Subrs:
345*2d1272b8SAndroid Build Coastguard Worker 	dictval.subrsOffset = env.argStack.pop_int ();
346*2d1272b8SAndroid Build Coastguard Worker 	env.clear_args ();
347*2d1272b8SAndroid Build Coastguard Worker 	break;
348*2d1272b8SAndroid Build Coastguard Worker 
349*2d1272b8SAndroid Build Coastguard Worker       default:
350*2d1272b8SAndroid Build Coastguard Worker 	SUPER::process_op (op, env);
351*2d1272b8SAndroid Build Coastguard Worker 	if (!env.argStack.is_empty ()) return;
352*2d1272b8SAndroid Build Coastguard Worker 	break;
353*2d1272b8SAndroid Build Coastguard Worker     }
354*2d1272b8SAndroid Build Coastguard Worker 
355*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (env.in_error ())) return;
356*2d1272b8SAndroid Build Coastguard Worker 
357*2d1272b8SAndroid Build Coastguard Worker     dictval.add_op (op, env.str_ref);
358*2d1272b8SAndroid Build Coastguard Worker   }
359*2d1272b8SAndroid Build Coastguard Worker 
360*2d1272b8SAndroid Build Coastguard Worker   private:
361*2d1272b8SAndroid Build Coastguard Worker   typedef dict_opset_t SUPER;
362*2d1272b8SAndroid Build Coastguard Worker };
363*2d1272b8SAndroid Build Coastguard Worker 
364*2d1272b8SAndroid Build Coastguard Worker typedef dict_interpreter_t<cff2_top_dict_opset_t, cff2_top_dict_values_t> cff2_top_dict_interpreter_t;
365*2d1272b8SAndroid Build Coastguard Worker typedef dict_interpreter_t<cff2_font_dict_opset_t, cff2_font_dict_values_t> cff2_font_dict_interpreter_t;
366*2d1272b8SAndroid Build Coastguard Worker 
367*2d1272b8SAndroid Build Coastguard Worker struct CFF2FDArray : FDArray<HBUINT32>
368*2d1272b8SAndroid Build Coastguard Worker {
369*2d1272b8SAndroid Build Coastguard Worker   /* FDArray::serialize does not compile without this partial specialization */
370*2d1272b8SAndroid Build Coastguard Worker   template <typename ITER, typename OP_SERIALIZER>
serializeCFF::CFF2FDArray371*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
372*2d1272b8SAndroid Build Coastguard Worker   { return FDArray<HBUINT32>::serialize<cff2_font_dict_values_t, table_info_t> (c, it, opszr); }
373*2d1272b8SAndroid Build Coastguard Worker };
374*2d1272b8SAndroid Build Coastguard Worker 
375*2d1272b8SAndroid Build Coastguard Worker } /* namespace CFF */
376*2d1272b8SAndroid Build Coastguard Worker 
377*2d1272b8SAndroid Build Coastguard Worker namespace OT {
378*2d1272b8SAndroid Build Coastguard Worker 
379*2d1272b8SAndroid Build Coastguard Worker using namespace CFF;
380*2d1272b8SAndroid Build Coastguard Worker 
381*2d1272b8SAndroid Build Coastguard Worker struct cff2
382*2d1272b8SAndroid Build Coastguard Worker {
383*2d1272b8SAndroid Build Coastguard Worker   static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF2;
384*2d1272b8SAndroid Build Coastguard Worker 
sanitizeOT::cff2385*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c) const
386*2d1272b8SAndroid Build Coastguard Worker   {
387*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
388*2d1272b8SAndroid Build Coastguard Worker     return_trace (c->check_struct (this) &&
389*2d1272b8SAndroid Build Coastguard Worker 		  hb_barrier () &&
390*2d1272b8SAndroid Build Coastguard Worker 		  likely (version.major == 2));
391*2d1272b8SAndroid Build Coastguard Worker   }
392*2d1272b8SAndroid Build Coastguard Worker 
393*2d1272b8SAndroid Build Coastguard Worker   template <typename PRIVOPSET, typename PRIVDICTVAL>
394*2d1272b8SAndroid Build Coastguard Worker   struct accelerator_templ_t
395*2d1272b8SAndroid Build Coastguard Worker   {
396*2d1272b8SAndroid Build Coastguard Worker     static constexpr hb_tag_t tableTag = cff2::tableTag;
397*2d1272b8SAndroid Build Coastguard Worker 
accelerator_templ_tOT::cff2::accelerator_templ_t398*2d1272b8SAndroid Build Coastguard Worker     accelerator_templ_t (hb_face_t *face)
399*2d1272b8SAndroid Build Coastguard Worker     {
400*2d1272b8SAndroid Build Coastguard Worker       if (!face) return;
401*2d1272b8SAndroid Build Coastguard Worker 
402*2d1272b8SAndroid Build Coastguard Worker       topDict.init ();
403*2d1272b8SAndroid Build Coastguard Worker       fontDicts.init ();
404*2d1272b8SAndroid Build Coastguard Worker       privateDicts.init ();
405*2d1272b8SAndroid Build Coastguard Worker 
406*2d1272b8SAndroid Build Coastguard Worker       this->blob = sc.reference_table<cff2> (face);
407*2d1272b8SAndroid Build Coastguard Worker 
408*2d1272b8SAndroid Build Coastguard Worker       /* setup for run-time santization */
409*2d1272b8SAndroid Build Coastguard Worker       sc.init (this->blob);
410*2d1272b8SAndroid Build Coastguard Worker       sc.start_processing ();
411*2d1272b8SAndroid Build Coastguard Worker 
412*2d1272b8SAndroid Build Coastguard Worker       const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
413*2d1272b8SAndroid Build Coastguard Worker 
414*2d1272b8SAndroid Build Coastguard Worker       if (cff2 == &Null (OT::cff2))
415*2d1272b8SAndroid Build Coastguard Worker         goto fail;
416*2d1272b8SAndroid Build Coastguard Worker 
417*2d1272b8SAndroid Build Coastguard Worker       { /* parse top dict */
418*2d1272b8SAndroid Build Coastguard Worker 	hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize);
419*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
420*2d1272b8SAndroid Build Coastguard Worker 	hb_barrier ();
421*2d1272b8SAndroid Build Coastguard Worker 	num_interp_env_t env (topDictStr);
422*2d1272b8SAndroid Build Coastguard Worker 	cff2_top_dict_interpreter_t top_interp (env);
423*2d1272b8SAndroid Build Coastguard Worker 	topDict.init ();
424*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (!top_interp.interpret (topDict))) goto fail;
425*2d1272b8SAndroid Build Coastguard Worker       }
426*2d1272b8SAndroid Build Coastguard Worker 
427*2d1272b8SAndroid Build Coastguard Worker       globalSubrs = &StructAtOffsetOrNull<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize, sc);
428*2d1272b8SAndroid Build Coastguard Worker       varStore = &StructAtOffsetOrNull<CFF2ItemVariationStore> (cff2, topDict.vstoreOffset, sc);
429*2d1272b8SAndroid Build Coastguard Worker       charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset, sc);
430*2d1272b8SAndroid Build Coastguard Worker       fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset, sc);
431*2d1272b8SAndroid Build Coastguard Worker       fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset, sc, fdArray->count);
432*2d1272b8SAndroid Build Coastguard Worker 
433*2d1272b8SAndroid Build Coastguard Worker       if (charStrings == &Null (CFF2CharStrings) ||
434*2d1272b8SAndroid Build Coastguard Worker 	  globalSubrs == &Null (CFF2Subrs) ||
435*2d1272b8SAndroid Build Coastguard Worker 	  fdArray == &Null (CFF2FDArray))
436*2d1272b8SAndroid Build Coastguard Worker         goto fail;
437*2d1272b8SAndroid Build Coastguard Worker 
438*2d1272b8SAndroid Build Coastguard Worker       num_glyphs = charStrings->count;
439*2d1272b8SAndroid Build Coastguard Worker       if (num_glyphs != sc.get_num_glyphs ())
440*2d1272b8SAndroid Build Coastguard Worker         goto fail;
441*2d1272b8SAndroid Build Coastguard Worker 
442*2d1272b8SAndroid Build Coastguard Worker       fdCount = fdArray->count;
443*2d1272b8SAndroid Build Coastguard Worker       if (!privateDicts.resize (fdCount))
444*2d1272b8SAndroid Build Coastguard Worker         goto fail;
445*2d1272b8SAndroid Build Coastguard Worker 
446*2d1272b8SAndroid Build Coastguard Worker       /* parse font dicts and gather private dicts */
447*2d1272b8SAndroid Build Coastguard Worker       for (unsigned int i = 0; i < fdCount; i++)
448*2d1272b8SAndroid Build Coastguard Worker       {
449*2d1272b8SAndroid Build Coastguard Worker 	const hb_ubytes_t fontDictStr = (*fdArray)[i];
450*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
451*2d1272b8SAndroid Build Coastguard Worker 	hb_barrier ();
452*2d1272b8SAndroid Build Coastguard Worker 	cff2_font_dict_values_t  *font;
453*2d1272b8SAndroid Build Coastguard Worker 	num_interp_env_t env (fontDictStr);
454*2d1272b8SAndroid Build Coastguard Worker 	cff2_font_dict_interpreter_t font_interp (env);
455*2d1272b8SAndroid Build Coastguard Worker 	font = fontDicts.push ();
456*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail;
457*2d1272b8SAndroid Build Coastguard Worker 	font->init ();
458*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (!font_interp.interpret (*font))) goto fail;
459*2d1272b8SAndroid Build Coastguard Worker 
460*2d1272b8SAndroid Build Coastguard Worker 	const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
461*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
462*2d1272b8SAndroid Build Coastguard Worker 	cff2_priv_dict_interp_env_t env2 (privDictStr);
463*2d1272b8SAndroid Build Coastguard Worker 	dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2);
464*2d1272b8SAndroid Build Coastguard Worker 	privateDicts[i].init ();
465*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
466*2d1272b8SAndroid Build Coastguard Worker 
467*2d1272b8SAndroid Build Coastguard Worker 	privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset, sc);
468*2d1272b8SAndroid Build Coastguard Worker       }
469*2d1272b8SAndroid Build Coastguard Worker 
470*2d1272b8SAndroid Build Coastguard Worker       return;
471*2d1272b8SAndroid Build Coastguard Worker 
472*2d1272b8SAndroid Build Coastguard Worker       fail:
473*2d1272b8SAndroid Build Coastguard Worker         _fini ();
474*2d1272b8SAndroid Build Coastguard Worker     }
~accelerator_templ_tOT::cff2::accelerator_templ_t475*2d1272b8SAndroid Build Coastguard Worker     ~accelerator_templ_t () { _fini (); }
_finiOT::cff2::accelerator_templ_t476*2d1272b8SAndroid Build Coastguard Worker     void _fini ()
477*2d1272b8SAndroid Build Coastguard Worker     {
478*2d1272b8SAndroid Build Coastguard Worker       sc.end_processing ();
479*2d1272b8SAndroid Build Coastguard Worker       topDict.fini ();
480*2d1272b8SAndroid Build Coastguard Worker       fontDicts.fini ();
481*2d1272b8SAndroid Build Coastguard Worker       privateDicts.fini ();
482*2d1272b8SAndroid Build Coastguard Worker       hb_blob_destroy (blob);
483*2d1272b8SAndroid Build Coastguard Worker       blob = nullptr;
484*2d1272b8SAndroid Build Coastguard Worker     }
485*2d1272b8SAndroid Build Coastguard Worker 
create_glyph_to_sid_mapOT::cff2::accelerator_templ_t486*2d1272b8SAndroid Build Coastguard Worker     hb_vector_t<uint16_t> *create_glyph_to_sid_map () const
487*2d1272b8SAndroid Build Coastguard Worker     {
488*2d1272b8SAndroid Build Coastguard Worker       return nullptr;
489*2d1272b8SAndroid Build Coastguard Worker     }
490*2d1272b8SAndroid Build Coastguard Worker 
get_blobOT::cff2::accelerator_templ_t491*2d1272b8SAndroid Build Coastguard Worker     hb_blob_t *get_blob () const { return blob; }
492*2d1272b8SAndroid Build Coastguard Worker 
is_validOT::cff2::accelerator_templ_t493*2d1272b8SAndroid Build Coastguard Worker     bool is_valid () const { return blob; }
494*2d1272b8SAndroid Build Coastguard Worker 
495*2d1272b8SAndroid Build Coastguard Worker     protected:
496*2d1272b8SAndroid Build Coastguard Worker     hb_sanitize_context_t	sc;
497*2d1272b8SAndroid Build Coastguard Worker 
498*2d1272b8SAndroid Build Coastguard Worker     public:
499*2d1272b8SAndroid Build Coastguard Worker     hb_blob_t			*blob = nullptr;
500*2d1272b8SAndroid Build Coastguard Worker     cff2_top_dict_values_t	topDict;
501*2d1272b8SAndroid Build Coastguard Worker     const CFF2Subrs		*globalSubrs = nullptr;
502*2d1272b8SAndroid Build Coastguard Worker     const CFF2ItemVariationStore	*varStore = nullptr;
503*2d1272b8SAndroid Build Coastguard Worker     const CFF2CharStrings	*charStrings = nullptr;
504*2d1272b8SAndroid Build Coastguard Worker     const CFF2FDArray		*fdArray = nullptr;
505*2d1272b8SAndroid Build Coastguard Worker     const CFF2FDSelect		*fdSelect = nullptr;
506*2d1272b8SAndroid Build Coastguard Worker     unsigned int		fdCount = 0;
507*2d1272b8SAndroid Build Coastguard Worker 
508*2d1272b8SAndroid Build Coastguard Worker     hb_vector_t<cff2_font_dict_values_t>     fontDicts;
509*2d1272b8SAndroid Build Coastguard Worker     hb_vector_t<PRIVDICTVAL>  privateDicts;
510*2d1272b8SAndroid Build Coastguard Worker 
511*2d1272b8SAndroid Build Coastguard Worker     unsigned int	      num_glyphs = 0;
512*2d1272b8SAndroid Build Coastguard Worker   };
513*2d1272b8SAndroid Build Coastguard Worker 
514*2d1272b8SAndroid Build Coastguard Worker   struct accelerator_t : accelerator_templ_t<cff2_private_dict_opset_t, cff2_private_dict_values_t>
515*2d1272b8SAndroid Build Coastguard Worker   {
accelerator_tOT::cff2::accelerator_t516*2d1272b8SAndroid Build Coastguard Worker     accelerator_t (hb_face_t *face) : accelerator_templ_t (face) {}
517*2d1272b8SAndroid Build Coastguard Worker 
518*2d1272b8SAndroid Build Coastguard Worker     HB_INTERNAL bool get_extents (hb_font_t *font,
519*2d1272b8SAndroid Build Coastguard Worker 				  hb_codepoint_t glyph,
520*2d1272b8SAndroid Build Coastguard Worker 				  hb_glyph_extents_t *extents) const;
521*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;
522*2d1272b8SAndroid Build Coastguard Worker     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
523*2d1272b8SAndroid Build Coastguard Worker     HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t<const int> coords) const;
524*2d1272b8SAndroid Build Coastguard Worker   };
525*2d1272b8SAndroid Build Coastguard Worker 
526*2d1272b8SAndroid Build Coastguard Worker   struct accelerator_subset_t : accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t>
527*2d1272b8SAndroid Build Coastguard Worker   {
accelerator_subset_tOT::cff2::accelerator_subset_t528*2d1272b8SAndroid Build Coastguard Worker     accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
~accelerator_subset_tOT::cff2::accelerator_subset_t529*2d1272b8SAndroid Build Coastguard Worker     ~accelerator_subset_t ()
530*2d1272b8SAndroid Build Coastguard Worker     {
531*2d1272b8SAndroid Build Coastguard Worker       if (cff_accelerator)
532*2d1272b8SAndroid Build Coastguard Worker 	cff_subset_accelerator_t::destroy (cff_accelerator);
533*2d1272b8SAndroid Build Coastguard Worker     }
534*2d1272b8SAndroid Build Coastguard Worker 
535*2d1272b8SAndroid Build Coastguard Worker     HB_INTERNAL bool subset (hb_subset_context_t *c) const;
536*2d1272b8SAndroid Build Coastguard Worker     HB_INTERNAL bool serialize (hb_serialize_context_t *c,
537*2d1272b8SAndroid Build Coastguard Worker 				struct cff2_subset_plan &plan,
538*2d1272b8SAndroid Build Coastguard Worker 				hb_array_t<int> normalized_coords) const;
539*2d1272b8SAndroid Build Coastguard Worker 
540*2d1272b8SAndroid Build Coastguard Worker     mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
541*2d1272b8SAndroid Build Coastguard Worker 
542*2d1272b8SAndroid Build Coastguard Worker     typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> SUPER;
543*2d1272b8SAndroid Build Coastguard Worker   };
544*2d1272b8SAndroid Build Coastguard Worker 
545*2d1272b8SAndroid Build Coastguard Worker   public:
546*2d1272b8SAndroid Build Coastguard Worker   FixedVersion<HBUINT8>		version;	/* Version of CFF2 table. set to 0x0200u */
547*2d1272b8SAndroid Build Coastguard Worker   NNOffsetTo<TopDict, HBUINT8>	topDict;	/* headerSize = Offset to Top DICT. */
548*2d1272b8SAndroid Build Coastguard Worker   HBUINT16			topDictSize;	/* Top DICT size */
549*2d1272b8SAndroid Build Coastguard Worker 
550*2d1272b8SAndroid Build Coastguard Worker   public:
551*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_STATIC (5);
552*2d1272b8SAndroid Build Coastguard Worker };
553*2d1272b8SAndroid Build Coastguard Worker 
554*2d1272b8SAndroid Build Coastguard Worker struct cff2_accelerator_t : cff2::accelerator_t {
cff2_accelerator_tOT::cff2_accelerator_t555*2d1272b8SAndroid Build Coastguard Worker   cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {}
556*2d1272b8SAndroid Build Coastguard Worker };
557*2d1272b8SAndroid Build Coastguard Worker 
558*2d1272b8SAndroid Build Coastguard Worker struct cff2_subset_accelerator_t : cff2::accelerator_subset_t {
cff2_subset_accelerator_tOT::cff2_subset_accelerator_t559*2d1272b8SAndroid Build Coastguard Worker   cff2_subset_accelerator_t (hb_face_t *face) : cff2::accelerator_subset_t (face) {}
560*2d1272b8SAndroid Build Coastguard Worker };
561*2d1272b8SAndroid Build Coastguard Worker 
562*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */
563*2d1272b8SAndroid Build Coastguard Worker 
564*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_OT_CFF2_TABLE_HH */
565