xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-subset-cff1.cc (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 #include "hb.hh"
28*2d1272b8SAndroid Build Coastguard Worker 
29*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_CFF
30*2d1272b8SAndroid Build Coastguard Worker 
31*2d1272b8SAndroid Build Coastguard Worker #include "hb-open-type.hh"
32*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-cff1-table.hh"
33*2d1272b8SAndroid Build Coastguard Worker #include "hb-set.h"
34*2d1272b8SAndroid Build Coastguard Worker #include "hb-bimap.hh"
35*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-plan.hh"
36*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-cff-common.hh"
37*2d1272b8SAndroid Build Coastguard Worker #include "hb-cff1-interp-cs.hh"
38*2d1272b8SAndroid Build Coastguard Worker 
39*2d1272b8SAndroid Build Coastguard Worker using namespace CFF;
40*2d1272b8SAndroid Build Coastguard Worker 
41*2d1272b8SAndroid Build Coastguard Worker struct remap_sid_t
42*2d1272b8SAndroid Build Coastguard Worker {
get_populationremap_sid_t43*2d1272b8SAndroid Build Coastguard Worker   unsigned get_population () const { return vector.length; }
44*2d1272b8SAndroid Build Coastguard Worker 
allocremap_sid_t45*2d1272b8SAndroid Build Coastguard Worker   void alloc (unsigned size)
46*2d1272b8SAndroid Build Coastguard Worker   {
47*2d1272b8SAndroid Build Coastguard Worker     map.alloc (size);
48*2d1272b8SAndroid Build Coastguard Worker     vector.alloc (size, true);
49*2d1272b8SAndroid Build Coastguard Worker   }
50*2d1272b8SAndroid Build Coastguard Worker 
in_errorremap_sid_t51*2d1272b8SAndroid Build Coastguard Worker   bool in_error () const
52*2d1272b8SAndroid Build Coastguard Worker   { return map.in_error () || vector.in_error (); }
53*2d1272b8SAndroid Build Coastguard Worker 
addremap_sid_t54*2d1272b8SAndroid Build Coastguard Worker   unsigned int add (unsigned int sid)
55*2d1272b8SAndroid Build Coastguard Worker   {
56*2d1272b8SAndroid Build Coastguard Worker     if (is_std_str (sid) || (sid == CFF_UNDEF_SID))
57*2d1272b8SAndroid Build Coastguard Worker       return sid;
58*2d1272b8SAndroid Build Coastguard Worker 
59*2d1272b8SAndroid Build Coastguard Worker     sid = unoffset_sid (sid);
60*2d1272b8SAndroid Build Coastguard Worker     unsigned v = next;
61*2d1272b8SAndroid Build Coastguard Worker     if (map.set (sid, v, false))
62*2d1272b8SAndroid Build Coastguard Worker     {
63*2d1272b8SAndroid Build Coastguard Worker       vector.push (sid);
64*2d1272b8SAndroid Build Coastguard Worker       next++;
65*2d1272b8SAndroid Build Coastguard Worker     }
66*2d1272b8SAndroid Build Coastguard Worker     else
67*2d1272b8SAndroid Build Coastguard Worker       v = map.get (sid); // already exists
68*2d1272b8SAndroid Build Coastguard Worker     return offset_sid (v);
69*2d1272b8SAndroid Build Coastguard Worker   }
70*2d1272b8SAndroid Build Coastguard Worker 
operator []remap_sid_t71*2d1272b8SAndroid Build Coastguard Worker   unsigned int operator[] (unsigned int sid) const
72*2d1272b8SAndroid Build Coastguard Worker   {
73*2d1272b8SAndroid Build Coastguard Worker     if (is_std_str (sid) || (sid == CFF_UNDEF_SID))
74*2d1272b8SAndroid Build Coastguard Worker       return sid;
75*2d1272b8SAndroid Build Coastguard Worker 
76*2d1272b8SAndroid Build Coastguard Worker     return offset_sid (map.get (unoffset_sid (sid)));
77*2d1272b8SAndroid Build Coastguard Worker   }
78*2d1272b8SAndroid Build Coastguard Worker 
79*2d1272b8SAndroid Build Coastguard Worker   static const unsigned int num_std_strings = 391;
80*2d1272b8SAndroid Build Coastguard Worker 
is_std_strremap_sid_t81*2d1272b8SAndroid Build Coastguard Worker   static bool is_std_str (unsigned int sid) { return sid < num_std_strings; }
offset_sidremap_sid_t82*2d1272b8SAndroid Build Coastguard Worker   static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
unoffset_sidremap_sid_t83*2d1272b8SAndroid Build Coastguard Worker   static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
84*2d1272b8SAndroid Build Coastguard Worker   unsigned next = 0;
85*2d1272b8SAndroid Build Coastguard Worker 
86*2d1272b8SAndroid Build Coastguard Worker   hb_map_t map;
87*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<unsigned> vector;
88*2d1272b8SAndroid Build Coastguard Worker };
89*2d1272b8SAndroid Build Coastguard Worker 
90*2d1272b8SAndroid Build Coastguard Worker struct cff1_sub_table_info_t : cff_sub_table_info_t
91*2d1272b8SAndroid Build Coastguard Worker {
cff1_sub_table_info_tcff1_sub_table_info_t92*2d1272b8SAndroid Build Coastguard Worker   cff1_sub_table_info_t ()
93*2d1272b8SAndroid Build Coastguard Worker     : cff_sub_table_info_t (),
94*2d1272b8SAndroid Build Coastguard Worker       encoding_link (0),
95*2d1272b8SAndroid Build Coastguard Worker       charset_link (0)
96*2d1272b8SAndroid Build Coastguard Worker    {
97*2d1272b8SAndroid Build Coastguard Worker     privateDictInfo.init ();
98*2d1272b8SAndroid Build Coastguard Worker   }
99*2d1272b8SAndroid Build Coastguard Worker 
100*2d1272b8SAndroid Build Coastguard Worker   objidx_t	encoding_link;
101*2d1272b8SAndroid Build Coastguard Worker   objidx_t	charset_link;
102*2d1272b8SAndroid Build Coastguard Worker   table_info_t	privateDictInfo;
103*2d1272b8SAndroid Build Coastguard Worker };
104*2d1272b8SAndroid Build Coastguard Worker 
105*2d1272b8SAndroid Build Coastguard Worker /* a copy of a parsed out cff1_top_dict_values_t augmented with additional operators */
106*2d1272b8SAndroid Build Coastguard Worker struct cff1_top_dict_values_mod_t : cff1_top_dict_values_t
107*2d1272b8SAndroid Build Coastguard Worker {
initcff1_top_dict_values_mod_t108*2d1272b8SAndroid Build Coastguard Worker   void init (const cff1_top_dict_values_t *base_= &Null (cff1_top_dict_values_t))
109*2d1272b8SAndroid Build Coastguard Worker   {
110*2d1272b8SAndroid Build Coastguard Worker     SUPER::init ();
111*2d1272b8SAndroid Build Coastguard Worker     base = base_;
112*2d1272b8SAndroid Build Coastguard Worker   }
113*2d1272b8SAndroid Build Coastguard Worker 
finicff1_top_dict_values_mod_t114*2d1272b8SAndroid Build Coastguard Worker   void fini () { SUPER::fini (); }
115*2d1272b8SAndroid Build Coastguard Worker 
get_countcff1_top_dict_values_mod_t116*2d1272b8SAndroid Build Coastguard Worker   unsigned get_count () const { return base->get_count () + SUPER::get_count (); }
get_valuecff1_top_dict_values_mod_t117*2d1272b8SAndroid Build Coastguard Worker   const cff1_top_dict_val_t &get_value (unsigned int i) const
118*2d1272b8SAndroid Build Coastguard Worker   {
119*2d1272b8SAndroid Build Coastguard Worker     if (i < base->get_count ())
120*2d1272b8SAndroid Build Coastguard Worker       return (*base)[i];
121*2d1272b8SAndroid Build Coastguard Worker     else
122*2d1272b8SAndroid Build Coastguard Worker       return SUPER::values[i - base->get_count ()];
123*2d1272b8SAndroid Build Coastguard Worker   }
operator []cff1_top_dict_values_mod_t124*2d1272b8SAndroid Build Coastguard Worker   const cff1_top_dict_val_t &operator [] (unsigned int i) const { return get_value (i); }
125*2d1272b8SAndroid Build Coastguard Worker 
reassignSIDscff1_top_dict_values_mod_t126*2d1272b8SAndroid Build Coastguard Worker   void reassignSIDs (const remap_sid_t& sidmap)
127*2d1272b8SAndroid Build Coastguard Worker   {
128*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
129*2d1272b8SAndroid Build Coastguard Worker       nameSIDs[i] = sidmap[base->nameSIDs[i]];
130*2d1272b8SAndroid Build Coastguard Worker   }
131*2d1272b8SAndroid Build Coastguard Worker 
132*2d1272b8SAndroid Build Coastguard Worker   protected:
133*2d1272b8SAndroid Build Coastguard Worker   typedef cff1_top_dict_values_t SUPER;
134*2d1272b8SAndroid Build Coastguard Worker   const cff1_top_dict_values_t *base;
135*2d1272b8SAndroid Build Coastguard Worker };
136*2d1272b8SAndroid Build Coastguard Worker 
137*2d1272b8SAndroid Build Coastguard Worker struct top_dict_modifiers_t
138*2d1272b8SAndroid Build Coastguard Worker {
top_dict_modifiers_ttop_dict_modifiers_t139*2d1272b8SAndroid Build Coastguard Worker   top_dict_modifiers_t (const cff1_sub_table_info_t &info_,
140*2d1272b8SAndroid Build Coastguard Worker 			const unsigned int (&nameSIDs_)[name_dict_values_t::ValCount])
141*2d1272b8SAndroid Build Coastguard Worker     : info (info_),
142*2d1272b8SAndroid Build Coastguard Worker       nameSIDs (nameSIDs_)
143*2d1272b8SAndroid Build Coastguard Worker   {}
144*2d1272b8SAndroid Build Coastguard Worker 
145*2d1272b8SAndroid Build Coastguard Worker   const cff1_sub_table_info_t &info;
146*2d1272b8SAndroid Build Coastguard Worker   const unsigned int	(&nameSIDs)[name_dict_values_t::ValCount];
147*2d1272b8SAndroid Build Coastguard Worker };
148*2d1272b8SAndroid Build Coastguard Worker 
149*2d1272b8SAndroid Build Coastguard Worker struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dict_val_t>
150*2d1272b8SAndroid Build Coastguard Worker {
serializecff1_top_dict_op_serializer_t151*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c,
152*2d1272b8SAndroid Build Coastguard Worker 		  const cff1_top_dict_val_t &opstr,
153*2d1272b8SAndroid Build Coastguard Worker 		  const top_dict_modifiers_t &mod) const
154*2d1272b8SAndroid Build Coastguard Worker   {
155*2d1272b8SAndroid Build Coastguard Worker     TRACE_SERIALIZE (this);
156*2d1272b8SAndroid Build Coastguard Worker 
157*2d1272b8SAndroid Build Coastguard Worker     op_code_t op = opstr.op;
158*2d1272b8SAndroid Build Coastguard Worker     switch (op)
159*2d1272b8SAndroid Build Coastguard Worker     {
160*2d1272b8SAndroid Build Coastguard Worker       case OpCode_charset:
161*2d1272b8SAndroid Build Coastguard Worker 	if (mod.info.charset_link)
162*2d1272b8SAndroid Build Coastguard Worker 	  return_trace (FontDict::serialize_link4_op(c, op, mod.info.charset_link, whence_t::Absolute));
163*2d1272b8SAndroid Build Coastguard Worker 	else
164*2d1272b8SAndroid Build Coastguard Worker 	  goto fall_back;
165*2d1272b8SAndroid Build Coastguard Worker 
166*2d1272b8SAndroid Build Coastguard Worker       case OpCode_Encoding:
167*2d1272b8SAndroid Build Coastguard Worker 	if (mod.info.encoding_link)
168*2d1272b8SAndroid Build Coastguard Worker 	  return_trace (FontDict::serialize_link4_op(c, op, mod.info.encoding_link, whence_t::Absolute));
169*2d1272b8SAndroid Build Coastguard Worker 	else
170*2d1272b8SAndroid Build Coastguard Worker 	  goto fall_back;
171*2d1272b8SAndroid Build Coastguard Worker 
172*2d1272b8SAndroid Build Coastguard Worker       case OpCode_Private:
173*2d1272b8SAndroid Build Coastguard Worker 	return_trace (UnsizedByteStr::serialize_int2 (c, mod.info.privateDictInfo.size) &&
174*2d1272b8SAndroid Build Coastguard Worker 		      Dict::serialize_link4_op (c, op, mod.info.privateDictInfo.link, whence_t::Absolute));
175*2d1272b8SAndroid Build Coastguard Worker 
176*2d1272b8SAndroid Build Coastguard Worker       case OpCode_version:
177*2d1272b8SAndroid Build Coastguard Worker       case OpCode_Notice:
178*2d1272b8SAndroid Build Coastguard Worker       case OpCode_Copyright:
179*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FullName:
180*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FamilyName:
181*2d1272b8SAndroid Build Coastguard Worker       case OpCode_Weight:
182*2d1272b8SAndroid Build Coastguard Worker       case OpCode_PostScript:
183*2d1272b8SAndroid Build Coastguard Worker       case OpCode_BaseFontName:
184*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FontName:
185*2d1272b8SAndroid Build Coastguard Worker 	return_trace (FontDict::serialize_int2_op (c, op, mod.nameSIDs[name_dict_values_t::name_op_to_index (op)]));
186*2d1272b8SAndroid Build Coastguard Worker 
187*2d1272b8SAndroid Build Coastguard Worker       case OpCode_ROS:
188*2d1272b8SAndroid Build Coastguard Worker 	{
189*2d1272b8SAndroid Build Coastguard Worker 	  /* for registry & ordering, reassigned SIDs are serialized
190*2d1272b8SAndroid Build Coastguard Worker 	   * for supplement, the original byte string is copied along with the op code */
191*2d1272b8SAndroid Build Coastguard Worker 	  op_str_t supp_op;
192*2d1272b8SAndroid Build Coastguard Worker 	  supp_op.op = op;
193*2d1272b8SAndroid Build Coastguard Worker 	  if ( unlikely (!(opstr.length >= opstr.last_arg_offset + 3)))
194*2d1272b8SAndroid Build Coastguard Worker 	    return_trace (false);
195*2d1272b8SAndroid Build Coastguard Worker 	  supp_op.ptr = opstr.ptr + opstr.last_arg_offset;
196*2d1272b8SAndroid Build Coastguard Worker 	  supp_op.length = opstr.length - opstr.last_arg_offset;
197*2d1272b8SAndroid Build Coastguard Worker 	  return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
198*2d1272b8SAndroid Build Coastguard Worker 			UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
199*2d1272b8SAndroid Build Coastguard Worker 			copy_opstr (c, supp_op));
200*2d1272b8SAndroid Build Coastguard Worker 	}
201*2d1272b8SAndroid Build Coastguard Worker       fall_back:
202*2d1272b8SAndroid Build Coastguard Worker       default:
203*2d1272b8SAndroid Build Coastguard Worker 	return_trace (cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::serialize (c, opstr, mod.info));
204*2d1272b8SAndroid Build Coastguard Worker     }
205*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
206*2d1272b8SAndroid Build Coastguard Worker   }
207*2d1272b8SAndroid Build Coastguard Worker 
208*2d1272b8SAndroid Build Coastguard Worker };
209*2d1272b8SAndroid Build Coastguard Worker 
210*2d1272b8SAndroid Build Coastguard Worker struct cff1_font_dict_op_serializer_t : cff_font_dict_op_serializer_t
211*2d1272b8SAndroid Build Coastguard Worker {
serializecff1_font_dict_op_serializer_t212*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c,
213*2d1272b8SAndroid Build Coastguard Worker 		  const op_str_t &opstr,
214*2d1272b8SAndroid Build Coastguard Worker 		  const cff1_font_dict_values_mod_t &mod) const
215*2d1272b8SAndroid Build Coastguard Worker   {
216*2d1272b8SAndroid Build Coastguard Worker     TRACE_SERIALIZE (this);
217*2d1272b8SAndroid Build Coastguard Worker 
218*2d1272b8SAndroid Build Coastguard Worker     if (opstr.op == OpCode_FontName)
219*2d1272b8SAndroid Build Coastguard Worker       return_trace (FontDict::serialize_int2_op (c, opstr.op, mod.fontName));
220*2d1272b8SAndroid Build Coastguard Worker     else
221*2d1272b8SAndroid Build Coastguard Worker       return_trace (SUPER::serialize (c, opstr, mod.privateDictInfo));
222*2d1272b8SAndroid Build Coastguard Worker   }
223*2d1272b8SAndroid Build Coastguard Worker 
224*2d1272b8SAndroid Build Coastguard Worker   private:
225*2d1272b8SAndroid Build Coastguard Worker   typedef cff_font_dict_op_serializer_t SUPER;
226*2d1272b8SAndroid Build Coastguard Worker };
227*2d1272b8SAndroid Build Coastguard Worker 
228*2d1272b8SAndroid Build Coastguard Worker struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatten_param_t>
229*2d1272b8SAndroid Build Coastguard Worker {
flush_args_and_opcff1_cs_opset_flatten_t230*2d1272b8SAndroid Build Coastguard Worker   static void flush_args_and_op (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
231*2d1272b8SAndroid Build Coastguard Worker   {
232*2d1272b8SAndroid Build Coastguard Worker     if (env.arg_start > 0)
233*2d1272b8SAndroid Build Coastguard Worker       flush_width (env, param);
234*2d1272b8SAndroid Build Coastguard Worker 
235*2d1272b8SAndroid Build Coastguard Worker     switch (op)
236*2d1272b8SAndroid Build Coastguard Worker     {
237*2d1272b8SAndroid Build Coastguard Worker       case OpCode_hstem:
238*2d1272b8SAndroid Build Coastguard Worker       case OpCode_hstemhm:
239*2d1272b8SAndroid Build Coastguard Worker       case OpCode_vstem:
240*2d1272b8SAndroid Build Coastguard Worker       case OpCode_vstemhm:
241*2d1272b8SAndroid Build Coastguard Worker       case OpCode_hintmask:
242*2d1272b8SAndroid Build Coastguard Worker       case OpCode_cntrmask:
243*2d1272b8SAndroid Build Coastguard Worker       case OpCode_dotsection:
244*2d1272b8SAndroid Build Coastguard Worker 	if (param.drop_hints)
245*2d1272b8SAndroid Build Coastguard Worker 	{
246*2d1272b8SAndroid Build Coastguard Worker 	  env.clear_args ();
247*2d1272b8SAndroid Build Coastguard Worker 	  return;
248*2d1272b8SAndroid Build Coastguard Worker 	}
249*2d1272b8SAndroid Build Coastguard Worker 	HB_FALLTHROUGH;
250*2d1272b8SAndroid Build Coastguard Worker 
251*2d1272b8SAndroid Build Coastguard Worker       default:
252*2d1272b8SAndroid Build Coastguard Worker 	SUPER::flush_args_and_op (op, env, param);
253*2d1272b8SAndroid Build Coastguard Worker 	break;
254*2d1272b8SAndroid Build Coastguard Worker     }
255*2d1272b8SAndroid Build Coastguard Worker   }
flush_argscff1_cs_opset_flatten_t256*2d1272b8SAndroid Build Coastguard Worker   static void flush_args (cff1_cs_interp_env_t &env, flatten_param_t& param)
257*2d1272b8SAndroid Build Coastguard Worker   {
258*2d1272b8SAndroid Build Coastguard Worker     str_encoder_t  encoder (param.flatStr);
259*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = env.arg_start; i < env.argStack.get_count (); i++)
260*2d1272b8SAndroid Build Coastguard Worker       encoder.encode_num_cs (env.eval_arg (i));
261*2d1272b8SAndroid Build Coastguard Worker     SUPER::flush_args (env, param);
262*2d1272b8SAndroid Build Coastguard Worker   }
263*2d1272b8SAndroid Build Coastguard Worker 
flush_opcff1_cs_opset_flatten_t264*2d1272b8SAndroid Build Coastguard Worker   static void flush_op (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
265*2d1272b8SAndroid Build Coastguard Worker   {
266*2d1272b8SAndroid Build Coastguard Worker     str_encoder_t  encoder (param.flatStr);
267*2d1272b8SAndroid Build Coastguard Worker     encoder.encode_op (op);
268*2d1272b8SAndroid Build Coastguard Worker   }
269*2d1272b8SAndroid Build Coastguard Worker 
flush_widthcff1_cs_opset_flatten_t270*2d1272b8SAndroid Build Coastguard Worker   static void flush_width (cff1_cs_interp_env_t &env, flatten_param_t& param)
271*2d1272b8SAndroid Build Coastguard Worker   {
272*2d1272b8SAndroid Build Coastguard Worker     assert (env.has_width);
273*2d1272b8SAndroid Build Coastguard Worker     str_encoder_t  encoder (param.flatStr);
274*2d1272b8SAndroid Build Coastguard Worker     encoder.encode_num_cs (env.width);
275*2d1272b8SAndroid Build Coastguard Worker   }
276*2d1272b8SAndroid Build Coastguard Worker 
flush_hintmaskcff1_cs_opset_flatten_t277*2d1272b8SAndroid Build Coastguard Worker   static void flush_hintmask (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
278*2d1272b8SAndroid Build Coastguard Worker   {
279*2d1272b8SAndroid Build Coastguard Worker     SUPER::flush_hintmask (op, env, param);
280*2d1272b8SAndroid Build Coastguard Worker     if (!param.drop_hints)
281*2d1272b8SAndroid Build Coastguard Worker     {
282*2d1272b8SAndroid Build Coastguard Worker       str_encoder_t  encoder (param.flatStr);
283*2d1272b8SAndroid Build Coastguard Worker       for (unsigned int i = 0; i < env.hintmask_size; i++)
284*2d1272b8SAndroid Build Coastguard Worker 	encoder.encode_byte (env.str_ref[i]);
285*2d1272b8SAndroid Build Coastguard Worker     }
286*2d1272b8SAndroid Build Coastguard Worker   }
287*2d1272b8SAndroid Build Coastguard Worker 
288*2d1272b8SAndroid Build Coastguard Worker   private:
289*2d1272b8SAndroid Build Coastguard Worker   typedef cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatten_param_t> SUPER;
290*2d1272b8SAndroid Build Coastguard Worker };
291*2d1272b8SAndroid Build Coastguard Worker 
292*2d1272b8SAndroid Build Coastguard Worker struct range_list_t : hb_vector_t<code_pair_t>
293*2d1272b8SAndroid Build Coastguard Worker {
294*2d1272b8SAndroid Build Coastguard Worker   /* replace the first glyph ID in the "glyph" field each range with a nLeft value */
completerange_list_t295*2d1272b8SAndroid Build Coastguard Worker   bool complete (unsigned int last_glyph)
296*2d1272b8SAndroid Build Coastguard Worker   {
297*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t all_glyphs = 0;
298*2d1272b8SAndroid Build Coastguard Worker     unsigned count = this->length;
299*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = count; i; i--)
300*2d1272b8SAndroid Build Coastguard Worker     {
301*2d1272b8SAndroid Build Coastguard Worker       code_pair_t &pair = arrayZ[i - 1];
302*2d1272b8SAndroid Build Coastguard Worker       unsigned int nLeft = last_glyph - pair.glyph - 1;
303*2d1272b8SAndroid Build Coastguard Worker       all_glyphs |= nLeft;
304*2d1272b8SAndroid Build Coastguard Worker       last_glyph = pair.glyph;
305*2d1272b8SAndroid Build Coastguard Worker       pair.glyph = nLeft;
306*2d1272b8SAndroid Build Coastguard Worker     }
307*2d1272b8SAndroid Build Coastguard Worker     bool two_byte = all_glyphs >= 0x100;
308*2d1272b8SAndroid Build Coastguard Worker     return two_byte;
309*2d1272b8SAndroid Build Coastguard Worker   }
310*2d1272b8SAndroid Build Coastguard Worker };
311*2d1272b8SAndroid Build Coastguard Worker 
312*2d1272b8SAndroid Build Coastguard Worker struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t>
313*2d1272b8SAndroid Build Coastguard Worker {
process_opcff1_cs_opset_subr_subset_t314*2d1272b8SAndroid Build Coastguard Worker   static void process_op (op_code_t op, cff1_cs_interp_env_t &env, subr_subset_param_t& param)
315*2d1272b8SAndroid Build Coastguard Worker   {
316*2d1272b8SAndroid Build Coastguard Worker     switch (op) {
317*2d1272b8SAndroid Build Coastguard Worker 
318*2d1272b8SAndroid Build Coastguard Worker       case OpCode_return:
319*2d1272b8SAndroid Build Coastguard Worker 	param.current_parsed_str->add_op (op, env.str_ref);
320*2d1272b8SAndroid Build Coastguard Worker 	param.current_parsed_str->set_parsed ();
321*2d1272b8SAndroid Build Coastguard Worker 	env.return_from_subr ();
322*2d1272b8SAndroid Build Coastguard Worker 	param.set_current_str (env, false);
323*2d1272b8SAndroid Build Coastguard Worker 	break;
324*2d1272b8SAndroid Build Coastguard Worker 
325*2d1272b8SAndroid Build Coastguard Worker       case OpCode_endchar:
326*2d1272b8SAndroid Build Coastguard Worker 	param.current_parsed_str->add_op (op, env.str_ref);
327*2d1272b8SAndroid Build Coastguard Worker 	param.current_parsed_str->set_parsed ();
328*2d1272b8SAndroid Build Coastguard Worker 	SUPER::process_op (op, env, param);
329*2d1272b8SAndroid Build Coastguard Worker 	break;
330*2d1272b8SAndroid Build Coastguard Worker 
331*2d1272b8SAndroid Build Coastguard Worker       case OpCode_callsubr:
332*2d1272b8SAndroid Build Coastguard Worker 	process_call_subr (op, CSType_LocalSubr, env, param, env.localSubrs, param.local_closure);
333*2d1272b8SAndroid Build Coastguard Worker 	break;
334*2d1272b8SAndroid Build Coastguard Worker 
335*2d1272b8SAndroid Build Coastguard Worker       case OpCode_callgsubr:
336*2d1272b8SAndroid Build Coastguard Worker 	process_call_subr (op, CSType_GlobalSubr, env, param, env.globalSubrs, param.global_closure);
337*2d1272b8SAndroid Build Coastguard Worker 	break;
338*2d1272b8SAndroid Build Coastguard Worker 
339*2d1272b8SAndroid Build Coastguard Worker       default:
340*2d1272b8SAndroid Build Coastguard Worker 	SUPER::process_op (op, env, param);
341*2d1272b8SAndroid Build Coastguard Worker 	param.current_parsed_str->add_op (op, env.str_ref);
342*2d1272b8SAndroid Build Coastguard Worker 	break;
343*2d1272b8SAndroid Build Coastguard Worker     }
344*2d1272b8SAndroid Build Coastguard Worker   }
345*2d1272b8SAndroid Build Coastguard Worker 
346*2d1272b8SAndroid Build Coastguard Worker   protected:
process_call_subrcff1_cs_opset_subr_subset_t347*2d1272b8SAndroid Build Coastguard Worker   static void process_call_subr (op_code_t op, cs_type_t type,
348*2d1272b8SAndroid Build Coastguard Worker 				 cff1_cs_interp_env_t &env, subr_subset_param_t& param,
349*2d1272b8SAndroid Build Coastguard Worker 				 cff1_biased_subrs_t& subrs, hb_set_t *closure)
350*2d1272b8SAndroid Build Coastguard Worker   {
351*2d1272b8SAndroid Build Coastguard Worker     byte_str_ref_t    str_ref = env.str_ref;
352*2d1272b8SAndroid Build Coastguard Worker     env.call_subr (subrs, type);
353*2d1272b8SAndroid Build Coastguard Worker     param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
354*2d1272b8SAndroid Build Coastguard Worker     closure->add (env.context.subr_num);
355*2d1272b8SAndroid Build Coastguard Worker     param.set_current_str (env, true);
356*2d1272b8SAndroid Build Coastguard Worker   }
357*2d1272b8SAndroid Build Coastguard Worker 
358*2d1272b8SAndroid Build Coastguard Worker   private:
359*2d1272b8SAndroid Build Coastguard Worker   typedef cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
360*2d1272b8SAndroid Build Coastguard Worker };
361*2d1272b8SAndroid Build Coastguard Worker 
362*2d1272b8SAndroid Build Coastguard Worker struct cff1_private_dict_op_serializer_t : op_serializer_t
363*2d1272b8SAndroid Build Coastguard Worker {
cff1_private_dict_op_serializer_tcff1_private_dict_op_serializer_t364*2d1272b8SAndroid Build Coastguard Worker   cff1_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_)
365*2d1272b8SAndroid Build Coastguard Worker     : desubroutinize (desubroutinize_), drop_hints (drop_hints_) {}
366*2d1272b8SAndroid Build Coastguard Worker 
serializecff1_private_dict_op_serializer_t367*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c,
368*2d1272b8SAndroid Build Coastguard Worker 		  const op_str_t &opstr,
369*2d1272b8SAndroid Build Coastguard Worker 		  objidx_t subrs_link) const
370*2d1272b8SAndroid Build Coastguard Worker   {
371*2d1272b8SAndroid Build Coastguard Worker     TRACE_SERIALIZE (this);
372*2d1272b8SAndroid Build Coastguard Worker 
373*2d1272b8SAndroid Build Coastguard Worker     if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
374*2d1272b8SAndroid Build Coastguard Worker       return_trace (true);
375*2d1272b8SAndroid Build Coastguard Worker 
376*2d1272b8SAndroid Build Coastguard Worker     if (opstr.op == OpCode_Subrs)
377*2d1272b8SAndroid Build Coastguard Worker     {
378*2d1272b8SAndroid Build Coastguard Worker       if (desubroutinize || !subrs_link)
379*2d1272b8SAndroid Build Coastguard Worker 	return_trace (true);
380*2d1272b8SAndroid Build Coastguard Worker       else
381*2d1272b8SAndroid Build Coastguard Worker 	return_trace (FontDict::serialize_link2_op (c, opstr.op, subrs_link));
382*2d1272b8SAndroid Build Coastguard Worker     }
383*2d1272b8SAndroid Build Coastguard Worker 
384*2d1272b8SAndroid Build Coastguard Worker     return_trace (copy_opstr (c, opstr));
385*2d1272b8SAndroid Build Coastguard Worker   }
386*2d1272b8SAndroid Build Coastguard Worker 
387*2d1272b8SAndroid Build Coastguard Worker   protected:
388*2d1272b8SAndroid Build Coastguard Worker   const bool desubroutinize;
389*2d1272b8SAndroid Build Coastguard Worker   const bool drop_hints;
390*2d1272b8SAndroid Build Coastguard Worker };
391*2d1272b8SAndroid Build Coastguard Worker 
392*2d1272b8SAndroid Build Coastguard Worker struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t, OpCode_endchar>
393*2d1272b8SAndroid Build Coastguard Worker {
cff1_subr_subsetter_tcff1_subr_subsetter_t394*2d1272b8SAndroid Build Coastguard Worker   cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
395*2d1272b8SAndroid Build Coastguard Worker     : subr_subsetter_t (acc_, plan_) {}
396*2d1272b8SAndroid Build Coastguard Worker 
complete_parsed_strcff1_subr_subsetter_t397*2d1272b8SAndroid Build Coastguard Worker   static void complete_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
398*2d1272b8SAndroid Build Coastguard Worker   {
399*2d1272b8SAndroid Build Coastguard Worker     /* insert width at the beginning of the charstring as necessary */
400*2d1272b8SAndroid Build Coastguard Worker     if (env.has_width)
401*2d1272b8SAndroid Build Coastguard Worker       charstring.set_prefix (env.width);
402*2d1272b8SAndroid Build Coastguard Worker 
403*2d1272b8SAndroid Build Coastguard Worker     /* subroutines/charstring left on the call stack are legally left unmarked
404*2d1272b8SAndroid Build Coastguard Worker      * unmarked when a subroutine terminates with endchar. mark them.
405*2d1272b8SAndroid Build Coastguard Worker      */
406*2d1272b8SAndroid Build Coastguard Worker     param.current_parsed_str->set_parsed ();
407*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < env.callStack.get_count (); i++)
408*2d1272b8SAndroid Build Coastguard Worker     {
409*2d1272b8SAndroid Build Coastguard Worker       parsed_cs_str_t *parsed_str = param.get_parsed_str_for_context (env.callStack[i]);
410*2d1272b8SAndroid Build Coastguard Worker       if (likely (parsed_str))
411*2d1272b8SAndroid Build Coastguard Worker 	parsed_str->set_parsed ();
412*2d1272b8SAndroid Build Coastguard Worker       else
413*2d1272b8SAndroid Build Coastguard Worker 	env.set_error ();
414*2d1272b8SAndroid Build Coastguard Worker     }
415*2d1272b8SAndroid Build Coastguard Worker   }
416*2d1272b8SAndroid Build Coastguard Worker };
417*2d1272b8SAndroid Build Coastguard Worker 
418*2d1272b8SAndroid Build Coastguard Worker namespace OT {
419*2d1272b8SAndroid Build Coastguard Worker struct cff1_subset_plan
420*2d1272b8SAndroid Build Coastguard Worker {
cff1_subset_planOT::cff1_subset_plan421*2d1272b8SAndroid Build Coastguard Worker   cff1_subset_plan ()
422*2d1272b8SAndroid Build Coastguard Worker   {
423*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
424*2d1272b8SAndroid Build Coastguard Worker       topDictModSIDs[i] = CFF_UNDEF_SID;
425*2d1272b8SAndroid Build Coastguard Worker   }
426*2d1272b8SAndroid Build Coastguard Worker 
plan_subset_encodingOT::cff1_subset_plan427*2d1272b8SAndroid Build Coastguard Worker   void plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
428*2d1272b8SAndroid Build Coastguard Worker   {
429*2d1272b8SAndroid Build Coastguard Worker     const Encoding *encoding = acc.encoding;
430*2d1272b8SAndroid Build Coastguard Worker     unsigned int  size0, size1;
431*2d1272b8SAndroid Build Coastguard Worker     unsigned code, last_code = CFF_UNDEF_CODE - 1;
432*2d1272b8SAndroid Build Coastguard Worker     hb_vector_t<hb_codepoint_t> supp_codes;
433*2d1272b8SAndroid Build Coastguard Worker 
434*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!subset_enc_code_ranges.resize (0)))
435*2d1272b8SAndroid Build Coastguard Worker     {
436*2d1272b8SAndroid Build Coastguard Worker       plan->check_success (false);
437*2d1272b8SAndroid Build Coastguard Worker       return;
438*2d1272b8SAndroid Build Coastguard Worker     }
439*2d1272b8SAndroid Build Coastguard Worker 
440*2d1272b8SAndroid Build Coastguard Worker     supp_codes.init ();
441*2d1272b8SAndroid Build Coastguard Worker 
442*2d1272b8SAndroid Build Coastguard Worker     code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
443*2d1272b8SAndroid Build Coastguard Worker     subset_enc_num_codes = plan->num_output_glyphs () - 1;
444*2d1272b8SAndroid Build Coastguard Worker     unsigned int glyph;
445*2d1272b8SAndroid Build Coastguard Worker     auto it = hb_iter (plan->new_to_old_gid_list);
446*2d1272b8SAndroid Build Coastguard Worker     if (it->first == 0) it++;
447*2d1272b8SAndroid Build Coastguard Worker     auto _ = *it;
448*2d1272b8SAndroid Build Coastguard Worker     for (glyph = 1; glyph < num_glyphs; glyph++)
449*2d1272b8SAndroid Build Coastguard Worker     {
450*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t old_glyph;
451*2d1272b8SAndroid Build Coastguard Worker       if (glyph == _.first)
452*2d1272b8SAndroid Build Coastguard Worker       {
453*2d1272b8SAndroid Build Coastguard Worker 	old_glyph = _.second;
454*2d1272b8SAndroid Build Coastguard Worker 	_ = *++it;
455*2d1272b8SAndroid Build Coastguard Worker       }
456*2d1272b8SAndroid Build Coastguard Worker       else
457*2d1272b8SAndroid Build Coastguard Worker       {
458*2d1272b8SAndroid Build Coastguard Worker 	/* Retain the SID for the old missing glyph ID */
459*2d1272b8SAndroid Build Coastguard Worker 	old_glyph = glyph;
460*2d1272b8SAndroid Build Coastguard Worker       }
461*2d1272b8SAndroid Build Coastguard Worker       code = acc.glyph_to_code (old_glyph, &glyph_to_sid_cache);
462*2d1272b8SAndroid Build Coastguard Worker       if (code == CFF_UNDEF_CODE)
463*2d1272b8SAndroid Build Coastguard Worker       {
464*2d1272b8SAndroid Build Coastguard Worker 	subset_enc_num_codes = glyph - 1;
465*2d1272b8SAndroid Build Coastguard Worker 	break;
466*2d1272b8SAndroid Build Coastguard Worker       }
467*2d1272b8SAndroid Build Coastguard Worker 
468*2d1272b8SAndroid Build Coastguard Worker       if (code != last_code + 1)
469*2d1272b8SAndroid Build Coastguard Worker 	subset_enc_code_ranges.push (code_pair_t {code, glyph});
470*2d1272b8SAndroid Build Coastguard Worker       last_code = code;
471*2d1272b8SAndroid Build Coastguard Worker 
472*2d1272b8SAndroid Build Coastguard Worker       if (encoding != &Null (Encoding))
473*2d1272b8SAndroid Build Coastguard Worker       {
474*2d1272b8SAndroid Build Coastguard Worker 	hb_codepoint_t  sid = acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache);
475*2d1272b8SAndroid Build Coastguard Worker 	encoding->get_supplement_codes (sid, supp_codes);
476*2d1272b8SAndroid Build Coastguard Worker 	for (unsigned int i = 0; i < supp_codes.length; i++)
477*2d1272b8SAndroid Build Coastguard Worker 	  subset_enc_supp_codes.push (code_pair_t {supp_codes[i], sid});
478*2d1272b8SAndroid Build Coastguard Worker       }
479*2d1272b8SAndroid Build Coastguard Worker     }
480*2d1272b8SAndroid Build Coastguard Worker     supp_codes.fini ();
481*2d1272b8SAndroid Build Coastguard Worker 
482*2d1272b8SAndroid Build Coastguard Worker     subset_enc_code_ranges.complete (glyph);
483*2d1272b8SAndroid Build Coastguard Worker 
484*2d1272b8SAndroid Build Coastguard Worker     assert (subset_enc_num_codes <= 0xFF);
485*2d1272b8SAndroid Build Coastguard Worker     size0 = Encoding0::min_size + HBUINT8::static_size * subset_enc_num_codes;
486*2d1272b8SAndroid Build Coastguard Worker     size1 = Encoding1::min_size + Encoding1_Range::static_size * subset_enc_code_ranges.length;
487*2d1272b8SAndroid Build Coastguard Worker 
488*2d1272b8SAndroid Build Coastguard Worker     if (size0 < size1)
489*2d1272b8SAndroid Build Coastguard Worker       subset_enc_format = 0;
490*2d1272b8SAndroid Build Coastguard Worker     else
491*2d1272b8SAndroid Build Coastguard Worker       subset_enc_format = 1;
492*2d1272b8SAndroid Build Coastguard Worker   }
493*2d1272b8SAndroid Build Coastguard Worker 
plan_subset_charsetOT::cff1_subset_plan494*2d1272b8SAndroid Build Coastguard Worker   bool plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
495*2d1272b8SAndroid Build Coastguard Worker   {
496*2d1272b8SAndroid Build Coastguard Worker     unsigned int  size0, size_ranges;
497*2d1272b8SAndroid Build Coastguard Worker     unsigned last_sid = CFF_UNDEF_CODE - 1;
498*2d1272b8SAndroid Build Coastguard Worker 
499*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!subset_charset_ranges.resize (0)))
500*2d1272b8SAndroid Build Coastguard Worker     {
501*2d1272b8SAndroid Build Coastguard Worker       plan->check_success (false);
502*2d1272b8SAndroid Build Coastguard Worker       return false;
503*2d1272b8SAndroid Build Coastguard Worker     }
504*2d1272b8SAndroid Build Coastguard Worker 
505*2d1272b8SAndroid Build Coastguard Worker     code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
506*2d1272b8SAndroid Build Coastguard Worker 
507*2d1272b8SAndroid Build Coastguard Worker     unsigned num_glyphs = plan->num_output_glyphs ();
508*2d1272b8SAndroid Build Coastguard Worker 
509*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!subset_charset_ranges.alloc (hb_min (num_glyphs,
510*2d1272b8SAndroid Build Coastguard Worker 							acc.num_charset_entries))))
511*2d1272b8SAndroid Build Coastguard Worker     {
512*2d1272b8SAndroid Build Coastguard Worker       plan->check_success (false);
513*2d1272b8SAndroid Build Coastguard Worker       return false;
514*2d1272b8SAndroid Build Coastguard Worker     }
515*2d1272b8SAndroid Build Coastguard Worker 
516*2d1272b8SAndroid Build Coastguard Worker     glyph_to_sid_map_t *glyph_to_sid_map = acc.cff_accelerator ?
517*2d1272b8SAndroid Build Coastguard Worker 					   acc.cff_accelerator->glyph_to_sid_map.get_acquire () :
518*2d1272b8SAndroid Build Coastguard Worker 					   nullptr;
519*2d1272b8SAndroid Build Coastguard Worker     bool created_map = false;
520*2d1272b8SAndroid Build Coastguard Worker     if (!glyph_to_sid_map && acc.cff_accelerator)
521*2d1272b8SAndroid Build Coastguard Worker     {
522*2d1272b8SAndroid Build Coastguard Worker       created_map = true;
523*2d1272b8SAndroid Build Coastguard Worker       glyph_to_sid_map = acc.create_glyph_to_sid_map ();
524*2d1272b8SAndroid Build Coastguard Worker     }
525*2d1272b8SAndroid Build Coastguard Worker 
526*2d1272b8SAndroid Build Coastguard Worker     auto it = hb_iter (plan->new_to_old_gid_list);
527*2d1272b8SAndroid Build Coastguard Worker     if (it->first == 0) it++;
528*2d1272b8SAndroid Build Coastguard Worker     auto _ = *it;
529*2d1272b8SAndroid Build Coastguard Worker     bool not_is_cid = !acc.is_CID ();
530*2d1272b8SAndroid Build Coastguard Worker     bool skip = !not_is_cid && glyph_to_sid_map;
531*2d1272b8SAndroid Build Coastguard Worker     if (not_is_cid)
532*2d1272b8SAndroid Build Coastguard Worker       sidmap.alloc (num_glyphs);
533*2d1272b8SAndroid Build Coastguard Worker     for (hb_codepoint_t glyph = 1; glyph < num_glyphs; glyph++)
534*2d1272b8SAndroid Build Coastguard Worker     {
535*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t old_glyph;
536*2d1272b8SAndroid Build Coastguard Worker       if (glyph == _.first)
537*2d1272b8SAndroid Build Coastguard Worker       {
538*2d1272b8SAndroid Build Coastguard Worker 	old_glyph = _.second;
539*2d1272b8SAndroid Build Coastguard Worker 	_ = *++it;
540*2d1272b8SAndroid Build Coastguard Worker       }
541*2d1272b8SAndroid Build Coastguard Worker       else
542*2d1272b8SAndroid Build Coastguard Worker       {
543*2d1272b8SAndroid Build Coastguard Worker 	/* Retain the SID for the old missing glyph ID */
544*2d1272b8SAndroid Build Coastguard Worker 	old_glyph = glyph;
545*2d1272b8SAndroid Build Coastguard Worker       }
546*2d1272b8SAndroid Build Coastguard Worker       unsigned sid = glyph_to_sid_map ?
547*2d1272b8SAndroid Build Coastguard Worker 		     glyph_to_sid_map->arrayZ[old_glyph].code :
548*2d1272b8SAndroid Build Coastguard Worker 		     acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache);
549*2d1272b8SAndroid Build Coastguard Worker 
550*2d1272b8SAndroid Build Coastguard Worker       if (not_is_cid)
551*2d1272b8SAndroid Build Coastguard Worker 	sid = sidmap.add (sid);
552*2d1272b8SAndroid Build Coastguard Worker 
553*2d1272b8SAndroid Build Coastguard Worker       if (sid != last_sid + 1)
554*2d1272b8SAndroid Build Coastguard Worker 	subset_charset_ranges.push (code_pair_t {sid, glyph});
555*2d1272b8SAndroid Build Coastguard Worker 
556*2d1272b8SAndroid Build Coastguard Worker       if (glyph == old_glyph && skip)
557*2d1272b8SAndroid Build Coastguard Worker       {
558*2d1272b8SAndroid Build Coastguard Worker 	glyph = hb_min (_.first - 1, glyph_to_sid_map->arrayZ[old_glyph].glyph);
559*2d1272b8SAndroid Build Coastguard Worker 	sid += glyph - old_glyph;
560*2d1272b8SAndroid Build Coastguard Worker       }
561*2d1272b8SAndroid Build Coastguard Worker       last_sid = sid;
562*2d1272b8SAndroid Build Coastguard Worker     }
563*2d1272b8SAndroid Build Coastguard Worker 
564*2d1272b8SAndroid Build Coastguard Worker     if (created_map)
565*2d1272b8SAndroid Build Coastguard Worker     {
566*2d1272b8SAndroid Build Coastguard Worker       if ((!plan->accelerator && acc.cff_accelerator) ||
567*2d1272b8SAndroid Build Coastguard Worker 	  !acc.cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map))
568*2d1272b8SAndroid Build Coastguard Worker       {
569*2d1272b8SAndroid Build Coastguard Worker 	glyph_to_sid_map->~glyph_to_sid_map_t ();
570*2d1272b8SAndroid Build Coastguard Worker 	hb_free (glyph_to_sid_map);
571*2d1272b8SAndroid Build Coastguard Worker       }
572*2d1272b8SAndroid Build Coastguard Worker     }
573*2d1272b8SAndroid Build Coastguard Worker 
574*2d1272b8SAndroid Build Coastguard Worker     bool two_byte = subset_charset_ranges.complete (num_glyphs);
575*2d1272b8SAndroid Build Coastguard Worker 
576*2d1272b8SAndroid Build Coastguard Worker     size0 = Charset0::get_size (plan->num_output_glyphs ());
577*2d1272b8SAndroid Build Coastguard Worker     if (!two_byte)
578*2d1272b8SAndroid Build Coastguard Worker       size_ranges = Charset1::get_size_for_ranges (subset_charset_ranges.length);
579*2d1272b8SAndroid Build Coastguard Worker     else
580*2d1272b8SAndroid Build Coastguard Worker       size_ranges = Charset2::get_size_for_ranges (subset_charset_ranges.length);
581*2d1272b8SAndroid Build Coastguard Worker 
582*2d1272b8SAndroid Build Coastguard Worker     if (size0 < size_ranges)
583*2d1272b8SAndroid Build Coastguard Worker       subset_charset_format = 0;
584*2d1272b8SAndroid Build Coastguard Worker     else if (!two_byte)
585*2d1272b8SAndroid Build Coastguard Worker       subset_charset_format = 1;
586*2d1272b8SAndroid Build Coastguard Worker     else
587*2d1272b8SAndroid Build Coastguard Worker       subset_charset_format = 2;
588*2d1272b8SAndroid Build Coastguard Worker 
589*2d1272b8SAndroid Build Coastguard Worker     return true;
590*2d1272b8SAndroid Build Coastguard Worker   }
591*2d1272b8SAndroid Build Coastguard Worker 
collect_sids_in_dictsOT::cff1_subset_plan592*2d1272b8SAndroid Build Coastguard Worker   bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
593*2d1272b8SAndroid Build Coastguard Worker   {
594*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
595*2d1272b8SAndroid Build Coastguard Worker     {
596*2d1272b8SAndroid Build Coastguard Worker       unsigned int sid = acc.topDict.nameSIDs[i];
597*2d1272b8SAndroid Build Coastguard Worker       if (sid != CFF_UNDEF_SID)
598*2d1272b8SAndroid Build Coastguard Worker       {
599*2d1272b8SAndroid Build Coastguard Worker 	topDictModSIDs[i] = sidmap.add (sid);
600*2d1272b8SAndroid Build Coastguard Worker       }
601*2d1272b8SAndroid Build Coastguard Worker     }
602*2d1272b8SAndroid Build Coastguard Worker 
603*2d1272b8SAndroid Build Coastguard Worker     if (acc.fdArray != &Null (CFF1FDArray))
604*2d1272b8SAndroid Build Coastguard Worker       for (unsigned int i = 0; i < orig_fdcount; i++)
605*2d1272b8SAndroid Build Coastguard Worker 	if (fdmap.has (i))
606*2d1272b8SAndroid Build Coastguard Worker 	  (void)sidmap.add (acc.fontDicts[i].fontName);
607*2d1272b8SAndroid Build Coastguard Worker 
608*2d1272b8SAndroid Build Coastguard Worker     return true;
609*2d1272b8SAndroid Build Coastguard Worker   }
610*2d1272b8SAndroid Build Coastguard Worker 
createOT::cff1_subset_plan611*2d1272b8SAndroid Build Coastguard Worker   bool create (const OT::cff1::accelerator_subset_t &acc,
612*2d1272b8SAndroid Build Coastguard Worker 	       hb_subset_plan_t *plan)
613*2d1272b8SAndroid Build Coastguard Worker   {
614*2d1272b8SAndroid Build Coastguard Worker     /* make sure notdef is first */
615*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t old_glyph;
616*2d1272b8SAndroid Build Coastguard Worker     if (!plan->old_gid_for_new_gid (0, &old_glyph) || (old_glyph != 0)) return false;
617*2d1272b8SAndroid Build Coastguard Worker 
618*2d1272b8SAndroid Build Coastguard Worker     num_glyphs = plan->num_output_glyphs ();
619*2d1272b8SAndroid Build Coastguard Worker     orig_fdcount = acc.fdCount;
620*2d1272b8SAndroid Build Coastguard Worker     drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
621*2d1272b8SAndroid Build Coastguard Worker     desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE;
622*2d1272b8SAndroid Build Coastguard Worker 
623*2d1272b8SAndroid Build Coastguard Worker  #ifdef HB_EXPERIMENTAL_API
624*2d1272b8SAndroid Build Coastguard Worker     min_charstrings_off_size = (plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS) ? 4 : 0;
625*2d1272b8SAndroid Build Coastguard Worker  #else
626*2d1272b8SAndroid Build Coastguard Worker     min_charstrings_off_size = 0;
627*2d1272b8SAndroid Build Coastguard Worker  #endif
628*2d1272b8SAndroid Build Coastguard Worker 
629*2d1272b8SAndroid Build Coastguard Worker     subset_charset = !acc.is_predef_charset ();
630*2d1272b8SAndroid Build Coastguard Worker     if (!subset_charset)
631*2d1272b8SAndroid Build Coastguard Worker       /* check whether the subset renumbers any glyph IDs */
632*2d1272b8SAndroid Build Coastguard Worker       for (const auto &_ : plan->new_to_old_gid_list)
633*2d1272b8SAndroid Build Coastguard Worker       {
634*2d1272b8SAndroid Build Coastguard Worker 	if (_.first != _.second)
635*2d1272b8SAndroid Build Coastguard Worker 	{
636*2d1272b8SAndroid Build Coastguard Worker 	  subset_charset = true;
637*2d1272b8SAndroid Build Coastguard Worker 	  break;
638*2d1272b8SAndroid Build Coastguard Worker 	}
639*2d1272b8SAndroid Build Coastguard Worker       }
640*2d1272b8SAndroid Build Coastguard Worker 
641*2d1272b8SAndroid Build Coastguard Worker     subset_encoding = !acc.is_CID() && !acc.is_predef_encoding ();
642*2d1272b8SAndroid Build Coastguard Worker 
643*2d1272b8SAndroid Build Coastguard Worker     /* top dict INDEX */
644*2d1272b8SAndroid Build Coastguard Worker     {
645*2d1272b8SAndroid Build Coastguard Worker       /* Add encoding/charset to a (copy of) top dict as necessary */
646*2d1272b8SAndroid Build Coastguard Worker       topdict_mod.init (&acc.topDict);
647*2d1272b8SAndroid Build Coastguard Worker       bool need_to_add_enc = (subset_encoding && !acc.topDict.has_op (OpCode_Encoding));
648*2d1272b8SAndroid Build Coastguard Worker       bool need_to_add_set = (subset_charset && !acc.topDict.has_op (OpCode_charset));
649*2d1272b8SAndroid Build Coastguard Worker       if (need_to_add_enc || need_to_add_set)
650*2d1272b8SAndroid Build Coastguard Worker       {
651*2d1272b8SAndroid Build Coastguard Worker 	if (need_to_add_enc)
652*2d1272b8SAndroid Build Coastguard Worker 	  topdict_mod.add_op (OpCode_Encoding);
653*2d1272b8SAndroid Build Coastguard Worker 	if (need_to_add_set)
654*2d1272b8SAndroid Build Coastguard Worker 	  topdict_mod.add_op (OpCode_charset);
655*2d1272b8SAndroid Build Coastguard Worker       }
656*2d1272b8SAndroid Build Coastguard Worker     }
657*2d1272b8SAndroid Build Coastguard Worker 
658*2d1272b8SAndroid Build Coastguard Worker     /* Determine re-mapping of font index as fdmap among other info */
659*2d1272b8SAndroid Build Coastguard Worker     if (acc.fdSelect != &Null (CFF1FDSelect))
660*2d1272b8SAndroid Build Coastguard Worker     {
661*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (!hb_plan_subset_cff_fdselect (plan,
662*2d1272b8SAndroid Build Coastguard Worker 				  orig_fdcount,
663*2d1272b8SAndroid Build Coastguard Worker 				  *acc.fdSelect,
664*2d1272b8SAndroid Build Coastguard Worker 				  subset_fdcount,
665*2d1272b8SAndroid Build Coastguard Worker 				  info.fd_select.size,
666*2d1272b8SAndroid Build Coastguard Worker 				  subset_fdselect_format,
667*2d1272b8SAndroid Build Coastguard Worker 				  subset_fdselect_ranges,
668*2d1272b8SAndroid Build Coastguard Worker 				  fdmap)))
669*2d1272b8SAndroid Build Coastguard Worker 	return false;
670*2d1272b8SAndroid Build Coastguard Worker     }
671*2d1272b8SAndroid Build Coastguard Worker     else
672*2d1272b8SAndroid Build Coastguard Worker       fdmap.identity (1);
673*2d1272b8SAndroid Build Coastguard Worker 
674*2d1272b8SAndroid Build Coastguard Worker     /* remove unused SIDs & reassign SIDs */
675*2d1272b8SAndroid Build Coastguard Worker     {
676*2d1272b8SAndroid Build Coastguard Worker       /* SIDs for name strings in dicts are added before glyph names so they fit in 16-bit int range */
677*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!collect_sids_in_dicts (acc)))
678*2d1272b8SAndroid Build Coastguard Worker 	return false;
679*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (sidmap.get_population () > 0x8000))	/* assumption: a dict won't reference that many strings */
680*2d1272b8SAndroid Build Coastguard Worker 	return false;
681*2d1272b8SAndroid Build Coastguard Worker 
682*2d1272b8SAndroid Build Coastguard Worker       if (subset_charset && !plan_subset_charset (acc, plan))
683*2d1272b8SAndroid Build Coastguard Worker         return false;
684*2d1272b8SAndroid Build Coastguard Worker 
685*2d1272b8SAndroid Build Coastguard Worker       topdict_mod.reassignSIDs (sidmap);
686*2d1272b8SAndroid Build Coastguard Worker     }
687*2d1272b8SAndroid Build Coastguard Worker 
688*2d1272b8SAndroid Build Coastguard Worker     if (desubroutinize)
689*2d1272b8SAndroid Build Coastguard Worker     {
690*2d1272b8SAndroid Build Coastguard Worker       /* Flatten global & local subrs */
691*2d1272b8SAndroid Build Coastguard Worker       subr_flattener_t<const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_flatten_t, OpCode_endchar>
692*2d1272b8SAndroid Build Coastguard Worker 		    flattener(acc, plan);
693*2d1272b8SAndroid Build Coastguard Worker       if (!flattener.flatten (subset_charstrings))
694*2d1272b8SAndroid Build Coastguard Worker 	return false;
695*2d1272b8SAndroid Build Coastguard Worker     }
696*2d1272b8SAndroid Build Coastguard Worker     else
697*2d1272b8SAndroid Build Coastguard Worker     {
698*2d1272b8SAndroid Build Coastguard Worker       cff1_subr_subsetter_t       subr_subsetter (acc, plan);
699*2d1272b8SAndroid Build Coastguard Worker 
700*2d1272b8SAndroid Build Coastguard Worker       /* Subset subrs: collect used subroutines, leaving all unused ones behind */
701*2d1272b8SAndroid Build Coastguard Worker       if (!subr_subsetter.subset ())
702*2d1272b8SAndroid Build Coastguard Worker 	return false;
703*2d1272b8SAndroid Build Coastguard Worker 
704*2d1272b8SAndroid Build Coastguard Worker       /* encode charstrings, global subrs, local subrs with new subroutine numbers */
705*2d1272b8SAndroid Build Coastguard Worker       if (!subr_subsetter.encode_charstrings (subset_charstrings))
706*2d1272b8SAndroid Build Coastguard Worker 	return false;
707*2d1272b8SAndroid Build Coastguard Worker 
708*2d1272b8SAndroid Build Coastguard Worker       if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
709*2d1272b8SAndroid Build Coastguard Worker 	return false;
710*2d1272b8SAndroid Build Coastguard Worker 
711*2d1272b8SAndroid Build Coastguard Worker       /* local subrs */
712*2d1272b8SAndroid Build Coastguard Worker       if (!subset_localsubrs.resize (orig_fdcount))
713*2d1272b8SAndroid Build Coastguard Worker 	return false;
714*2d1272b8SAndroid Build Coastguard Worker       for (unsigned int fd = 0; fd < orig_fdcount; fd++)
715*2d1272b8SAndroid Build Coastguard Worker       {
716*2d1272b8SAndroid Build Coastguard Worker 	subset_localsubrs[fd].init ();
717*2d1272b8SAndroid Build Coastguard Worker 	if (fdmap.has (fd))
718*2d1272b8SAndroid Build Coastguard Worker 	{
719*2d1272b8SAndroid Build Coastguard Worker 	  if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
720*2d1272b8SAndroid Build Coastguard Worker 	    return false;
721*2d1272b8SAndroid Build Coastguard Worker 	}
722*2d1272b8SAndroid Build Coastguard Worker       }
723*2d1272b8SAndroid Build Coastguard Worker     }
724*2d1272b8SAndroid Build Coastguard Worker 
725*2d1272b8SAndroid Build Coastguard Worker     /* Encoding */
726*2d1272b8SAndroid Build Coastguard Worker     if (subset_encoding)
727*2d1272b8SAndroid Build Coastguard Worker       plan_subset_encoding (acc, plan);
728*2d1272b8SAndroid Build Coastguard Worker 
729*2d1272b8SAndroid Build Coastguard Worker     /* private dicts & local subrs */
730*2d1272b8SAndroid Build Coastguard Worker     if (!acc.is_CID ())
731*2d1272b8SAndroid Build Coastguard Worker       fontdicts_mod.push (cff1_font_dict_values_mod_t ());
732*2d1272b8SAndroid Build Coastguard Worker     else
733*2d1272b8SAndroid Build Coastguard Worker     {
734*2d1272b8SAndroid Build Coastguard Worker       + hb_iter (acc.fontDicts)
735*2d1272b8SAndroid Build Coastguard Worker       | hb_filter ([&] (const cff1_font_dict_values_t &_)
736*2d1272b8SAndroid Build Coastguard Worker 	{ return fdmap.has (&_ - &acc.fontDicts[0]); } )
737*2d1272b8SAndroid Build Coastguard Worker       | hb_map ([&] (const cff1_font_dict_values_t &_)
738*2d1272b8SAndroid Build Coastguard Worker 	{
739*2d1272b8SAndroid Build Coastguard Worker 	  cff1_font_dict_values_mod_t mod;
740*2d1272b8SAndroid Build Coastguard Worker 	  mod.init (&_, sidmap[_.fontName]);
741*2d1272b8SAndroid Build Coastguard Worker 	  return mod;
742*2d1272b8SAndroid Build Coastguard Worker 	})
743*2d1272b8SAndroid Build Coastguard Worker       | hb_sink (fontdicts_mod)
744*2d1272b8SAndroid Build Coastguard Worker       ;
745*2d1272b8SAndroid Build Coastguard Worker     }
746*2d1272b8SAndroid Build Coastguard Worker 
747*2d1272b8SAndroid Build Coastguard Worker     return !plan->in_error () &&
748*2d1272b8SAndroid Build Coastguard Worker 	   (subset_charstrings.length == plan->num_output_glyphs ()) &&
749*2d1272b8SAndroid Build Coastguard Worker 	   (fontdicts_mod.length == subset_fdcount);
750*2d1272b8SAndroid Build Coastguard Worker   }
751*2d1272b8SAndroid Build Coastguard Worker 
752*2d1272b8SAndroid Build Coastguard Worker   cff1_top_dict_values_mod_t	topdict_mod;
753*2d1272b8SAndroid Build Coastguard Worker   cff1_sub_table_info_t		info;
754*2d1272b8SAndroid Build Coastguard Worker 
755*2d1272b8SAndroid Build Coastguard Worker   unsigned int    num_glyphs;
756*2d1272b8SAndroid Build Coastguard Worker   unsigned int    orig_fdcount = 0;
757*2d1272b8SAndroid Build Coastguard Worker   unsigned int    subset_fdcount = 1;
758*2d1272b8SAndroid Build Coastguard Worker   unsigned int    subset_fdselect_format = 0;
759*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<code_pair_t>   subset_fdselect_ranges;
760*2d1272b8SAndroid Build Coastguard Worker 
761*2d1272b8SAndroid Build Coastguard Worker   /* font dict index remap table from fullset FDArray to subset FDArray.
762*2d1272b8SAndroid Build Coastguard Worker    * set to CFF_UNDEF_CODE if excluded from subset */
763*2d1272b8SAndroid Build Coastguard Worker   hb_inc_bimap_t   fdmap;
764*2d1272b8SAndroid Build Coastguard Worker 
765*2d1272b8SAndroid Build Coastguard Worker   str_buff_vec_t		subset_charstrings;
766*2d1272b8SAndroid Build Coastguard Worker   str_buff_vec_t		subset_globalsubrs;
767*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<str_buff_vec_t>	subset_localsubrs;
768*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<cff1_font_dict_values_mod_t>  fontdicts_mod;
769*2d1272b8SAndroid Build Coastguard Worker 
770*2d1272b8SAndroid Build Coastguard Worker   bool		drop_hints = false;
771*2d1272b8SAndroid Build Coastguard Worker 
772*2d1272b8SAndroid Build Coastguard Worker   bool		gid_renum;
773*2d1272b8SAndroid Build Coastguard Worker   bool		subset_encoding;
774*2d1272b8SAndroid Build Coastguard Worker   uint8_t	subset_enc_format;
775*2d1272b8SAndroid Build Coastguard Worker   unsigned int	subset_enc_num_codes;
776*2d1272b8SAndroid Build Coastguard Worker   range_list_t	subset_enc_code_ranges;
777*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<code_pair_t>  subset_enc_supp_codes;
778*2d1272b8SAndroid Build Coastguard Worker 
779*2d1272b8SAndroid Build Coastguard Worker   uint8_t	subset_charset_format;
780*2d1272b8SAndroid Build Coastguard Worker   range_list_t	subset_charset_ranges;
781*2d1272b8SAndroid Build Coastguard Worker   bool		subset_charset;
782*2d1272b8SAndroid Build Coastguard Worker 
783*2d1272b8SAndroid Build Coastguard Worker   remap_sid_t	sidmap;
784*2d1272b8SAndroid Build Coastguard Worker   unsigned int	topDictModSIDs[name_dict_values_t::ValCount];
785*2d1272b8SAndroid Build Coastguard Worker 
786*2d1272b8SAndroid Build Coastguard Worker   bool		desubroutinize = false;
787*2d1272b8SAndroid Build Coastguard Worker 
788*2d1272b8SAndroid Build Coastguard Worker   unsigned	min_charstrings_off_size = 0;
789*2d1272b8SAndroid Build Coastguard Worker };
790*2d1272b8SAndroid Build Coastguard Worker } // namespace OT
791*2d1272b8SAndroid Build Coastguard Worker 
_serialize_cff1_charstrings(hb_serialize_context_t * c,struct OT::cff1_subset_plan & plan,const OT::cff1::accelerator_subset_t & acc)792*2d1272b8SAndroid Build Coastguard Worker static bool _serialize_cff1_charstrings (hb_serialize_context_t *c,
793*2d1272b8SAndroid Build Coastguard Worker                                          struct OT::cff1_subset_plan &plan,
794*2d1272b8SAndroid Build Coastguard Worker                                          const OT::cff1::accelerator_subset_t  &acc)
795*2d1272b8SAndroid Build Coastguard Worker {
796*2d1272b8SAndroid Build Coastguard Worker   c->push<CFF1CharStrings> ();
797*2d1272b8SAndroid Build Coastguard Worker 
798*2d1272b8SAndroid Build Coastguard Worker   unsigned data_size = 0;
799*2d1272b8SAndroid Build Coastguard Worker   unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size, plan.min_charstrings_off_size);
800*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!c->start_zerocopy (total_size)))
801*2d1272b8SAndroid Build Coastguard Worker     return false;
802*2d1272b8SAndroid Build Coastguard Worker 
803*2d1272b8SAndroid Build Coastguard Worker   auto *cs = c->start_embed<CFF1CharStrings> ();
804*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!cs->serialize (c, plan.subset_charstrings, &data_size, plan.min_charstrings_off_size))) {
805*2d1272b8SAndroid Build Coastguard Worker     c->pop_discard ();
806*2d1272b8SAndroid Build Coastguard Worker     return false;
807*2d1272b8SAndroid Build Coastguard Worker   }
808*2d1272b8SAndroid Build Coastguard Worker 
809*2d1272b8SAndroid Build Coastguard Worker   plan.info.char_strings_link = c->pop_pack (false);
810*2d1272b8SAndroid Build Coastguard Worker   return true;
811*2d1272b8SAndroid Build Coastguard Worker }
812*2d1272b8SAndroid Build Coastguard Worker 
813*2d1272b8SAndroid Build Coastguard Worker bool
serialize(hb_serialize_context_t * c,struct OT::cff1_subset_plan & plan) const814*2d1272b8SAndroid Build Coastguard Worker OT::cff1::accelerator_subset_t::serialize (hb_serialize_context_t *c,
815*2d1272b8SAndroid Build Coastguard Worker 					   struct OT::cff1_subset_plan &plan) const
816*2d1272b8SAndroid Build Coastguard Worker {
817*2d1272b8SAndroid Build Coastguard Worker   /* push charstrings onto the object stack first which will ensure it packs as the last
818*2d1272b8SAndroid Build Coastguard Worker      object in the table. Keeping the chastrings last satisfies the requirements for patching
819*2d1272b8SAndroid Build Coastguard Worker      via IFTB. If this ordering needs to be changed in the future, charstrings should be left
820*2d1272b8SAndroid Build Coastguard Worker      at the end whenever HB_SUBSET_FLAGS_ITFB_REQUIREMENTS is enabled. */
821*2d1272b8SAndroid Build Coastguard Worker   if (!_serialize_cff1_charstrings(c, plan, *this))
822*2d1272b8SAndroid Build Coastguard Worker     return false;
823*2d1272b8SAndroid Build Coastguard Worker 
824*2d1272b8SAndroid Build Coastguard Worker   /* private dicts & local subrs */
825*2d1272b8SAndroid Build Coastguard Worker   for (int i = (int) privateDicts.length; --i >= 0 ;)
826*2d1272b8SAndroid Build Coastguard Worker   {
827*2d1272b8SAndroid Build Coastguard Worker     if (plan.fdmap.has (i))
828*2d1272b8SAndroid Build Coastguard Worker     {
829*2d1272b8SAndroid Build Coastguard Worker       objidx_t	subrs_link = 0;
830*2d1272b8SAndroid Build Coastguard Worker       if (plan.subset_localsubrs[i].length > 0)
831*2d1272b8SAndroid Build Coastguard Worker       {
832*2d1272b8SAndroid Build Coastguard Worker 	auto *dest = c->push <CFF1Subrs> ();
833*2d1272b8SAndroid Build Coastguard Worker 	if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
834*2d1272b8SAndroid Build Coastguard Worker 	  subrs_link = c->pop_pack ();
835*2d1272b8SAndroid Build Coastguard Worker 	else
836*2d1272b8SAndroid Build Coastguard Worker 	{
837*2d1272b8SAndroid Build Coastguard Worker 	  c->pop_discard ();
838*2d1272b8SAndroid Build Coastguard Worker 	  return false;
839*2d1272b8SAndroid Build Coastguard Worker 	}
840*2d1272b8SAndroid Build Coastguard Worker       }
841*2d1272b8SAndroid Build Coastguard Worker 
842*2d1272b8SAndroid Build Coastguard Worker       auto *pd = c->push<PrivateDict> ();
843*2d1272b8SAndroid Build Coastguard Worker       cff1_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
844*2d1272b8SAndroid Build Coastguard Worker       /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
845*2d1272b8SAndroid Build Coastguard Worker       if (likely (pd->serialize (c, privateDicts[i], privSzr, subrs_link)))
846*2d1272b8SAndroid Build Coastguard Worker       {
847*2d1272b8SAndroid Build Coastguard Worker 	unsigned fd = plan.fdmap[i];
848*2d1272b8SAndroid Build Coastguard Worker 	plan.fontdicts_mod[fd].privateDictInfo.size = c->length ();
849*2d1272b8SAndroid Build Coastguard Worker 	plan.fontdicts_mod[fd].privateDictInfo.link = c->pop_pack ();
850*2d1272b8SAndroid Build Coastguard Worker       }
851*2d1272b8SAndroid Build Coastguard Worker       else
852*2d1272b8SAndroid Build Coastguard Worker       {
853*2d1272b8SAndroid Build Coastguard Worker 	c->pop_discard ();
854*2d1272b8SAndroid Build Coastguard Worker 	return false;
855*2d1272b8SAndroid Build Coastguard Worker       }
856*2d1272b8SAndroid Build Coastguard Worker     }
857*2d1272b8SAndroid Build Coastguard Worker   }
858*2d1272b8SAndroid Build Coastguard Worker 
859*2d1272b8SAndroid Build Coastguard Worker   if (!is_CID ())
860*2d1272b8SAndroid Build Coastguard Worker     plan.info.privateDictInfo = plan.fontdicts_mod[0].privateDictInfo;
861*2d1272b8SAndroid Build Coastguard Worker 
862*2d1272b8SAndroid Build Coastguard Worker   /* FDArray (FD Index) */
863*2d1272b8SAndroid Build Coastguard Worker   if (fdArray != &Null (CFF1FDArray))
864*2d1272b8SAndroid Build Coastguard Worker   {
865*2d1272b8SAndroid Build Coastguard Worker     auto *fda = c->push<CFF1FDArray> ();
866*2d1272b8SAndroid Build Coastguard Worker     cff1_font_dict_op_serializer_t  fontSzr;
867*2d1272b8SAndroid Build Coastguard Worker     auto it = + hb_zip (+ hb_iter (plan.fontdicts_mod), + hb_iter (plan.fontdicts_mod));
868*2d1272b8SAndroid Build Coastguard Worker     if (likely (fda->serialize (c, it, fontSzr)))
869*2d1272b8SAndroid Build Coastguard Worker       plan.info.fd_array_link = c->pop_pack (false);
870*2d1272b8SAndroid Build Coastguard Worker     else
871*2d1272b8SAndroid Build Coastguard Worker     {
872*2d1272b8SAndroid Build Coastguard Worker       c->pop_discard ();
873*2d1272b8SAndroid Build Coastguard Worker       return false;
874*2d1272b8SAndroid Build Coastguard Worker     }
875*2d1272b8SAndroid Build Coastguard Worker   }
876*2d1272b8SAndroid Build Coastguard Worker 
877*2d1272b8SAndroid Build Coastguard Worker   /* FDSelect */
878*2d1272b8SAndroid Build Coastguard Worker   if (fdSelect != &Null (CFF1FDSelect))
879*2d1272b8SAndroid Build Coastguard Worker   {
880*2d1272b8SAndroid Build Coastguard Worker     c->push ();
881*2d1272b8SAndroid Build Coastguard Worker     if (likely (hb_serialize_cff_fdselect (c, plan.num_glyphs, *fdSelect, fdCount,
882*2d1272b8SAndroid Build Coastguard Worker 					   plan.subset_fdselect_format, plan.info.fd_select.size,
883*2d1272b8SAndroid Build Coastguard Worker 					   plan.subset_fdselect_ranges)))
884*2d1272b8SAndroid Build Coastguard Worker       plan.info.fd_select.link = c->pop_pack ();
885*2d1272b8SAndroid Build Coastguard Worker     else
886*2d1272b8SAndroid Build Coastguard Worker     {
887*2d1272b8SAndroid Build Coastguard Worker       c->pop_discard ();
888*2d1272b8SAndroid Build Coastguard Worker       return false;
889*2d1272b8SAndroid Build Coastguard Worker     }
890*2d1272b8SAndroid Build Coastguard Worker   }
891*2d1272b8SAndroid Build Coastguard Worker 
892*2d1272b8SAndroid Build Coastguard Worker   /* Charset */
893*2d1272b8SAndroid Build Coastguard Worker   if (plan.subset_charset)
894*2d1272b8SAndroid Build Coastguard Worker   {
895*2d1272b8SAndroid Build Coastguard Worker     auto *dest = c->push<Charset> ();
896*2d1272b8SAndroid Build Coastguard Worker     if (likely (dest->serialize (c,
897*2d1272b8SAndroid Build Coastguard Worker 				 plan.subset_charset_format,
898*2d1272b8SAndroid Build Coastguard Worker 				 plan.num_glyphs,
899*2d1272b8SAndroid Build Coastguard Worker 				 plan.subset_charset_ranges)))
900*2d1272b8SAndroid Build Coastguard Worker       plan.info.charset_link = c->pop_pack ();
901*2d1272b8SAndroid Build Coastguard Worker     else
902*2d1272b8SAndroid Build Coastguard Worker     {
903*2d1272b8SAndroid Build Coastguard Worker       c->pop_discard ();
904*2d1272b8SAndroid Build Coastguard Worker       return false;
905*2d1272b8SAndroid Build Coastguard Worker     }
906*2d1272b8SAndroid Build Coastguard Worker   }
907*2d1272b8SAndroid Build Coastguard Worker 
908*2d1272b8SAndroid Build Coastguard Worker   /* Encoding */
909*2d1272b8SAndroid Build Coastguard Worker   if (plan.subset_encoding)
910*2d1272b8SAndroid Build Coastguard Worker   {
911*2d1272b8SAndroid Build Coastguard Worker     auto *dest = c->push<Encoding> ();
912*2d1272b8SAndroid Build Coastguard Worker     if (likely (dest->serialize (c,
913*2d1272b8SAndroid Build Coastguard Worker 				 plan.subset_enc_format,
914*2d1272b8SAndroid Build Coastguard Worker 				 plan.subset_enc_num_codes,
915*2d1272b8SAndroid Build Coastguard Worker 				 plan.subset_enc_code_ranges,
916*2d1272b8SAndroid Build Coastguard Worker 				 plan.subset_enc_supp_codes)))
917*2d1272b8SAndroid Build Coastguard Worker       plan.info.encoding_link = c->pop_pack ();
918*2d1272b8SAndroid Build Coastguard Worker     else
919*2d1272b8SAndroid Build Coastguard Worker     {
920*2d1272b8SAndroid Build Coastguard Worker       c->pop_discard ();
921*2d1272b8SAndroid Build Coastguard Worker       return false;
922*2d1272b8SAndroid Build Coastguard Worker     }
923*2d1272b8SAndroid Build Coastguard Worker   }
924*2d1272b8SAndroid Build Coastguard Worker 
925*2d1272b8SAndroid Build Coastguard Worker   /* global subrs */
926*2d1272b8SAndroid Build Coastguard Worker   {
927*2d1272b8SAndroid Build Coastguard Worker     auto *dest = c->push <CFF1Subrs> ();
928*2d1272b8SAndroid Build Coastguard Worker     if (likely (dest->serialize (c, plan.subset_globalsubrs)))
929*2d1272b8SAndroid Build Coastguard Worker       c->pop_pack (false);
930*2d1272b8SAndroid Build Coastguard Worker     else
931*2d1272b8SAndroid Build Coastguard Worker     {
932*2d1272b8SAndroid Build Coastguard Worker       c->pop_discard ();
933*2d1272b8SAndroid Build Coastguard Worker       return false;
934*2d1272b8SAndroid Build Coastguard Worker     }
935*2d1272b8SAndroid Build Coastguard Worker   }
936*2d1272b8SAndroid Build Coastguard Worker 
937*2d1272b8SAndroid Build Coastguard Worker   /* String INDEX */
938*2d1272b8SAndroid Build Coastguard Worker   {
939*2d1272b8SAndroid Build Coastguard Worker     auto *dest = c->push<CFF1StringIndex> ();
940*2d1272b8SAndroid Build Coastguard Worker     if (likely (!plan.sidmap.in_error () &&
941*2d1272b8SAndroid Build Coastguard Worker 		dest->serialize (c, *stringIndex, plan.sidmap.vector)))
942*2d1272b8SAndroid Build Coastguard Worker       c->pop_pack ();
943*2d1272b8SAndroid Build Coastguard Worker     else
944*2d1272b8SAndroid Build Coastguard Worker     {
945*2d1272b8SAndroid Build Coastguard Worker       c->pop_discard ();
946*2d1272b8SAndroid Build Coastguard Worker       return false;
947*2d1272b8SAndroid Build Coastguard Worker     }
948*2d1272b8SAndroid Build Coastguard Worker   }
949*2d1272b8SAndroid Build Coastguard Worker 
950*2d1272b8SAndroid Build Coastguard Worker   OT::cff1 *cff = c->allocate_min<OT::cff1> ();
951*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!cff))
952*2d1272b8SAndroid Build Coastguard Worker     return false;
953*2d1272b8SAndroid Build Coastguard Worker 
954*2d1272b8SAndroid Build Coastguard Worker   /* header */
955*2d1272b8SAndroid Build Coastguard Worker   cff->version.major = 0x01;
956*2d1272b8SAndroid Build Coastguard Worker   cff->version.minor = 0x00;
957*2d1272b8SAndroid Build Coastguard Worker   cff->nameIndex = cff->min_size;
958*2d1272b8SAndroid Build Coastguard Worker   cff->offSize = 4; /* unused? */
959*2d1272b8SAndroid Build Coastguard Worker 
960*2d1272b8SAndroid Build Coastguard Worker   /* name INDEX */
961*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!c->embed (*nameIndex))) return false;
962*2d1272b8SAndroid Build Coastguard Worker 
963*2d1272b8SAndroid Build Coastguard Worker   /* top dict INDEX */
964*2d1272b8SAndroid Build Coastguard Worker   {
965*2d1272b8SAndroid Build Coastguard Worker     /* serialize singleton TopDict */
966*2d1272b8SAndroid Build Coastguard Worker     auto *top = c->push<TopDict> ();
967*2d1272b8SAndroid Build Coastguard Worker     cff1_top_dict_op_serializer_t topSzr;
968*2d1272b8SAndroid Build Coastguard Worker     unsigned top_size = 0;
969*2d1272b8SAndroid Build Coastguard Worker     top_dict_modifiers_t  modifier (plan.info, plan.topDictModSIDs);
970*2d1272b8SAndroid Build Coastguard Worker     if (likely (top->serialize (c, plan.topdict_mod, topSzr, modifier)))
971*2d1272b8SAndroid Build Coastguard Worker     {
972*2d1272b8SAndroid Build Coastguard Worker       top_size = c->length ();
973*2d1272b8SAndroid Build Coastguard Worker       c->pop_pack (false);
974*2d1272b8SAndroid Build Coastguard Worker     }
975*2d1272b8SAndroid Build Coastguard Worker     else
976*2d1272b8SAndroid Build Coastguard Worker     {
977*2d1272b8SAndroid Build Coastguard Worker       c->pop_discard ();
978*2d1272b8SAndroid Build Coastguard Worker       return false;
979*2d1272b8SAndroid Build Coastguard Worker     }
980*2d1272b8SAndroid Build Coastguard Worker     /* serialize INDEX header for above */
981*2d1272b8SAndroid Build Coastguard Worker     auto *dest = c->start_embed<CFF1Index> ();
982*2d1272b8SAndroid Build Coastguard Worker     return dest->serialize_header (c, hb_iter (&top_size, 1), top_size);
983*2d1272b8SAndroid Build Coastguard Worker   }
984*2d1272b8SAndroid Build Coastguard Worker }
985*2d1272b8SAndroid Build Coastguard Worker 
986*2d1272b8SAndroid Build Coastguard Worker bool
subset(hb_subset_context_t * c) const987*2d1272b8SAndroid Build Coastguard Worker OT::cff1::accelerator_subset_t::subset (hb_subset_context_t *c) const
988*2d1272b8SAndroid Build Coastguard Worker {
989*2d1272b8SAndroid Build Coastguard Worker   cff1_subset_plan cff_plan;
990*2d1272b8SAndroid Build Coastguard Worker 
991*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!cff_plan.create (*this, c->plan)))
992*2d1272b8SAndroid Build Coastguard Worker   {
993*2d1272b8SAndroid Build Coastguard Worker     DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan.");
994*2d1272b8SAndroid Build Coastguard Worker     return false;
995*2d1272b8SAndroid Build Coastguard Worker   }
996*2d1272b8SAndroid Build Coastguard Worker 
997*2d1272b8SAndroid Build Coastguard Worker   return serialize (c->serializer, cff_plan);
998*2d1272b8SAndroid Build Coastguard Worker }
999*2d1272b8SAndroid Build Coastguard Worker 
1000*2d1272b8SAndroid Build Coastguard Worker 
1001*2d1272b8SAndroid Build Coastguard Worker #endif
1002