xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-subset-cff-common.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_SUBSET_CFF_COMMON_HH
28*2d1272b8SAndroid Build Coastguard Worker #define HB_SUBSET_CFF_COMMON_HH
29*2d1272b8SAndroid Build Coastguard Worker 
30*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
31*2d1272b8SAndroid Build Coastguard Worker 
32*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-plan.hh"
33*2d1272b8SAndroid Build Coastguard Worker #include "hb-cff-interp-cs-common.hh"
34*2d1272b8SAndroid Build Coastguard Worker 
35*2d1272b8SAndroid Build Coastguard Worker namespace CFF {
36*2d1272b8SAndroid Build Coastguard Worker 
37*2d1272b8SAndroid Build Coastguard Worker /* Used for writing a temporary charstring */
38*2d1272b8SAndroid Build Coastguard Worker struct str_encoder_t
39*2d1272b8SAndroid Build Coastguard Worker {
str_encoder_tCFF::str_encoder_t40*2d1272b8SAndroid Build Coastguard Worker   str_encoder_t (str_buff_t &buff_)
41*2d1272b8SAndroid Build Coastguard Worker     : buff (buff_) {}
42*2d1272b8SAndroid Build Coastguard Worker 
resetCFF::str_encoder_t43*2d1272b8SAndroid Build Coastguard Worker   void reset () { buff.reset (); }
44*2d1272b8SAndroid Build Coastguard Worker 
encode_byteCFF::str_encoder_t45*2d1272b8SAndroid Build Coastguard Worker   void encode_byte (unsigned char b)
46*2d1272b8SAndroid Build Coastguard Worker   {
47*2d1272b8SAndroid Build Coastguard Worker     if (likely ((signed) buff.length < buff.allocated))
48*2d1272b8SAndroid Build Coastguard Worker       buff.arrayZ[buff.length++] = b;
49*2d1272b8SAndroid Build Coastguard Worker     else
50*2d1272b8SAndroid Build Coastguard Worker       buff.push (b);
51*2d1272b8SAndroid Build Coastguard Worker   }
52*2d1272b8SAndroid Build Coastguard Worker 
encode_intCFF::str_encoder_t53*2d1272b8SAndroid Build Coastguard Worker   void encode_int (int v)
54*2d1272b8SAndroid Build Coastguard Worker   {
55*2d1272b8SAndroid Build Coastguard Worker     if ((-1131 <= v) && (v <= 1131))
56*2d1272b8SAndroid Build Coastguard Worker     {
57*2d1272b8SAndroid Build Coastguard Worker       if ((-107 <= v) && (v <= 107))
58*2d1272b8SAndroid Build Coastguard Worker 	encode_byte (v + 139);
59*2d1272b8SAndroid Build Coastguard Worker       else if (v > 0)
60*2d1272b8SAndroid Build Coastguard Worker       {
61*2d1272b8SAndroid Build Coastguard Worker 	v -= 108;
62*2d1272b8SAndroid Build Coastguard Worker 	encode_byte ((v >> 8) + OpCode_TwoBytePosInt0);
63*2d1272b8SAndroid Build Coastguard Worker 	encode_byte (v & 0xFF);
64*2d1272b8SAndroid Build Coastguard Worker       }
65*2d1272b8SAndroid Build Coastguard Worker       else
66*2d1272b8SAndroid Build Coastguard Worker       {
67*2d1272b8SAndroid Build Coastguard Worker 	v = -v - 108;
68*2d1272b8SAndroid Build Coastguard Worker 	encode_byte ((v >> 8) + OpCode_TwoByteNegInt0);
69*2d1272b8SAndroid Build Coastguard Worker 	encode_byte (v & 0xFF);
70*2d1272b8SAndroid Build Coastguard Worker       }
71*2d1272b8SAndroid Build Coastguard Worker     }
72*2d1272b8SAndroid Build Coastguard Worker     else
73*2d1272b8SAndroid Build Coastguard Worker     {
74*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (v < -32768))
75*2d1272b8SAndroid Build Coastguard Worker 	v = -32768;
76*2d1272b8SAndroid Build Coastguard Worker       else if (unlikely (v > 32767))
77*2d1272b8SAndroid Build Coastguard Worker 	v = 32767;
78*2d1272b8SAndroid Build Coastguard Worker       encode_byte (OpCode_shortint);
79*2d1272b8SAndroid Build Coastguard Worker       encode_byte ((v >> 8) & 0xFF);
80*2d1272b8SAndroid Build Coastguard Worker       encode_byte (v & 0xFF);
81*2d1272b8SAndroid Build Coastguard Worker     }
82*2d1272b8SAndroid Build Coastguard Worker   }
83*2d1272b8SAndroid Build Coastguard Worker 
84*2d1272b8SAndroid Build Coastguard Worker   // Encode number for CharString
encode_num_csCFF::str_encoder_t85*2d1272b8SAndroid Build Coastguard Worker   void encode_num_cs (const number_t& n)
86*2d1272b8SAndroid Build Coastguard Worker   {
87*2d1272b8SAndroid Build Coastguard Worker     if (n.in_int_range ())
88*2d1272b8SAndroid Build Coastguard Worker     {
89*2d1272b8SAndroid Build Coastguard Worker       encode_int (n.to_int ());
90*2d1272b8SAndroid Build Coastguard Worker     }
91*2d1272b8SAndroid Build Coastguard Worker     else
92*2d1272b8SAndroid Build Coastguard Worker     {
93*2d1272b8SAndroid Build Coastguard Worker       int32_t v = n.to_fixed ();
94*2d1272b8SAndroid Build Coastguard Worker       encode_byte (OpCode_fixedcs);
95*2d1272b8SAndroid Build Coastguard Worker       encode_byte ((v >> 24) & 0xFF);
96*2d1272b8SAndroid Build Coastguard Worker       encode_byte ((v >> 16) & 0xFF);
97*2d1272b8SAndroid Build Coastguard Worker       encode_byte ((v >> 8) & 0xFF);
98*2d1272b8SAndroid Build Coastguard Worker       encode_byte (v & 0xFF);
99*2d1272b8SAndroid Build Coastguard Worker     }
100*2d1272b8SAndroid Build Coastguard Worker   }
101*2d1272b8SAndroid Build Coastguard Worker 
102*2d1272b8SAndroid Build Coastguard Worker   // Encode number for TopDict / Private
encode_num_tpCFF::str_encoder_t103*2d1272b8SAndroid Build Coastguard Worker   void encode_num_tp (const number_t& n)
104*2d1272b8SAndroid Build Coastguard Worker   {
105*2d1272b8SAndroid Build Coastguard Worker     if (n.in_int_range ())
106*2d1272b8SAndroid Build Coastguard Worker     {
107*2d1272b8SAndroid Build Coastguard Worker       // TODO longint
108*2d1272b8SAndroid Build Coastguard Worker       encode_int (n.to_int ());
109*2d1272b8SAndroid Build Coastguard Worker     }
110*2d1272b8SAndroid Build Coastguard Worker     else
111*2d1272b8SAndroid Build Coastguard Worker     {
112*2d1272b8SAndroid Build Coastguard Worker       // Sigh. BCD
113*2d1272b8SAndroid Build Coastguard Worker       // https://learn.microsoft.com/en-us/typography/opentype/spec/cff2#table-5-nibble-definitions
114*2d1272b8SAndroid Build Coastguard Worker       double v = n.to_real ();
115*2d1272b8SAndroid Build Coastguard Worker       encode_byte (OpCode_BCD);
116*2d1272b8SAndroid Build Coastguard Worker 
117*2d1272b8SAndroid Build Coastguard Worker       // Based on:
118*2d1272b8SAndroid Build Coastguard Worker       // https://github.com/fonttools/fonttools/blob/0738c41dfbcbc213ab9263f486ef0cccc6eb5ce5/Lib/fontTools/misc/psCharStrings.py#L267-L316
119*2d1272b8SAndroid Build Coastguard Worker 
120*2d1272b8SAndroid Build Coastguard Worker       char buf[16];
121*2d1272b8SAndroid Build Coastguard Worker       /* FontTools has the following comment:
122*2d1272b8SAndroid Build Coastguard Worker        *
123*2d1272b8SAndroid Build Coastguard Worker        * # Note: 14 decimal digits seems to be the limitation for CFF real numbers
124*2d1272b8SAndroid Build Coastguard Worker        * # in macOS. However, we use 8 here to match the implementation of AFDKO.
125*2d1272b8SAndroid Build Coastguard Worker        *
126*2d1272b8SAndroid Build Coastguard Worker        * We use 8 here to match FontTools X-).
127*2d1272b8SAndroid Build Coastguard Worker        */
128*2d1272b8SAndroid Build Coastguard Worker 
129*2d1272b8SAndroid Build Coastguard Worker       hb_locale_t clocale HB_UNUSED;
130*2d1272b8SAndroid Build Coastguard Worker       hb_locale_t oldlocale HB_UNUSED;
131*2d1272b8SAndroid Build Coastguard Worker       oldlocale = hb_uselocale (clocale = newlocale (LC_ALL_MASK, "C", NULL));
132*2d1272b8SAndroid Build Coastguard Worker       snprintf (buf, sizeof (buf), "%.8G", v);
133*2d1272b8SAndroid Build Coastguard Worker       (void) hb_uselocale (((void) freelocale (clocale), oldlocale));
134*2d1272b8SAndroid Build Coastguard Worker 
135*2d1272b8SAndroid Build Coastguard Worker       char *s = buf;
136*2d1272b8SAndroid Build Coastguard Worker       size_t len;
137*2d1272b8SAndroid Build Coastguard Worker       char *comma = strchr (s, ',');
138*2d1272b8SAndroid Build Coastguard Worker       if (comma) // Comma for some European locales in case no uselocale available.
139*2d1272b8SAndroid Build Coastguard Worker 	*comma = '.';
140*2d1272b8SAndroid Build Coastguard Worker       if (s[0] == '0' && s[1] == '.')
141*2d1272b8SAndroid Build Coastguard Worker 	s++;
142*2d1272b8SAndroid Build Coastguard Worker       else if (s[0] == '-' && s[1] == '0' && s[2] == '.')
143*2d1272b8SAndroid Build Coastguard Worker       {
144*2d1272b8SAndroid Build Coastguard Worker 	s[1] = '-';
145*2d1272b8SAndroid Build Coastguard Worker 	s++;
146*2d1272b8SAndroid Build Coastguard Worker       }
147*2d1272b8SAndroid Build Coastguard Worker       else if ((len = strlen (s)) > 3 && !strcmp (s + len - 3, "000"))
148*2d1272b8SAndroid Build Coastguard Worker       {
149*2d1272b8SAndroid Build Coastguard Worker 	unsigned exponent = len - 3;
150*2d1272b8SAndroid Build Coastguard Worker 	char *s2 = s + exponent - 1;
151*2d1272b8SAndroid Build Coastguard Worker 	while (*s2 == '0' && exponent > 1)
152*2d1272b8SAndroid Build Coastguard Worker 	{
153*2d1272b8SAndroid Build Coastguard Worker 	  s2--;
154*2d1272b8SAndroid Build Coastguard Worker 	  exponent++;
155*2d1272b8SAndroid Build Coastguard Worker 	}
156*2d1272b8SAndroid Build Coastguard Worker 	snprintf (s2 + 1, sizeof (buf) - (s2 + 1 - buf), "E%u", exponent);
157*2d1272b8SAndroid Build Coastguard Worker       }
158*2d1272b8SAndroid Build Coastguard Worker       else
159*2d1272b8SAndroid Build Coastguard Worker       {
160*2d1272b8SAndroid Build Coastguard Worker 	char *dot = strchr (s, '.');
161*2d1272b8SAndroid Build Coastguard Worker 	char *e = strchr (s, 'E');
162*2d1272b8SAndroid Build Coastguard Worker 	if (dot && e)
163*2d1272b8SAndroid Build Coastguard Worker 	{
164*2d1272b8SAndroid Build Coastguard Worker 	  memmove (dot, dot + 1, e - (dot + 1));
165*2d1272b8SAndroid Build Coastguard Worker 	  int exponent = atoi (e + 1);
166*2d1272b8SAndroid Build Coastguard Worker 	  int new_exponent = exponent - (e - (dot + 1));
167*2d1272b8SAndroid Build Coastguard Worker 	  if (new_exponent == 1)
168*2d1272b8SAndroid Build Coastguard Worker 	  {
169*2d1272b8SAndroid Build Coastguard Worker 	    e[-1] = '0';
170*2d1272b8SAndroid Build Coastguard Worker 	    e[0] = '\0';
171*2d1272b8SAndroid Build Coastguard Worker 	  }
172*2d1272b8SAndroid Build Coastguard Worker 	  else
173*2d1272b8SAndroid Build Coastguard Worker 	    snprintf (e - 1, sizeof (buf) - (e - 1 - buf), "E%d", new_exponent);
174*2d1272b8SAndroid Build Coastguard Worker 	}
175*2d1272b8SAndroid Build Coastguard Worker       }
176*2d1272b8SAndroid Build Coastguard Worker       if ((s[0] == '.' && s[1] == '0') || (s[0] == '-' && s[1] == '.' && s[2] == '0'))
177*2d1272b8SAndroid Build Coastguard Worker       {
178*2d1272b8SAndroid Build Coastguard Worker 	int sign = s[0] == '-';
179*2d1272b8SAndroid Build Coastguard Worker 	char *s2 = s + sign + 1;
180*2d1272b8SAndroid Build Coastguard Worker 	while (*s2 == '0')
181*2d1272b8SAndroid Build Coastguard Worker 	  s2++;
182*2d1272b8SAndroid Build Coastguard Worker 	len = strlen (s2);
183*2d1272b8SAndroid Build Coastguard Worker 	memmove (s + sign, s2, len);
184*2d1272b8SAndroid Build Coastguard Worker 	snprintf (s + sign + len, sizeof (buf) - (s + sign + len - buf), "E-%u", (unsigned) (strlen (s + sign) - 1));
185*2d1272b8SAndroid Build Coastguard Worker       }
186*2d1272b8SAndroid Build Coastguard Worker       hb_vector_t<char> nibbles;
187*2d1272b8SAndroid Build Coastguard Worker       while (*s)
188*2d1272b8SAndroid Build Coastguard Worker       {
189*2d1272b8SAndroid Build Coastguard Worker 	char c = s[0];
190*2d1272b8SAndroid Build Coastguard Worker 	s++;
191*2d1272b8SAndroid Build Coastguard Worker 
192*2d1272b8SAndroid Build Coastguard Worker 	switch (c)
193*2d1272b8SAndroid Build Coastguard Worker 	{
194*2d1272b8SAndroid Build Coastguard Worker 	  case 'E':
195*2d1272b8SAndroid Build Coastguard Worker 	  {
196*2d1272b8SAndroid Build Coastguard Worker 	    char c2 = *s;
197*2d1272b8SAndroid Build Coastguard Worker 	    if (c2 == '-')
198*2d1272b8SAndroid Build Coastguard Worker 	    {
199*2d1272b8SAndroid Build Coastguard Worker 	      s++;
200*2d1272b8SAndroid Build Coastguard Worker 	      nibbles.push (0x0C); // E-
201*2d1272b8SAndroid Build Coastguard Worker 	    } else {
202*2d1272b8SAndroid Build Coastguard Worker 	      if (c2 == '+')
203*2d1272b8SAndroid Build Coastguard Worker 		s++;
204*2d1272b8SAndroid Build Coastguard Worker 	      nibbles.push (0x0B); // E
205*2d1272b8SAndroid Build Coastguard Worker 	    }
206*2d1272b8SAndroid Build Coastguard Worker 	    if (*s == '0')
207*2d1272b8SAndroid Build Coastguard Worker 	      s++;
208*2d1272b8SAndroid Build Coastguard Worker 	    continue;
209*2d1272b8SAndroid Build Coastguard Worker 	  }
210*2d1272b8SAndroid Build Coastguard Worker 
211*2d1272b8SAndroid Build Coastguard Worker 	  case '.':
212*2d1272b8SAndroid Build Coastguard Worker 	    nibbles.push (0x0A); // .
213*2d1272b8SAndroid Build Coastguard Worker 	    continue;
214*2d1272b8SAndroid Build Coastguard Worker 
215*2d1272b8SAndroid Build Coastguard Worker 	  case '-':
216*2d1272b8SAndroid Build Coastguard Worker 	    nibbles.push (0x0E); // -
217*2d1272b8SAndroid Build Coastguard Worker 	    continue;
218*2d1272b8SAndroid Build Coastguard Worker 	}
219*2d1272b8SAndroid Build Coastguard Worker 
220*2d1272b8SAndroid Build Coastguard Worker 	nibbles.push (c - '0');
221*2d1272b8SAndroid Build Coastguard Worker       }
222*2d1272b8SAndroid Build Coastguard Worker       nibbles.push (0x0F);
223*2d1272b8SAndroid Build Coastguard Worker       if (nibbles.length % 2)
224*2d1272b8SAndroid Build Coastguard Worker 	nibbles.push (0x0F);
225*2d1272b8SAndroid Build Coastguard Worker 
226*2d1272b8SAndroid Build Coastguard Worker       unsigned count = nibbles.length;
227*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < count; i += 2)
228*2d1272b8SAndroid Build Coastguard Worker         encode_byte ((nibbles[i] << 4) | nibbles[i+1]);
229*2d1272b8SAndroid Build Coastguard Worker     }
230*2d1272b8SAndroid Build Coastguard Worker   }
231*2d1272b8SAndroid Build Coastguard Worker 
encode_opCFF::str_encoder_t232*2d1272b8SAndroid Build Coastguard Worker   void encode_op (op_code_t op)
233*2d1272b8SAndroid Build Coastguard Worker   {
234*2d1272b8SAndroid Build Coastguard Worker     if (Is_OpCode_ESC (op))
235*2d1272b8SAndroid Build Coastguard Worker     {
236*2d1272b8SAndroid Build Coastguard Worker       encode_byte (OpCode_escape);
237*2d1272b8SAndroid Build Coastguard Worker       encode_byte (Unmake_OpCode_ESC (op));
238*2d1272b8SAndroid Build Coastguard Worker     }
239*2d1272b8SAndroid Build Coastguard Worker     else
240*2d1272b8SAndroid Build Coastguard Worker       encode_byte (op);
241*2d1272b8SAndroid Build Coastguard Worker   }
242*2d1272b8SAndroid Build Coastguard Worker 
copy_strCFF::str_encoder_t243*2d1272b8SAndroid Build Coastguard Worker   void copy_str (const unsigned char *str, unsigned length)
244*2d1272b8SAndroid Build Coastguard Worker   {
245*2d1272b8SAndroid Build Coastguard Worker     assert ((signed) (buff.length + length) <= buff.allocated);
246*2d1272b8SAndroid Build Coastguard Worker     hb_memcpy (buff.arrayZ + buff.length, str, length);
247*2d1272b8SAndroid Build Coastguard Worker     buff.length += length;
248*2d1272b8SAndroid Build Coastguard Worker   }
249*2d1272b8SAndroid Build Coastguard Worker 
in_errorCFF::str_encoder_t250*2d1272b8SAndroid Build Coastguard Worker   bool in_error () const { return buff.in_error (); }
251*2d1272b8SAndroid Build Coastguard Worker 
252*2d1272b8SAndroid Build Coastguard Worker   protected:
253*2d1272b8SAndroid Build Coastguard Worker 
254*2d1272b8SAndroid Build Coastguard Worker   str_buff_t &buff;
255*2d1272b8SAndroid Build Coastguard Worker };
256*2d1272b8SAndroid Build Coastguard Worker 
257*2d1272b8SAndroid Build Coastguard Worker struct cff_sub_table_info_t {
cff_sub_table_info_tCFF::cff_sub_table_info_t258*2d1272b8SAndroid Build Coastguard Worker   cff_sub_table_info_t ()
259*2d1272b8SAndroid Build Coastguard Worker     : fd_array_link (0),
260*2d1272b8SAndroid Build Coastguard Worker       char_strings_link (0)
261*2d1272b8SAndroid Build Coastguard Worker   {
262*2d1272b8SAndroid Build Coastguard Worker     fd_select.init ();
263*2d1272b8SAndroid Build Coastguard Worker   }
264*2d1272b8SAndroid Build Coastguard Worker 
265*2d1272b8SAndroid Build Coastguard Worker   table_info_t     fd_select;
266*2d1272b8SAndroid Build Coastguard Worker   objidx_t     	   fd_array_link;
267*2d1272b8SAndroid Build Coastguard Worker   objidx_t     	   char_strings_link;
268*2d1272b8SAndroid Build Coastguard Worker };
269*2d1272b8SAndroid Build Coastguard Worker 
270*2d1272b8SAndroid Build Coastguard Worker template <typename OPSTR=op_str_t>
271*2d1272b8SAndroid Build Coastguard Worker struct cff_top_dict_op_serializer_t : op_serializer_t
272*2d1272b8SAndroid Build Coastguard Worker {
serializeCFF::cff_top_dict_op_serializer_t273*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c,
274*2d1272b8SAndroid Build Coastguard Worker 		  const OPSTR &opstr,
275*2d1272b8SAndroid Build Coastguard Worker 		  const cff_sub_table_info_t &info) const
276*2d1272b8SAndroid Build Coastguard Worker   {
277*2d1272b8SAndroid Build Coastguard Worker     TRACE_SERIALIZE (this);
278*2d1272b8SAndroid Build Coastguard Worker 
279*2d1272b8SAndroid Build Coastguard Worker     switch (opstr.op)
280*2d1272b8SAndroid Build Coastguard Worker     {
281*2d1272b8SAndroid Build Coastguard Worker       case OpCode_CharStrings:
282*2d1272b8SAndroid Build Coastguard Worker 	return_trace (FontDict::serialize_link4_op(c, opstr.op, info.char_strings_link, whence_t::Absolute));
283*2d1272b8SAndroid Build Coastguard Worker 
284*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FDArray:
285*2d1272b8SAndroid Build Coastguard Worker 	return_trace (FontDict::serialize_link4_op(c, opstr.op, info.fd_array_link, whence_t::Absolute));
286*2d1272b8SAndroid Build Coastguard Worker 
287*2d1272b8SAndroid Build Coastguard Worker       case OpCode_FDSelect:
288*2d1272b8SAndroid Build Coastguard Worker 	return_trace (FontDict::serialize_link4_op(c, opstr.op, info.fd_select.link, whence_t::Absolute));
289*2d1272b8SAndroid Build Coastguard Worker 
290*2d1272b8SAndroid Build Coastguard Worker       default:
291*2d1272b8SAndroid Build Coastguard Worker 	return_trace (copy_opstr (c, opstr));
292*2d1272b8SAndroid Build Coastguard Worker     }
293*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
294*2d1272b8SAndroid Build Coastguard Worker   }
295*2d1272b8SAndroid Build Coastguard Worker };
296*2d1272b8SAndroid Build Coastguard Worker 
297*2d1272b8SAndroid Build Coastguard Worker struct cff_font_dict_op_serializer_t : op_serializer_t
298*2d1272b8SAndroid Build Coastguard Worker {
serializeCFF::cff_font_dict_op_serializer_t299*2d1272b8SAndroid Build Coastguard Worker   bool serialize (hb_serialize_context_t *c,
300*2d1272b8SAndroid Build Coastguard Worker 		  const op_str_t &opstr,
301*2d1272b8SAndroid Build Coastguard Worker 		  const table_info_t &privateDictInfo) const
302*2d1272b8SAndroid Build Coastguard Worker   {
303*2d1272b8SAndroid Build Coastguard Worker     TRACE_SERIALIZE (this);
304*2d1272b8SAndroid Build Coastguard Worker 
305*2d1272b8SAndroid Build Coastguard Worker     if (opstr.op == OpCode_Private)
306*2d1272b8SAndroid Build Coastguard Worker     {
307*2d1272b8SAndroid Build Coastguard Worker       /* serialize the private dict size & offset as 2-byte & 4-byte integers */
308*2d1272b8SAndroid Build Coastguard Worker       return_trace (UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) &&
309*2d1272b8SAndroid Build Coastguard Worker 		    Dict::serialize_link4_op (c, opstr.op, privateDictInfo.link, whence_t::Absolute));
310*2d1272b8SAndroid Build Coastguard Worker     }
311*2d1272b8SAndroid Build Coastguard Worker     else
312*2d1272b8SAndroid Build Coastguard Worker     {
313*2d1272b8SAndroid Build Coastguard Worker       unsigned char *d = c->allocate_size<unsigned char> (opstr.length);
314*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!d)) return_trace (false);
315*2d1272b8SAndroid Build Coastguard Worker       /* Faster than hb_memcpy for small strings. */
316*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < opstr.length; i++)
317*2d1272b8SAndroid Build Coastguard Worker 	d[i] = opstr.ptr[i];
318*2d1272b8SAndroid Build Coastguard Worker       //hb_memcpy (d, opstr.ptr, opstr.length);
319*2d1272b8SAndroid Build Coastguard Worker     }
320*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
321*2d1272b8SAndroid Build Coastguard Worker   }
322*2d1272b8SAndroid Build Coastguard Worker };
323*2d1272b8SAndroid Build Coastguard Worker 
324*2d1272b8SAndroid Build Coastguard Worker struct flatten_param_t
325*2d1272b8SAndroid Build Coastguard Worker {
326*2d1272b8SAndroid Build Coastguard Worker   str_buff_t     &flatStr;
327*2d1272b8SAndroid Build Coastguard Worker   bool	drop_hints;
328*2d1272b8SAndroid Build Coastguard Worker   const hb_subset_plan_t *plan;
329*2d1272b8SAndroid Build Coastguard Worker };
330*2d1272b8SAndroid Build Coastguard Worker 
331*2d1272b8SAndroid Build Coastguard Worker template <typename ACC, typename ENV, typename OPSET, op_code_t endchar_op=OpCode_Invalid>
332*2d1272b8SAndroid Build Coastguard Worker struct subr_flattener_t
333*2d1272b8SAndroid Build Coastguard Worker {
subr_flattener_tCFF::subr_flattener_t334*2d1272b8SAndroid Build Coastguard Worker   subr_flattener_t (const ACC &acc_,
335*2d1272b8SAndroid Build Coastguard Worker 		    const hb_subset_plan_t *plan_)
336*2d1272b8SAndroid Build Coastguard Worker 		   : acc (acc_), plan (plan_) {}
337*2d1272b8SAndroid Build Coastguard Worker 
flattenCFF::subr_flattener_t338*2d1272b8SAndroid Build Coastguard Worker   bool flatten (str_buff_vec_t &flat_charstrings)
339*2d1272b8SAndroid Build Coastguard Worker   {
340*2d1272b8SAndroid Build Coastguard Worker     unsigned count = plan->num_output_glyphs ();
341*2d1272b8SAndroid Build Coastguard Worker     if (!flat_charstrings.resize_exact (count))
342*2d1272b8SAndroid Build Coastguard Worker       return false;
343*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < count; i++)
344*2d1272b8SAndroid Build Coastguard Worker     {
345*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t  glyph;
346*2d1272b8SAndroid Build Coastguard Worker       if (!plan->old_gid_for_new_gid (i, &glyph))
347*2d1272b8SAndroid Build Coastguard Worker       {
348*2d1272b8SAndroid Build Coastguard Worker 	/* add an endchar only charstring for a missing glyph if CFF1 */
349*2d1272b8SAndroid Build Coastguard Worker 	if (endchar_op != OpCode_Invalid) flat_charstrings[i].push (endchar_op);
350*2d1272b8SAndroid Build Coastguard Worker 	continue;
351*2d1272b8SAndroid Build Coastguard Worker       }
352*2d1272b8SAndroid Build Coastguard Worker       const hb_ubytes_t str = (*acc.charStrings)[glyph];
353*2d1272b8SAndroid Build Coastguard Worker       unsigned int fd = acc.fdSelect->get_fd (glyph);
354*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (fd >= acc.fdCount))
355*2d1272b8SAndroid Build Coastguard Worker 	return false;
356*2d1272b8SAndroid Build Coastguard Worker 
357*2d1272b8SAndroid Build Coastguard Worker 
358*2d1272b8SAndroid Build Coastguard Worker       ENV env (str, acc, fd,
359*2d1272b8SAndroid Build Coastguard Worker 	       plan->normalized_coords.arrayZ, plan->normalized_coords.length);
360*2d1272b8SAndroid Build Coastguard Worker       cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env);
361*2d1272b8SAndroid Build Coastguard Worker       flatten_param_t  param = {
362*2d1272b8SAndroid Build Coastguard Worker         flat_charstrings.arrayZ[i],
363*2d1272b8SAndroid Build Coastguard Worker         (bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING),
364*2d1272b8SAndroid Build Coastguard Worker 	plan
365*2d1272b8SAndroid Build Coastguard Worker       };
366*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!interp.interpret (param)))
367*2d1272b8SAndroid Build Coastguard Worker 	return false;
368*2d1272b8SAndroid Build Coastguard Worker     }
369*2d1272b8SAndroid Build Coastguard Worker     return true;
370*2d1272b8SAndroid Build Coastguard Worker   }
371*2d1272b8SAndroid Build Coastguard Worker 
372*2d1272b8SAndroid Build Coastguard Worker   const ACC &acc;
373*2d1272b8SAndroid Build Coastguard Worker   const hb_subset_plan_t *plan;
374*2d1272b8SAndroid Build Coastguard Worker };
375*2d1272b8SAndroid Build Coastguard Worker 
376*2d1272b8SAndroid Build Coastguard Worker struct subr_closures_t
377*2d1272b8SAndroid Build Coastguard Worker {
subr_closures_tCFF::subr_closures_t378*2d1272b8SAndroid Build Coastguard Worker   subr_closures_t (unsigned int fd_count) : global_closure (), local_closures ()
379*2d1272b8SAndroid Build Coastguard Worker   {
380*2d1272b8SAndroid Build Coastguard Worker     local_closures.resize_exact (fd_count);
381*2d1272b8SAndroid Build Coastguard Worker   }
382*2d1272b8SAndroid Build Coastguard Worker 
resetCFF::subr_closures_t383*2d1272b8SAndroid Build Coastguard Worker   void reset ()
384*2d1272b8SAndroid Build Coastguard Worker   {
385*2d1272b8SAndroid Build Coastguard Worker     global_closure.clear();
386*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < local_closures.length; i++)
387*2d1272b8SAndroid Build Coastguard Worker       local_closures[i].clear();
388*2d1272b8SAndroid Build Coastguard Worker   }
389*2d1272b8SAndroid Build Coastguard Worker 
in_errorCFF::subr_closures_t390*2d1272b8SAndroid Build Coastguard Worker   bool in_error () const { return local_closures.in_error (); }
391*2d1272b8SAndroid Build Coastguard Worker   hb_set_t  global_closure;
392*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<hb_set_t> local_closures;
393*2d1272b8SAndroid Build Coastguard Worker };
394*2d1272b8SAndroid Build Coastguard Worker 
395*2d1272b8SAndroid Build Coastguard Worker struct parsed_cs_op_t : op_str_t
396*2d1272b8SAndroid Build Coastguard Worker {
parsed_cs_op_tCFF::parsed_cs_op_t397*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_op_t (unsigned int subr_num_ = 0) :
398*2d1272b8SAndroid Build Coastguard Worker     subr_num (subr_num_) {}
399*2d1272b8SAndroid Build Coastguard Worker 
is_hintingCFF::parsed_cs_op_t400*2d1272b8SAndroid Build Coastguard Worker   bool is_hinting () const { return hinting_flag; }
set_hintingCFF::parsed_cs_op_t401*2d1272b8SAndroid Build Coastguard Worker   void set_hinting ()       { hinting_flag = true; }
402*2d1272b8SAndroid Build Coastguard Worker 
403*2d1272b8SAndroid Build Coastguard Worker   /* The layout of this struct is designed to fit within the
404*2d1272b8SAndroid Build Coastguard Worker    * padding of op_str_t! */
405*2d1272b8SAndroid Build Coastguard Worker 
406*2d1272b8SAndroid Build Coastguard Worker   protected:
407*2d1272b8SAndroid Build Coastguard Worker   bool	  hinting_flag = false;
408*2d1272b8SAndroid Build Coastguard Worker 
409*2d1272b8SAndroid Build Coastguard Worker   public:
410*2d1272b8SAndroid Build Coastguard Worker   uint16_t subr_num;
411*2d1272b8SAndroid Build Coastguard Worker };
412*2d1272b8SAndroid Build Coastguard Worker 
413*2d1272b8SAndroid Build Coastguard Worker struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
414*2d1272b8SAndroid Build Coastguard Worker {
parsed_cs_str_tCFF::parsed_cs_str_t415*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_t () :
416*2d1272b8SAndroid Build Coastguard Worker     parsed (false),
417*2d1272b8SAndroid Build Coastguard Worker     hint_dropped (false),
418*2d1272b8SAndroid Build Coastguard Worker     has_prefix_ (false),
419*2d1272b8SAndroid Build Coastguard Worker     has_calls_ (false)
420*2d1272b8SAndroid Build Coastguard Worker   {
421*2d1272b8SAndroid Build Coastguard Worker     SUPER::init ();
422*2d1272b8SAndroid Build Coastguard Worker   }
423*2d1272b8SAndroid Build Coastguard Worker 
add_opCFF::parsed_cs_str_t424*2d1272b8SAndroid Build Coastguard Worker   void add_op (op_code_t op, const byte_str_ref_t& str_ref)
425*2d1272b8SAndroid Build Coastguard Worker   {
426*2d1272b8SAndroid Build Coastguard Worker     if (!is_parsed ())
427*2d1272b8SAndroid Build Coastguard Worker       SUPER::add_op (op, str_ref);
428*2d1272b8SAndroid Build Coastguard Worker   }
429*2d1272b8SAndroid Build Coastguard Worker 
add_call_opCFF::parsed_cs_str_t430*2d1272b8SAndroid Build Coastguard Worker   void add_call_op (op_code_t op, const byte_str_ref_t& str_ref, unsigned int subr_num)
431*2d1272b8SAndroid Build Coastguard Worker   {
432*2d1272b8SAndroid Build Coastguard Worker     if (!is_parsed ())
433*2d1272b8SAndroid Build Coastguard Worker     {
434*2d1272b8SAndroid Build Coastguard Worker       has_calls_ = true;
435*2d1272b8SAndroid Build Coastguard Worker 
436*2d1272b8SAndroid Build Coastguard Worker       /* Pop the subroutine number. */
437*2d1272b8SAndroid Build Coastguard Worker       values.pop ();
438*2d1272b8SAndroid Build Coastguard Worker 
439*2d1272b8SAndroid Build Coastguard Worker       SUPER::add_op (op, str_ref, {subr_num});
440*2d1272b8SAndroid Build Coastguard Worker     }
441*2d1272b8SAndroid Build Coastguard Worker   }
442*2d1272b8SAndroid Build Coastguard Worker 
set_prefixCFF::parsed_cs_str_t443*2d1272b8SAndroid Build Coastguard Worker   void set_prefix (const number_t &num, op_code_t op = OpCode_Invalid)
444*2d1272b8SAndroid Build Coastguard Worker   {
445*2d1272b8SAndroid Build Coastguard Worker     has_prefix_ = true;
446*2d1272b8SAndroid Build Coastguard Worker     prefix_op_ = op;
447*2d1272b8SAndroid Build Coastguard Worker     prefix_num_ = num;
448*2d1272b8SAndroid Build Coastguard Worker   }
449*2d1272b8SAndroid Build Coastguard Worker 
at_endCFF::parsed_cs_str_t450*2d1272b8SAndroid Build Coastguard Worker   bool at_end (unsigned int pos) const
451*2d1272b8SAndroid Build Coastguard Worker   {
452*2d1272b8SAndroid Build Coastguard Worker     return ((pos + 1 >= values.length) /* CFF2 */
453*2d1272b8SAndroid Build Coastguard Worker 	|| (values[pos + 1].op == OpCode_return));
454*2d1272b8SAndroid Build Coastguard Worker   }
455*2d1272b8SAndroid Build Coastguard Worker 
is_parsedCFF::parsed_cs_str_t456*2d1272b8SAndroid Build Coastguard Worker   bool is_parsed () const { return parsed; }
set_parsedCFF::parsed_cs_str_t457*2d1272b8SAndroid Build Coastguard Worker   void set_parsed ()      { parsed = true; }
458*2d1272b8SAndroid Build Coastguard Worker 
is_hint_droppedCFF::parsed_cs_str_t459*2d1272b8SAndroid Build Coastguard Worker   bool is_hint_dropped () const { return hint_dropped; }
set_hint_droppedCFF::parsed_cs_str_t460*2d1272b8SAndroid Build Coastguard Worker   void set_hint_dropped ()      { hint_dropped = true; }
461*2d1272b8SAndroid Build Coastguard Worker 
is_vsindex_droppedCFF::parsed_cs_str_t462*2d1272b8SAndroid Build Coastguard Worker   bool is_vsindex_dropped () const { return vsindex_dropped; }
set_vsindex_droppedCFF::parsed_cs_str_t463*2d1272b8SAndroid Build Coastguard Worker   void set_vsindex_dropped ()      { vsindex_dropped = true; }
464*2d1272b8SAndroid Build Coastguard Worker 
has_prefixCFF::parsed_cs_str_t465*2d1272b8SAndroid Build Coastguard Worker   bool has_prefix () const          { return has_prefix_; }
prefix_opCFF::parsed_cs_str_t466*2d1272b8SAndroid Build Coastguard Worker   op_code_t prefix_op () const         { return prefix_op_; }
prefix_numCFF::parsed_cs_str_t467*2d1272b8SAndroid Build Coastguard Worker   const number_t &prefix_num () const { return prefix_num_; }
468*2d1272b8SAndroid Build Coastguard Worker 
has_callsCFF::parsed_cs_str_t469*2d1272b8SAndroid Build Coastguard Worker   bool has_calls () const          { return has_calls_; }
470*2d1272b8SAndroid Build Coastguard Worker 
compactCFF::parsed_cs_str_t471*2d1272b8SAndroid Build Coastguard Worker   void compact ()
472*2d1272b8SAndroid Build Coastguard Worker   {
473*2d1272b8SAndroid Build Coastguard Worker     unsigned count = values.length;
474*2d1272b8SAndroid Build Coastguard Worker     if (!count) return;
475*2d1272b8SAndroid Build Coastguard Worker     auto &opstr = values.arrayZ;
476*2d1272b8SAndroid Build Coastguard Worker     unsigned j = 0;
477*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 1; i < count; i++)
478*2d1272b8SAndroid Build Coastguard Worker     {
479*2d1272b8SAndroid Build Coastguard Worker       /* See if we can combine op j and op i. */
480*2d1272b8SAndroid Build Coastguard Worker       bool combine =
481*2d1272b8SAndroid Build Coastguard Worker         (opstr[j].op != OpCode_callsubr && opstr[j].op != OpCode_callgsubr) &&
482*2d1272b8SAndroid Build Coastguard Worker         (opstr[i].op != OpCode_callsubr && opstr[i].op != OpCode_callgsubr) &&
483*2d1272b8SAndroid Build Coastguard Worker         (opstr[j].is_hinting () == opstr[i].is_hinting ()) &&
484*2d1272b8SAndroid Build Coastguard Worker         (opstr[j].ptr + opstr[j].length == opstr[i].ptr) &&
485*2d1272b8SAndroid Build Coastguard Worker         (opstr[j].length + opstr[i].length <= 255);
486*2d1272b8SAndroid Build Coastguard Worker 
487*2d1272b8SAndroid Build Coastguard Worker       if (combine)
488*2d1272b8SAndroid Build Coastguard Worker       {
489*2d1272b8SAndroid Build Coastguard Worker 	opstr[j].length += opstr[i].length;
490*2d1272b8SAndroid Build Coastguard Worker 	opstr[j].op = OpCode_Invalid;
491*2d1272b8SAndroid Build Coastguard Worker       }
492*2d1272b8SAndroid Build Coastguard Worker       else
493*2d1272b8SAndroid Build Coastguard Worker       {
494*2d1272b8SAndroid Build Coastguard Worker 	opstr[++j] = opstr[i];
495*2d1272b8SAndroid Build Coastguard Worker       }
496*2d1272b8SAndroid Build Coastguard Worker     }
497*2d1272b8SAndroid Build Coastguard Worker     values.shrink (j + 1);
498*2d1272b8SAndroid Build Coastguard Worker   }
499*2d1272b8SAndroid Build Coastguard Worker 
500*2d1272b8SAndroid Build Coastguard Worker   protected:
501*2d1272b8SAndroid Build Coastguard Worker   bool    parsed : 1;
502*2d1272b8SAndroid Build Coastguard Worker   bool    hint_dropped : 1;
503*2d1272b8SAndroid Build Coastguard Worker   bool    vsindex_dropped : 1;
504*2d1272b8SAndroid Build Coastguard Worker   bool    has_prefix_ : 1;
505*2d1272b8SAndroid Build Coastguard Worker   bool    has_calls_ : 1;
506*2d1272b8SAndroid Build Coastguard Worker   op_code_t	prefix_op_;
507*2d1272b8SAndroid Build Coastguard Worker   number_t	prefix_num_;
508*2d1272b8SAndroid Build Coastguard Worker 
509*2d1272b8SAndroid Build Coastguard Worker   private:
510*2d1272b8SAndroid Build Coastguard Worker   typedef parsed_values_t<parsed_cs_op_t> SUPER;
511*2d1272b8SAndroid Build Coastguard Worker };
512*2d1272b8SAndroid Build Coastguard Worker 
513*2d1272b8SAndroid Build Coastguard Worker struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
514*2d1272b8SAndroid Build Coastguard Worker {
515*2d1272b8SAndroid Build Coastguard Worker   private:
516*2d1272b8SAndroid Build Coastguard Worker   typedef hb_vector_t<parsed_cs_str_t> SUPER;
517*2d1272b8SAndroid Build Coastguard Worker };
518*2d1272b8SAndroid Build Coastguard Worker 
519*2d1272b8SAndroid Build Coastguard Worker struct cff_subset_accelerator_t
520*2d1272b8SAndroid Build Coastguard Worker {
createCFF::cff_subset_accelerator_t521*2d1272b8SAndroid Build Coastguard Worker   static cff_subset_accelerator_t* create (
522*2d1272b8SAndroid Build Coastguard Worker       hb_blob_t* original_blob,
523*2d1272b8SAndroid Build Coastguard Worker       const parsed_cs_str_vec_t& parsed_charstrings,
524*2d1272b8SAndroid Build Coastguard Worker       const parsed_cs_str_vec_t& parsed_global_subrs,
525*2d1272b8SAndroid Build Coastguard Worker       const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs) {
526*2d1272b8SAndroid Build Coastguard Worker     cff_subset_accelerator_t* accel =
527*2d1272b8SAndroid Build Coastguard Worker         (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t));
528*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!accel)) return nullptr;
529*2d1272b8SAndroid Build Coastguard Worker     new (accel) cff_subset_accelerator_t (original_blob,
530*2d1272b8SAndroid Build Coastguard Worker                                           parsed_charstrings,
531*2d1272b8SAndroid Build Coastguard Worker                                           parsed_global_subrs,
532*2d1272b8SAndroid Build Coastguard Worker                                           parsed_local_subrs);
533*2d1272b8SAndroid Build Coastguard Worker     return accel;
534*2d1272b8SAndroid Build Coastguard Worker   }
535*2d1272b8SAndroid Build Coastguard Worker 
destroyCFF::cff_subset_accelerator_t536*2d1272b8SAndroid Build Coastguard Worker   static void destroy (void* value) {
537*2d1272b8SAndroid Build Coastguard Worker     if (!value) return;
538*2d1272b8SAndroid Build Coastguard Worker 
539*2d1272b8SAndroid Build Coastguard Worker     cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) value;
540*2d1272b8SAndroid Build Coastguard Worker     accel->~cff_subset_accelerator_t ();
541*2d1272b8SAndroid Build Coastguard Worker     hb_free (accel);
542*2d1272b8SAndroid Build Coastguard Worker   }
543*2d1272b8SAndroid Build Coastguard Worker 
cff_subset_accelerator_tCFF::cff_subset_accelerator_t544*2d1272b8SAndroid Build Coastguard Worker   cff_subset_accelerator_t(
545*2d1272b8SAndroid Build Coastguard Worker       hb_blob_t* original_blob_,
546*2d1272b8SAndroid Build Coastguard Worker       const parsed_cs_str_vec_t& parsed_charstrings_,
547*2d1272b8SAndroid Build Coastguard Worker       const parsed_cs_str_vec_t& parsed_global_subrs_,
548*2d1272b8SAndroid Build Coastguard Worker       const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs_)
549*2d1272b8SAndroid Build Coastguard Worker   {
550*2d1272b8SAndroid Build Coastguard Worker     parsed_charstrings = parsed_charstrings_;
551*2d1272b8SAndroid Build Coastguard Worker     parsed_global_subrs = parsed_global_subrs_;
552*2d1272b8SAndroid Build Coastguard Worker     parsed_local_subrs = parsed_local_subrs_;
553*2d1272b8SAndroid Build Coastguard Worker 
554*2d1272b8SAndroid Build Coastguard Worker     // the parsed charstrings point to memory in the original CFF table so we must hold a reference
555*2d1272b8SAndroid Build Coastguard Worker     // to it to keep the memory valid.
556*2d1272b8SAndroid Build Coastguard Worker     original_blob = hb_blob_reference (original_blob_);
557*2d1272b8SAndroid Build Coastguard Worker   }
558*2d1272b8SAndroid Build Coastguard Worker 
~cff_subset_accelerator_tCFF::cff_subset_accelerator_t559*2d1272b8SAndroid Build Coastguard Worker   ~cff_subset_accelerator_t()
560*2d1272b8SAndroid Build Coastguard Worker   {
561*2d1272b8SAndroid Build Coastguard Worker     hb_blob_destroy (original_blob);
562*2d1272b8SAndroid Build Coastguard Worker     auto *mapping = glyph_to_sid_map.get_relaxed ();
563*2d1272b8SAndroid Build Coastguard Worker     if (mapping)
564*2d1272b8SAndroid Build Coastguard Worker     {
565*2d1272b8SAndroid Build Coastguard Worker       mapping->~glyph_to_sid_map_t ();
566*2d1272b8SAndroid Build Coastguard Worker       hb_free (mapping);
567*2d1272b8SAndroid Build Coastguard Worker     }
568*2d1272b8SAndroid Build Coastguard Worker   }
569*2d1272b8SAndroid Build Coastguard Worker 
570*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_vec_t parsed_charstrings;
571*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_vec_t parsed_global_subrs;
572*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
573*2d1272b8SAndroid Build Coastguard Worker   mutable hb_atomic_ptr_t<glyph_to_sid_map_t> glyph_to_sid_map;
574*2d1272b8SAndroid Build Coastguard Worker 
575*2d1272b8SAndroid Build Coastguard Worker  private:
576*2d1272b8SAndroid Build Coastguard Worker   hb_blob_t* original_blob;
577*2d1272b8SAndroid Build Coastguard Worker };
578*2d1272b8SAndroid Build Coastguard Worker 
579*2d1272b8SAndroid Build Coastguard Worker struct subr_subset_param_t
580*2d1272b8SAndroid Build Coastguard Worker {
subr_subset_param_tCFF::subr_subset_param_t581*2d1272b8SAndroid Build Coastguard Worker   subr_subset_param_t (parsed_cs_str_t *parsed_charstring_,
582*2d1272b8SAndroid Build Coastguard Worker 		       parsed_cs_str_vec_t *parsed_global_subrs_,
583*2d1272b8SAndroid Build Coastguard Worker 		       parsed_cs_str_vec_t *parsed_local_subrs_,
584*2d1272b8SAndroid Build Coastguard Worker 		       hb_set_t *global_closure_,
585*2d1272b8SAndroid Build Coastguard Worker 		       hb_set_t *local_closure_,
586*2d1272b8SAndroid Build Coastguard Worker 		       bool drop_hints_) :
587*2d1272b8SAndroid Build Coastguard Worker       current_parsed_str (parsed_charstring_),
588*2d1272b8SAndroid Build Coastguard Worker       parsed_charstring (parsed_charstring_),
589*2d1272b8SAndroid Build Coastguard Worker       parsed_global_subrs (parsed_global_subrs_),
590*2d1272b8SAndroid Build Coastguard Worker       parsed_local_subrs (parsed_local_subrs_),
591*2d1272b8SAndroid Build Coastguard Worker       global_closure (global_closure_),
592*2d1272b8SAndroid Build Coastguard Worker       local_closure (local_closure_),
593*2d1272b8SAndroid Build Coastguard Worker       drop_hints (drop_hints_) {}
594*2d1272b8SAndroid Build Coastguard Worker 
get_parsed_str_for_contextCFF::subr_subset_param_t595*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_t *get_parsed_str_for_context (call_context_t &context)
596*2d1272b8SAndroid Build Coastguard Worker   {
597*2d1272b8SAndroid Build Coastguard Worker     switch (context.type)
598*2d1272b8SAndroid Build Coastguard Worker     {
599*2d1272b8SAndroid Build Coastguard Worker       case CSType_CharString:
600*2d1272b8SAndroid Build Coastguard Worker 	return parsed_charstring;
601*2d1272b8SAndroid Build Coastguard Worker 
602*2d1272b8SAndroid Build Coastguard Worker       case CSType_LocalSubr:
603*2d1272b8SAndroid Build Coastguard Worker 	if (likely (context.subr_num < parsed_local_subrs->length))
604*2d1272b8SAndroid Build Coastguard Worker 	  return &(*parsed_local_subrs)[context.subr_num];
605*2d1272b8SAndroid Build Coastguard Worker 	break;
606*2d1272b8SAndroid Build Coastguard Worker 
607*2d1272b8SAndroid Build Coastguard Worker       case CSType_GlobalSubr:
608*2d1272b8SAndroid Build Coastguard Worker 	if (likely (context.subr_num < parsed_global_subrs->length))
609*2d1272b8SAndroid Build Coastguard Worker 	  return &(*parsed_global_subrs)[context.subr_num];
610*2d1272b8SAndroid Build Coastguard Worker 	break;
611*2d1272b8SAndroid Build Coastguard Worker     }
612*2d1272b8SAndroid Build Coastguard Worker     return nullptr;
613*2d1272b8SAndroid Build Coastguard Worker   }
614*2d1272b8SAndroid Build Coastguard Worker 
615*2d1272b8SAndroid Build Coastguard Worker   template <typename ENV>
set_current_strCFF::subr_subset_param_t616*2d1272b8SAndroid Build Coastguard Worker   void set_current_str (ENV &env, bool calling)
617*2d1272b8SAndroid Build Coastguard Worker   {
618*2d1272b8SAndroid Build Coastguard Worker     parsed_cs_str_t *parsed_str = get_parsed_str_for_context (env.context);
619*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!parsed_str))
620*2d1272b8SAndroid Build Coastguard Worker     {
621*2d1272b8SAndroid Build Coastguard Worker       env.set_error ();
622*2d1272b8SAndroid Build Coastguard Worker       return;
623*2d1272b8SAndroid Build Coastguard Worker     }
624*2d1272b8SAndroid Build Coastguard Worker     /* If the called subroutine is parsed partially but not completely yet,
625*2d1272b8SAndroid Build Coastguard Worker      * it must be because we are calling it recursively.
626*2d1272b8SAndroid Build Coastguard Worker      * Handle it as an error. */
627*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
628*2d1272b8SAndroid Build Coastguard Worker       env.set_error ();
629*2d1272b8SAndroid Build Coastguard Worker     else
630*2d1272b8SAndroid Build Coastguard Worker     {
631*2d1272b8SAndroid Build Coastguard Worker       if (!parsed_str->is_parsed ())
632*2d1272b8SAndroid Build Coastguard Worker         parsed_str->alloc (env.str_ref.total_size ());
633*2d1272b8SAndroid Build Coastguard Worker       current_parsed_str = parsed_str;
634*2d1272b8SAndroid Build Coastguard Worker     }
635*2d1272b8SAndroid Build Coastguard Worker   }
636*2d1272b8SAndroid Build Coastguard Worker 
637*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_t	*current_parsed_str;
638*2d1272b8SAndroid Build Coastguard Worker 
639*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_t	*parsed_charstring;
640*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_vec_t	*parsed_global_subrs;
641*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_vec_t	*parsed_local_subrs;
642*2d1272b8SAndroid Build Coastguard Worker   hb_set_t      *global_closure;
643*2d1272b8SAndroid Build Coastguard Worker   hb_set_t      *local_closure;
644*2d1272b8SAndroid Build Coastguard Worker   bool	  drop_hints;
645*2d1272b8SAndroid Build Coastguard Worker };
646*2d1272b8SAndroid Build Coastguard Worker 
647*2d1272b8SAndroid Build Coastguard Worker struct subr_remap_t : hb_inc_bimap_t
648*2d1272b8SAndroid Build Coastguard Worker {
createCFF::subr_remap_t649*2d1272b8SAndroid Build Coastguard Worker   void create (const hb_set_t *closure)
650*2d1272b8SAndroid Build Coastguard Worker   {
651*2d1272b8SAndroid Build Coastguard Worker     /* create a remapping of subroutine numbers from old to new.
652*2d1272b8SAndroid Build Coastguard Worker      * no optimization based on usage counts. fonttools doesn't appear doing that either.
653*2d1272b8SAndroid Build Coastguard Worker      */
654*2d1272b8SAndroid Build Coastguard Worker 
655*2d1272b8SAndroid Build Coastguard Worker     alloc (closure->get_population ());
656*2d1272b8SAndroid Build Coastguard Worker     for (auto old_num : *closure)
657*2d1272b8SAndroid Build Coastguard Worker       add (old_num);
658*2d1272b8SAndroid Build Coastguard Worker 
659*2d1272b8SAndroid Build Coastguard Worker     if (get_population () < 1240)
660*2d1272b8SAndroid Build Coastguard Worker       bias = 107;
661*2d1272b8SAndroid Build Coastguard Worker     else if (get_population () < 33900)
662*2d1272b8SAndroid Build Coastguard Worker       bias = 1131;
663*2d1272b8SAndroid Build Coastguard Worker     else
664*2d1272b8SAndroid Build Coastguard Worker       bias = 32768;
665*2d1272b8SAndroid Build Coastguard Worker   }
666*2d1272b8SAndroid Build Coastguard Worker 
biased_numCFF::subr_remap_t667*2d1272b8SAndroid Build Coastguard Worker   int biased_num (unsigned int old_num) const
668*2d1272b8SAndroid Build Coastguard Worker   {
669*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t new_num = get (old_num);
670*2d1272b8SAndroid Build Coastguard Worker     return (int)new_num - bias;
671*2d1272b8SAndroid Build Coastguard Worker   }
672*2d1272b8SAndroid Build Coastguard Worker 
673*2d1272b8SAndroid Build Coastguard Worker   protected:
674*2d1272b8SAndroid Build Coastguard Worker   int bias;
675*2d1272b8SAndroid Build Coastguard Worker };
676*2d1272b8SAndroid Build Coastguard Worker 
677*2d1272b8SAndroid Build Coastguard Worker struct subr_remaps_t
678*2d1272b8SAndroid Build Coastguard Worker {
subr_remaps_tCFF::subr_remaps_t679*2d1272b8SAndroid Build Coastguard Worker   subr_remaps_t (unsigned int fdCount)
680*2d1272b8SAndroid Build Coastguard Worker   {
681*2d1272b8SAndroid Build Coastguard Worker     local_remaps.resize (fdCount);
682*2d1272b8SAndroid Build Coastguard Worker   }
683*2d1272b8SAndroid Build Coastguard Worker 
in_errorCFF::subr_remaps_t684*2d1272b8SAndroid Build Coastguard Worker   bool in_error()
685*2d1272b8SAndroid Build Coastguard Worker   {
686*2d1272b8SAndroid Build Coastguard Worker     return local_remaps.in_error ();
687*2d1272b8SAndroid Build Coastguard Worker   }
688*2d1272b8SAndroid Build Coastguard Worker 
createCFF::subr_remaps_t689*2d1272b8SAndroid Build Coastguard Worker   void create (subr_closures_t& closures)
690*2d1272b8SAndroid Build Coastguard Worker   {
691*2d1272b8SAndroid Build Coastguard Worker     global_remap.create (&closures.global_closure);
692*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < local_remaps.length; i++)
693*2d1272b8SAndroid Build Coastguard Worker       local_remaps.arrayZ[i].create (&closures.local_closures[i]);
694*2d1272b8SAndroid Build Coastguard Worker   }
695*2d1272b8SAndroid Build Coastguard Worker 
696*2d1272b8SAndroid Build Coastguard Worker   subr_remap_t	       global_remap;
697*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<subr_remap_t>  local_remaps;
698*2d1272b8SAndroid Build Coastguard Worker };
699*2d1272b8SAndroid Build Coastguard Worker 
700*2d1272b8SAndroid Build Coastguard Worker template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typename OPSET, op_code_t endchar_op=OpCode_Invalid>
701*2d1272b8SAndroid Build Coastguard Worker struct subr_subsetter_t
702*2d1272b8SAndroid Build Coastguard Worker {
subr_subsetter_tCFF::subr_subsetter_t703*2d1272b8SAndroid Build Coastguard Worker   subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_)
704*2d1272b8SAndroid Build Coastguard Worker       : acc (acc_), plan (plan_), closures(acc_.fdCount),
705*2d1272b8SAndroid Build Coastguard Worker         remaps(acc_.fdCount)
706*2d1272b8SAndroid Build Coastguard Worker   {}
707*2d1272b8SAndroid Build Coastguard Worker 
708*2d1272b8SAndroid Build Coastguard Worker   /* Subroutine subsetting with --no-desubroutinize runs in phases:
709*2d1272b8SAndroid Build Coastguard Worker    *
710*2d1272b8SAndroid Build Coastguard Worker    * 1. execute charstrings/subroutines to determine subroutine closures
711*2d1272b8SAndroid Build Coastguard Worker    * 2. parse out all operators and numbers
712*2d1272b8SAndroid Build Coastguard Worker    * 3. mark hint operators and operands for removal if --no-hinting
713*2d1272b8SAndroid Build Coastguard Worker    * 4. re-encode all charstrings and subroutines with new subroutine numbers
714*2d1272b8SAndroid Build Coastguard Worker    *
715*2d1272b8SAndroid Build Coastguard Worker    * Phases #1 and #2 are done at the same time in collect_subrs ().
716*2d1272b8SAndroid Build Coastguard Worker    * Phase #3 walks charstrings/subroutines forward then backward (hence parsing required),
717*2d1272b8SAndroid Build Coastguard Worker    * because we can't tell if a number belongs to a hint op until we see the first moveto.
718*2d1272b8SAndroid Build Coastguard Worker    *
719*2d1272b8SAndroid Build Coastguard Worker    * Assumption: a callsubr/callgsubr operator must immediately follow a (biased) subroutine number
720*2d1272b8SAndroid Build Coastguard Worker    * within the same charstring/subroutine, e.g., not split across a charstring and a subroutine.
721*2d1272b8SAndroid Build Coastguard Worker    */
subsetCFF::subr_subsetter_t722*2d1272b8SAndroid Build Coastguard Worker   bool subset (void)
723*2d1272b8SAndroid Build Coastguard Worker   {
724*2d1272b8SAndroid Build Coastguard Worker     unsigned fd_count = acc.fdCount;
725*2d1272b8SAndroid Build Coastguard Worker     const cff_subset_accelerator_t* cff_accelerator = nullptr;
726*2d1272b8SAndroid Build Coastguard Worker     if (acc.cff_accelerator) {
727*2d1272b8SAndroid Build Coastguard Worker       cff_accelerator = acc.cff_accelerator;
728*2d1272b8SAndroid Build Coastguard Worker       fd_count = cff_accelerator->parsed_local_subrs.length;
729*2d1272b8SAndroid Build Coastguard Worker     }
730*2d1272b8SAndroid Build Coastguard Worker 
731*2d1272b8SAndroid Build Coastguard Worker     if (cff_accelerator) {
732*2d1272b8SAndroid Build Coastguard Worker       // If we are not dropping hinting then charstrings are not modified so we can
733*2d1272b8SAndroid Build Coastguard Worker       // just use a reference to the cached copies.
734*2d1272b8SAndroid Build Coastguard Worker       cached_charstrings.resize_exact (plan->num_output_glyphs ());
735*2d1272b8SAndroid Build Coastguard Worker       parsed_global_subrs = &cff_accelerator->parsed_global_subrs;
736*2d1272b8SAndroid Build Coastguard Worker       parsed_local_subrs = &cff_accelerator->parsed_local_subrs;
737*2d1272b8SAndroid Build Coastguard Worker     } else {
738*2d1272b8SAndroid Build Coastguard Worker       parsed_charstrings.resize_exact (plan->num_output_glyphs ());
739*2d1272b8SAndroid Build Coastguard Worker       parsed_global_subrs_storage.resize_exact (acc.globalSubrs->count);
740*2d1272b8SAndroid Build Coastguard Worker 
741*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!parsed_local_subrs_storage.resize (fd_count))) return false;
742*2d1272b8SAndroid Build Coastguard Worker 
743*2d1272b8SAndroid Build Coastguard Worker       for (unsigned int i = 0; i < acc.fdCount; i++)
744*2d1272b8SAndroid Build Coastguard Worker       {
745*2d1272b8SAndroid Build Coastguard Worker         unsigned count = acc.privateDicts[i].localSubrs->count;
746*2d1272b8SAndroid Build Coastguard Worker         parsed_local_subrs_storage[i].resize (count);
747*2d1272b8SAndroid Build Coastguard Worker         if (unlikely (parsed_local_subrs_storage[i].in_error ())) return false;
748*2d1272b8SAndroid Build Coastguard Worker       }
749*2d1272b8SAndroid Build Coastguard Worker 
750*2d1272b8SAndroid Build Coastguard Worker       parsed_global_subrs = &parsed_global_subrs_storage;
751*2d1272b8SAndroid Build Coastguard Worker       parsed_local_subrs = &parsed_local_subrs_storage;
752*2d1272b8SAndroid Build Coastguard Worker     }
753*2d1272b8SAndroid Build Coastguard Worker 
754*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (remaps.in_error()
755*2d1272b8SAndroid Build Coastguard Worker                   || cached_charstrings.in_error ()
756*2d1272b8SAndroid Build Coastguard Worker                   || parsed_charstrings.in_error ()
757*2d1272b8SAndroid Build Coastguard Worker                   || parsed_global_subrs->in_error ()
758*2d1272b8SAndroid Build Coastguard Worker                   || closures.in_error ())) {
759*2d1272b8SAndroid Build Coastguard Worker       return false;
760*2d1272b8SAndroid Build Coastguard Worker     }
761*2d1272b8SAndroid Build Coastguard Worker 
762*2d1272b8SAndroid Build Coastguard Worker     /* phase 1 & 2 */
763*2d1272b8SAndroid Build Coastguard Worker     for (auto _ : plan->new_to_old_gid_list)
764*2d1272b8SAndroid Build Coastguard Worker     {
765*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t new_glyph = _.first;
766*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t old_glyph = _.second;
767*2d1272b8SAndroid Build Coastguard Worker 
768*2d1272b8SAndroid Build Coastguard Worker       const hb_ubytes_t str = (*acc.charStrings)[old_glyph];
769*2d1272b8SAndroid Build Coastguard Worker       unsigned int fd = acc.fdSelect->get_fd (old_glyph);
770*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (fd >= acc.fdCount))
771*2d1272b8SAndroid Build Coastguard Worker         return false;
772*2d1272b8SAndroid Build Coastguard Worker 
773*2d1272b8SAndroid Build Coastguard Worker       if (cff_accelerator)
774*2d1272b8SAndroid Build Coastguard Worker       {
775*2d1272b8SAndroid Build Coastguard Worker         // parsed string already exists in accelerator, copy it and move
776*2d1272b8SAndroid Build Coastguard Worker         // on.
777*2d1272b8SAndroid Build Coastguard Worker         if (cached_charstrings)
778*2d1272b8SAndroid Build Coastguard Worker           cached_charstrings[new_glyph] = &cff_accelerator->parsed_charstrings[old_glyph];
779*2d1272b8SAndroid Build Coastguard Worker         else
780*2d1272b8SAndroid Build Coastguard Worker           parsed_charstrings[new_glyph] = cff_accelerator->parsed_charstrings[old_glyph];
781*2d1272b8SAndroid Build Coastguard Worker 
782*2d1272b8SAndroid Build Coastguard Worker         continue;
783*2d1272b8SAndroid Build Coastguard Worker       }
784*2d1272b8SAndroid Build Coastguard Worker 
785*2d1272b8SAndroid Build Coastguard Worker       ENV env (str, acc, fd);
786*2d1272b8SAndroid Build Coastguard Worker       cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env);
787*2d1272b8SAndroid Build Coastguard Worker 
788*2d1272b8SAndroid Build Coastguard Worker       parsed_charstrings[new_glyph].alloc (str.length);
789*2d1272b8SAndroid Build Coastguard Worker       subr_subset_param_t  param (&parsed_charstrings[new_glyph],
790*2d1272b8SAndroid Build Coastguard Worker                                   &parsed_global_subrs_storage,
791*2d1272b8SAndroid Build Coastguard Worker                                   &parsed_local_subrs_storage[fd],
792*2d1272b8SAndroid Build Coastguard Worker                                   &closures.global_closure,
793*2d1272b8SAndroid Build Coastguard Worker                                   &closures.local_closures[fd],
794*2d1272b8SAndroid Build Coastguard Worker                                   plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
795*2d1272b8SAndroid Build Coastguard Worker 
796*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!interp.interpret (param)))
797*2d1272b8SAndroid Build Coastguard Worker         return false;
798*2d1272b8SAndroid Build Coastguard Worker 
799*2d1272b8SAndroid Build Coastguard Worker       /* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
800*2d1272b8SAndroid Build Coastguard Worker       SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[new_glyph]);
801*2d1272b8SAndroid Build Coastguard Worker 
802*2d1272b8SAndroid Build Coastguard Worker       /* mark hint ops and arguments for drop */
803*2d1272b8SAndroid Build Coastguard Worker       if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING) || plan->inprogress_accelerator)
804*2d1272b8SAndroid Build Coastguard Worker       {
805*2d1272b8SAndroid Build Coastguard Worker 	subr_subset_param_t  param (&parsed_charstrings[new_glyph],
806*2d1272b8SAndroid Build Coastguard Worker 				    &parsed_global_subrs_storage,
807*2d1272b8SAndroid Build Coastguard Worker 				    &parsed_local_subrs_storage[fd],
808*2d1272b8SAndroid Build Coastguard Worker 				    &closures.global_closure,
809*2d1272b8SAndroid Build Coastguard Worker 				    &closures.local_closures[fd],
810*2d1272b8SAndroid Build Coastguard Worker 				    plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
811*2d1272b8SAndroid Build Coastguard Worker 
812*2d1272b8SAndroid Build Coastguard Worker 	drop_hints_param_t  drop;
813*2d1272b8SAndroid Build Coastguard Worker 	if (drop_hints_in_str (parsed_charstrings[new_glyph], param, drop))
814*2d1272b8SAndroid Build Coastguard Worker 	{
815*2d1272b8SAndroid Build Coastguard Worker 	  parsed_charstrings[new_glyph].set_hint_dropped ();
816*2d1272b8SAndroid Build Coastguard Worker 	  if (drop.vsindex_dropped)
817*2d1272b8SAndroid Build Coastguard Worker 	    parsed_charstrings[new_glyph].set_vsindex_dropped ();
818*2d1272b8SAndroid Build Coastguard Worker 	}
819*2d1272b8SAndroid Build Coastguard Worker       }
820*2d1272b8SAndroid Build Coastguard Worker 
821*2d1272b8SAndroid Build Coastguard Worker       /* Doing this here one by one instead of compacting all at the end
822*2d1272b8SAndroid Build Coastguard Worker        * has massive peak-memory saving.
823*2d1272b8SAndroid Build Coastguard Worker        *
824*2d1272b8SAndroid Build Coastguard Worker        * The compacting both saves memory and makes further operations
825*2d1272b8SAndroid Build Coastguard Worker        * faster.
826*2d1272b8SAndroid Build Coastguard Worker        */
827*2d1272b8SAndroid Build Coastguard Worker       parsed_charstrings[new_glyph].compact ();
828*2d1272b8SAndroid Build Coastguard Worker     }
829*2d1272b8SAndroid Build Coastguard Worker 
830*2d1272b8SAndroid Build Coastguard Worker     /* Since parsed strings were loaded from accelerator, we still need
831*2d1272b8SAndroid Build Coastguard Worker      * to compute the subroutine closures which would have normally happened during
832*2d1272b8SAndroid Build Coastguard Worker      * parsing.
833*2d1272b8SAndroid Build Coastguard Worker      *
834*2d1272b8SAndroid Build Coastguard Worker      * Or if we are dropping hinting, redo closure to get actually used subrs.
835*2d1272b8SAndroid Build Coastguard Worker      */
836*2d1272b8SAndroid Build Coastguard Worker     if ((cff_accelerator ||
837*2d1272b8SAndroid Build Coastguard Worker 	(!cff_accelerator && plan->flags & HB_SUBSET_FLAGS_NO_HINTING)) &&
838*2d1272b8SAndroid Build Coastguard Worker         !closure_subroutines(*parsed_global_subrs,
839*2d1272b8SAndroid Build Coastguard Worker                              *parsed_local_subrs))
840*2d1272b8SAndroid Build Coastguard Worker       return false;
841*2d1272b8SAndroid Build Coastguard Worker 
842*2d1272b8SAndroid Build Coastguard Worker     remaps.create (closures);
843*2d1272b8SAndroid Build Coastguard Worker 
844*2d1272b8SAndroid Build Coastguard Worker     populate_subset_accelerator ();
845*2d1272b8SAndroid Build Coastguard Worker     return true;
846*2d1272b8SAndroid Build Coastguard Worker   }
847*2d1272b8SAndroid Build Coastguard Worker 
encode_charstringsCFF::subr_subsetter_t848*2d1272b8SAndroid Build Coastguard Worker   bool encode_charstrings (str_buff_vec_t &buffArray, bool encode_prefix = true) const
849*2d1272b8SAndroid Build Coastguard Worker   {
850*2d1272b8SAndroid Build Coastguard Worker     unsigned num_glyphs = plan->num_output_glyphs ();
851*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!buffArray.resize_exact (num_glyphs)))
852*2d1272b8SAndroid Build Coastguard Worker       return false;
853*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t last = 0;
854*2d1272b8SAndroid Build Coastguard Worker     for (auto _ : plan->new_to_old_gid_list)
855*2d1272b8SAndroid Build Coastguard Worker     {
856*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t gid = _.first;
857*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t old_glyph = _.second;
858*2d1272b8SAndroid Build Coastguard Worker 
859*2d1272b8SAndroid Build Coastguard Worker       if (endchar_op != OpCode_Invalid)
860*2d1272b8SAndroid Build Coastguard Worker         for (; last < gid; last++)
861*2d1272b8SAndroid Build Coastguard Worker 	{
862*2d1272b8SAndroid Build Coastguard Worker 	  // Hack to point vector to static string.
863*2d1272b8SAndroid Build Coastguard Worker 	  auto &b = buffArray.arrayZ[last];
864*2d1272b8SAndroid Build Coastguard Worker 	  b.length = 1;
865*2d1272b8SAndroid Build Coastguard Worker 	  b.arrayZ = const_cast<unsigned char *>(endchar_str);
866*2d1272b8SAndroid Build Coastguard Worker 	}
867*2d1272b8SAndroid Build Coastguard Worker 
868*2d1272b8SAndroid Build Coastguard Worker       last++; // Skip over gid
869*2d1272b8SAndroid Build Coastguard Worker       unsigned int  fd = acc.fdSelect->get_fd (old_glyph);
870*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (fd >= acc.fdCount))
871*2d1272b8SAndroid Build Coastguard Worker 	return false;
872*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!encode_str (get_parsed_charstring (gid), fd, buffArray.arrayZ[gid], encode_prefix)))
873*2d1272b8SAndroid Build Coastguard Worker 	return false;
874*2d1272b8SAndroid Build Coastguard Worker     }
875*2d1272b8SAndroid Build Coastguard Worker     if (endchar_op != OpCode_Invalid)
876*2d1272b8SAndroid Build Coastguard Worker       for (; last < num_glyphs; last++)
877*2d1272b8SAndroid Build Coastguard Worker       {
878*2d1272b8SAndroid Build Coastguard Worker 	// Hack to point vector to static string.
879*2d1272b8SAndroid Build Coastguard Worker 	auto &b = buffArray.arrayZ[last];
880*2d1272b8SAndroid Build Coastguard Worker 	b.length = 1;
881*2d1272b8SAndroid Build Coastguard Worker 	b.arrayZ = const_cast<unsigned char *>(endchar_str);
882*2d1272b8SAndroid Build Coastguard Worker       }
883*2d1272b8SAndroid Build Coastguard Worker 
884*2d1272b8SAndroid Build Coastguard Worker     return true;
885*2d1272b8SAndroid Build Coastguard Worker   }
886*2d1272b8SAndroid Build Coastguard Worker 
encode_subrsCFF::subr_subsetter_t887*2d1272b8SAndroid Build Coastguard Worker   bool encode_subrs (const parsed_cs_str_vec_t &subrs, const subr_remap_t& remap, unsigned int fd, str_buff_vec_t &buffArray) const
888*2d1272b8SAndroid Build Coastguard Worker   {
889*2d1272b8SAndroid Build Coastguard Worker     unsigned int  count = remap.get_population ();
890*2d1272b8SAndroid Build Coastguard Worker 
891*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!buffArray.resize_exact (count)))
892*2d1272b8SAndroid Build Coastguard Worker       return false;
893*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int new_num = 0; new_num < count; new_num++)
894*2d1272b8SAndroid Build Coastguard Worker     {
895*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t old_num = remap.backward (new_num);
896*2d1272b8SAndroid Build Coastguard Worker       assert (old_num != CFF_UNDEF_CODE);
897*2d1272b8SAndroid Build Coastguard Worker 
898*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
899*2d1272b8SAndroid Build Coastguard Worker 	return false;
900*2d1272b8SAndroid Build Coastguard Worker     }
901*2d1272b8SAndroid Build Coastguard Worker     return true;
902*2d1272b8SAndroid Build Coastguard Worker   }
903*2d1272b8SAndroid Build Coastguard Worker 
encode_globalsubrsCFF::subr_subsetter_t904*2d1272b8SAndroid Build Coastguard Worker   bool encode_globalsubrs (str_buff_vec_t &buffArray)
905*2d1272b8SAndroid Build Coastguard Worker   {
906*2d1272b8SAndroid Build Coastguard Worker     return encode_subrs (*parsed_global_subrs, remaps.global_remap, 0, buffArray);
907*2d1272b8SAndroid Build Coastguard Worker   }
908*2d1272b8SAndroid Build Coastguard Worker 
encode_localsubrsCFF::subr_subsetter_t909*2d1272b8SAndroid Build Coastguard Worker   bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const
910*2d1272b8SAndroid Build Coastguard Worker   {
911*2d1272b8SAndroid Build Coastguard Worker     return encode_subrs ((*parsed_local_subrs)[fd], remaps.local_remaps[fd], fd, buffArray);
912*2d1272b8SAndroid Build Coastguard Worker   }
913*2d1272b8SAndroid Build Coastguard Worker 
914*2d1272b8SAndroid Build Coastguard Worker   protected:
915*2d1272b8SAndroid Build Coastguard Worker   struct drop_hints_param_t
916*2d1272b8SAndroid Build Coastguard Worker   {
drop_hints_param_tCFF::subr_subsetter_t::drop_hints_param_t917*2d1272b8SAndroid Build Coastguard Worker     drop_hints_param_t ()
918*2d1272b8SAndroid Build Coastguard Worker       : seen_moveto (false),
919*2d1272b8SAndroid Build Coastguard Worker 	ends_in_hint (false),
920*2d1272b8SAndroid Build Coastguard Worker 	all_dropped (false),
921*2d1272b8SAndroid Build Coastguard Worker 	vsindex_dropped (false) {}
922*2d1272b8SAndroid Build Coastguard Worker 
923*2d1272b8SAndroid Build Coastguard Worker     bool  seen_moveto;
924*2d1272b8SAndroid Build Coastguard Worker     bool  ends_in_hint;
925*2d1272b8SAndroid Build Coastguard Worker     bool  all_dropped;
926*2d1272b8SAndroid Build Coastguard Worker     bool  vsindex_dropped;
927*2d1272b8SAndroid Build Coastguard Worker   };
928*2d1272b8SAndroid Build Coastguard Worker 
drop_hints_in_subrCFF::subr_subsetter_t929*2d1272b8SAndroid Build Coastguard Worker   bool drop_hints_in_subr (parsed_cs_str_t &str, unsigned int pos,
930*2d1272b8SAndroid Build Coastguard Worker 			   parsed_cs_str_vec_t &subrs, unsigned int subr_num,
931*2d1272b8SAndroid Build Coastguard Worker 			   const subr_subset_param_t &param, drop_hints_param_t &drop)
932*2d1272b8SAndroid Build Coastguard Worker   {
933*2d1272b8SAndroid Build Coastguard Worker     drop.ends_in_hint = false;
934*2d1272b8SAndroid Build Coastguard Worker     bool has_hint = drop_hints_in_str (subrs[subr_num], param, drop);
935*2d1272b8SAndroid Build Coastguard Worker 
936*2d1272b8SAndroid Build Coastguard Worker     /* if this subr ends with a stem hint (i.e., not a number; potential argument for moveto),
937*2d1272b8SAndroid Build Coastguard Worker      * then this entire subroutine must be a hint. drop its call. */
938*2d1272b8SAndroid Build Coastguard Worker     if (drop.ends_in_hint)
939*2d1272b8SAndroid Build Coastguard Worker     {
940*2d1272b8SAndroid Build Coastguard Worker       str.values[pos].set_hinting ();
941*2d1272b8SAndroid Build Coastguard Worker       /* if this subr call is at the end of the parent subr, propagate the flag
942*2d1272b8SAndroid Build Coastguard Worker        * otherwise reset the flag */
943*2d1272b8SAndroid Build Coastguard Worker       if (!str.at_end (pos))
944*2d1272b8SAndroid Build Coastguard Worker 	drop.ends_in_hint = false;
945*2d1272b8SAndroid Build Coastguard Worker     }
946*2d1272b8SAndroid Build Coastguard Worker     else if (drop.all_dropped)
947*2d1272b8SAndroid Build Coastguard Worker     {
948*2d1272b8SAndroid Build Coastguard Worker       str.values[pos].set_hinting ();
949*2d1272b8SAndroid Build Coastguard Worker     }
950*2d1272b8SAndroid Build Coastguard Worker 
951*2d1272b8SAndroid Build Coastguard Worker     return has_hint;
952*2d1272b8SAndroid Build Coastguard Worker   }
953*2d1272b8SAndroid Build Coastguard Worker 
954*2d1272b8SAndroid Build Coastguard Worker   /* returns true if it sees a hint op before the first moveto */
drop_hints_in_strCFF::subr_subsetter_t955*2d1272b8SAndroid Build Coastguard Worker   bool drop_hints_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param, drop_hints_param_t &drop)
956*2d1272b8SAndroid Build Coastguard Worker   {
957*2d1272b8SAndroid Build Coastguard Worker     bool  seen_hint = false;
958*2d1272b8SAndroid Build Coastguard Worker 
959*2d1272b8SAndroid Build Coastguard Worker     unsigned count = str.values.length;
960*2d1272b8SAndroid Build Coastguard Worker     auto *values = str.values.arrayZ;
961*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int pos = 0; pos < count; pos++)
962*2d1272b8SAndroid Build Coastguard Worker     {
963*2d1272b8SAndroid Build Coastguard Worker       bool  has_hint = false;
964*2d1272b8SAndroid Build Coastguard Worker       switch (values[pos].op)
965*2d1272b8SAndroid Build Coastguard Worker       {
966*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_callsubr:
967*2d1272b8SAndroid Build Coastguard Worker 	  has_hint = drop_hints_in_subr (str, pos,
968*2d1272b8SAndroid Build Coastguard Worker 					*param.parsed_local_subrs, values[pos].subr_num,
969*2d1272b8SAndroid Build Coastguard Worker 					param, drop);
970*2d1272b8SAndroid Build Coastguard Worker 	  break;
971*2d1272b8SAndroid Build Coastguard Worker 
972*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_callgsubr:
973*2d1272b8SAndroid Build Coastguard Worker 	  has_hint = drop_hints_in_subr (str, pos,
974*2d1272b8SAndroid Build Coastguard Worker 					*param.parsed_global_subrs, values[pos].subr_num,
975*2d1272b8SAndroid Build Coastguard Worker 					param, drop);
976*2d1272b8SAndroid Build Coastguard Worker 	  break;
977*2d1272b8SAndroid Build Coastguard Worker 
978*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_rmoveto:
979*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_hmoveto:
980*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_vmoveto:
981*2d1272b8SAndroid Build Coastguard Worker 	  drop.seen_moveto = true;
982*2d1272b8SAndroid Build Coastguard Worker 	  break;
983*2d1272b8SAndroid Build Coastguard Worker 
984*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_hintmask:
985*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_cntrmask:
986*2d1272b8SAndroid Build Coastguard Worker 	  if (drop.seen_moveto)
987*2d1272b8SAndroid Build Coastguard Worker 	  {
988*2d1272b8SAndroid Build Coastguard Worker 	    values[pos].set_hinting ();
989*2d1272b8SAndroid Build Coastguard Worker 	    break;
990*2d1272b8SAndroid Build Coastguard Worker 	  }
991*2d1272b8SAndroid Build Coastguard Worker 	  HB_FALLTHROUGH;
992*2d1272b8SAndroid Build Coastguard Worker 
993*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_hstemhm:
994*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_vstemhm:
995*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_hstem:
996*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_vstem:
997*2d1272b8SAndroid Build Coastguard Worker 	  has_hint = true;
998*2d1272b8SAndroid Build Coastguard Worker 	  values[pos].set_hinting ();
999*2d1272b8SAndroid Build Coastguard Worker 	  if (str.at_end (pos))
1000*2d1272b8SAndroid Build Coastguard Worker 	    drop.ends_in_hint = true;
1001*2d1272b8SAndroid Build Coastguard Worker 	  break;
1002*2d1272b8SAndroid Build Coastguard Worker 
1003*2d1272b8SAndroid Build Coastguard Worker 	case OpCode_dotsection:
1004*2d1272b8SAndroid Build Coastguard Worker 	  values[pos].set_hinting ();
1005*2d1272b8SAndroid Build Coastguard Worker 	  break;
1006*2d1272b8SAndroid Build Coastguard Worker 
1007*2d1272b8SAndroid Build Coastguard Worker 	default:
1008*2d1272b8SAndroid Build Coastguard Worker 	  /* NONE */
1009*2d1272b8SAndroid Build Coastguard Worker 	  break;
1010*2d1272b8SAndroid Build Coastguard Worker       }
1011*2d1272b8SAndroid Build Coastguard Worker       if (has_hint)
1012*2d1272b8SAndroid Build Coastguard Worker       {
1013*2d1272b8SAndroid Build Coastguard Worker 	for (int i = pos - 1; i >= 0; i--)
1014*2d1272b8SAndroid Build Coastguard Worker 	{
1015*2d1272b8SAndroid Build Coastguard Worker 	  parsed_cs_op_t  &csop = values[(unsigned)i];
1016*2d1272b8SAndroid Build Coastguard Worker 	  if (csop.is_hinting ())
1017*2d1272b8SAndroid Build Coastguard Worker 	    break;
1018*2d1272b8SAndroid Build Coastguard Worker 	  csop.set_hinting ();
1019*2d1272b8SAndroid Build Coastguard Worker 	  if (csop.op == OpCode_vsindexcs)
1020*2d1272b8SAndroid Build Coastguard Worker 	    drop.vsindex_dropped = true;
1021*2d1272b8SAndroid Build Coastguard Worker 	}
1022*2d1272b8SAndroid Build Coastguard Worker 	seen_hint |= has_hint;
1023*2d1272b8SAndroid Build Coastguard Worker       }
1024*2d1272b8SAndroid Build Coastguard Worker     }
1025*2d1272b8SAndroid Build Coastguard Worker 
1026*2d1272b8SAndroid Build Coastguard Worker     /* Raise all_dropped flag if all operators except return are dropped from a subr.
1027*2d1272b8SAndroid Build Coastguard Worker      * It may happen even after seeing the first moveto if a subr contains
1028*2d1272b8SAndroid Build Coastguard Worker      * only (usually one) hintmask operator, then calls to this subr can be dropped.
1029*2d1272b8SAndroid Build Coastguard Worker      */
1030*2d1272b8SAndroid Build Coastguard Worker     drop.all_dropped = true;
1031*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int pos = 0; pos < count; pos++)
1032*2d1272b8SAndroid Build Coastguard Worker     {
1033*2d1272b8SAndroid Build Coastguard Worker       parsed_cs_op_t  &csop = values[pos];
1034*2d1272b8SAndroid Build Coastguard Worker       if (csop.op == OpCode_return)
1035*2d1272b8SAndroid Build Coastguard Worker 	break;
1036*2d1272b8SAndroid Build Coastguard Worker       if (!csop.is_hinting ())
1037*2d1272b8SAndroid Build Coastguard Worker       {
1038*2d1272b8SAndroid Build Coastguard Worker 	drop.all_dropped = false;
1039*2d1272b8SAndroid Build Coastguard Worker 	break;
1040*2d1272b8SAndroid Build Coastguard Worker       }
1041*2d1272b8SAndroid Build Coastguard Worker     }
1042*2d1272b8SAndroid Build Coastguard Worker 
1043*2d1272b8SAndroid Build Coastguard Worker     return seen_hint;
1044*2d1272b8SAndroid Build Coastguard Worker   }
1045*2d1272b8SAndroid Build Coastguard Worker 
closure_subroutinesCFF::subr_subsetter_t1046*2d1272b8SAndroid Build Coastguard Worker   bool closure_subroutines (const parsed_cs_str_vec_t& global_subrs,
1047*2d1272b8SAndroid Build Coastguard Worker                             const hb_vector_t<parsed_cs_str_vec_t>& local_subrs)
1048*2d1272b8SAndroid Build Coastguard Worker   {
1049*2d1272b8SAndroid Build Coastguard Worker     closures.reset ();
1050*2d1272b8SAndroid Build Coastguard Worker     for (auto _ : plan->new_to_old_gid_list)
1051*2d1272b8SAndroid Build Coastguard Worker     {
1052*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t new_glyph = _.first;
1053*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t old_glyph = _.second;
1054*2d1272b8SAndroid Build Coastguard Worker       unsigned int fd = acc.fdSelect->get_fd (old_glyph);
1055*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (fd >= acc.fdCount))
1056*2d1272b8SAndroid Build Coastguard Worker         return false;
1057*2d1272b8SAndroid Build Coastguard Worker 
1058*2d1272b8SAndroid Build Coastguard Worker       // Note: const cast is safe here because the collect_subr_refs_in_str only performs a
1059*2d1272b8SAndroid Build Coastguard Worker       //       closure and does not modify any of the charstrings.
1060*2d1272b8SAndroid Build Coastguard Worker       subr_subset_param_t  param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (new_glyph)),
1061*2d1272b8SAndroid Build Coastguard Worker                                   const_cast<parsed_cs_str_vec_t*> (&global_subrs),
1062*2d1272b8SAndroid Build Coastguard Worker                                   const_cast<parsed_cs_str_vec_t*> (&local_subrs[fd]),
1063*2d1272b8SAndroid Build Coastguard Worker                                   &closures.global_closure,
1064*2d1272b8SAndroid Build Coastguard Worker                                   &closures.local_closures[fd],
1065*2d1272b8SAndroid Build Coastguard Worker                                   plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
1066*2d1272b8SAndroid Build Coastguard Worker       collect_subr_refs_in_str (get_parsed_charstring (new_glyph), param);
1067*2d1272b8SAndroid Build Coastguard Worker     }
1068*2d1272b8SAndroid Build Coastguard Worker 
1069*2d1272b8SAndroid Build Coastguard Worker     return true;
1070*2d1272b8SAndroid Build Coastguard Worker   }
1071*2d1272b8SAndroid Build Coastguard Worker 
collect_subr_refs_in_subrCFF::subr_subsetter_t1072*2d1272b8SAndroid Build Coastguard Worker   void collect_subr_refs_in_subr (unsigned int subr_num, parsed_cs_str_vec_t &subrs,
1073*2d1272b8SAndroid Build Coastguard Worker 				  hb_set_t *closure,
1074*2d1272b8SAndroid Build Coastguard Worker 				  const subr_subset_param_t &param)
1075*2d1272b8SAndroid Build Coastguard Worker   {
1076*2d1272b8SAndroid Build Coastguard Worker     if (closure->has (subr_num))
1077*2d1272b8SAndroid Build Coastguard Worker       return;
1078*2d1272b8SAndroid Build Coastguard Worker     closure->add (subr_num);
1079*2d1272b8SAndroid Build Coastguard Worker     collect_subr_refs_in_str (subrs[subr_num], param);
1080*2d1272b8SAndroid Build Coastguard Worker   }
1081*2d1272b8SAndroid Build Coastguard Worker 
collect_subr_refs_in_strCFF::subr_subsetter_t1082*2d1272b8SAndroid Build Coastguard Worker   void collect_subr_refs_in_str (const parsed_cs_str_t &str,
1083*2d1272b8SAndroid Build Coastguard Worker                                  const subr_subset_param_t &param)
1084*2d1272b8SAndroid Build Coastguard Worker   {
1085*2d1272b8SAndroid Build Coastguard Worker     if (!str.has_calls ())
1086*2d1272b8SAndroid Build Coastguard Worker       return;
1087*2d1272b8SAndroid Build Coastguard Worker 
1088*2d1272b8SAndroid Build Coastguard Worker     for (auto &opstr : str.values)
1089*2d1272b8SAndroid Build Coastguard Worker     {
1090*2d1272b8SAndroid Build Coastguard Worker       if (!param.drop_hints || !opstr.is_hinting ())
1091*2d1272b8SAndroid Build Coastguard Worker       {
1092*2d1272b8SAndroid Build Coastguard Worker 	switch (opstr.op)
1093*2d1272b8SAndroid Build Coastguard Worker 	{
1094*2d1272b8SAndroid Build Coastguard Worker 	  case OpCode_callsubr:
1095*2d1272b8SAndroid Build Coastguard Worker 	    collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_local_subrs,
1096*2d1272b8SAndroid Build Coastguard Worker 				       param.local_closure, param);
1097*2d1272b8SAndroid Build Coastguard Worker 	    break;
1098*2d1272b8SAndroid Build Coastguard Worker 
1099*2d1272b8SAndroid Build Coastguard Worker 	  case OpCode_callgsubr:
1100*2d1272b8SAndroid Build Coastguard Worker 	    collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_global_subrs,
1101*2d1272b8SAndroid Build Coastguard Worker 				       param.global_closure, param);
1102*2d1272b8SAndroid Build Coastguard Worker 	    break;
1103*2d1272b8SAndroid Build Coastguard Worker 
1104*2d1272b8SAndroid Build Coastguard Worker 	  default: break;
1105*2d1272b8SAndroid Build Coastguard Worker 	}
1106*2d1272b8SAndroid Build Coastguard Worker       }
1107*2d1272b8SAndroid Build Coastguard Worker     }
1108*2d1272b8SAndroid Build Coastguard Worker   }
1109*2d1272b8SAndroid Build Coastguard Worker 
encode_strCFF::subr_subsetter_t1110*2d1272b8SAndroid Build Coastguard Worker   bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff, bool encode_prefix = true) const
1111*2d1272b8SAndroid Build Coastguard Worker   {
1112*2d1272b8SAndroid Build Coastguard Worker     str_encoder_t  encoder (buff);
1113*2d1272b8SAndroid Build Coastguard Worker     encoder.reset ();
1114*2d1272b8SAndroid Build Coastguard Worker     bool hinting = !(plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
1115*2d1272b8SAndroid Build Coastguard Worker     /* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
1116*2d1272b8SAndroid Build Coastguard Worker      * re-insert it at the beginning of charstreing */
1117*2d1272b8SAndroid Build Coastguard Worker     if (encode_prefix && str.has_prefix () && !hinting && str.is_hint_dropped ())
1118*2d1272b8SAndroid Build Coastguard Worker     {
1119*2d1272b8SAndroid Build Coastguard Worker       encoder.encode_num_cs (str.prefix_num ());
1120*2d1272b8SAndroid Build Coastguard Worker       if (str.prefix_op () != OpCode_Invalid)
1121*2d1272b8SAndroid Build Coastguard Worker 	encoder.encode_op (str.prefix_op ());
1122*2d1272b8SAndroid Build Coastguard Worker     }
1123*2d1272b8SAndroid Build Coastguard Worker 
1124*2d1272b8SAndroid Build Coastguard Worker     unsigned size = 0;
1125*2d1272b8SAndroid Build Coastguard Worker     for (auto &opstr : str.values)
1126*2d1272b8SAndroid Build Coastguard Worker     {
1127*2d1272b8SAndroid Build Coastguard Worker       size += opstr.length;
1128*2d1272b8SAndroid Build Coastguard Worker       if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr)
1129*2d1272b8SAndroid Build Coastguard Worker         size += 3;
1130*2d1272b8SAndroid Build Coastguard Worker     }
1131*2d1272b8SAndroid Build Coastguard Worker     if (!buff.alloc (buff.length + size, true))
1132*2d1272b8SAndroid Build Coastguard Worker       return false;
1133*2d1272b8SAndroid Build Coastguard Worker 
1134*2d1272b8SAndroid Build Coastguard Worker     for (auto &opstr : str.values)
1135*2d1272b8SAndroid Build Coastguard Worker     {
1136*2d1272b8SAndroid Build Coastguard Worker       if (hinting || !opstr.is_hinting ())
1137*2d1272b8SAndroid Build Coastguard Worker       {
1138*2d1272b8SAndroid Build Coastguard Worker 	switch (opstr.op)
1139*2d1272b8SAndroid Build Coastguard Worker 	{
1140*2d1272b8SAndroid Build Coastguard Worker 	  case OpCode_callsubr:
1141*2d1272b8SAndroid Build Coastguard Worker 	    encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num));
1142*2d1272b8SAndroid Build Coastguard Worker 	    encoder.copy_str (opstr.ptr, opstr.length);
1143*2d1272b8SAndroid Build Coastguard Worker 	    break;
1144*2d1272b8SAndroid Build Coastguard Worker 
1145*2d1272b8SAndroid Build Coastguard Worker 	  case OpCode_callgsubr:
1146*2d1272b8SAndroid Build Coastguard Worker 	    encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num));
1147*2d1272b8SAndroid Build Coastguard Worker 	    encoder.copy_str (opstr.ptr, opstr.length);
1148*2d1272b8SAndroid Build Coastguard Worker 	    break;
1149*2d1272b8SAndroid Build Coastguard Worker 
1150*2d1272b8SAndroid Build Coastguard Worker 	  default:
1151*2d1272b8SAndroid Build Coastguard Worker 	    encoder.copy_str (opstr.ptr, opstr.length);
1152*2d1272b8SAndroid Build Coastguard Worker 	    break;
1153*2d1272b8SAndroid Build Coastguard Worker 	}
1154*2d1272b8SAndroid Build Coastguard Worker       }
1155*2d1272b8SAndroid Build Coastguard Worker     }
1156*2d1272b8SAndroid Build Coastguard Worker     return !encoder.in_error ();
1157*2d1272b8SAndroid Build Coastguard Worker   }
1158*2d1272b8SAndroid Build Coastguard Worker 
compact_parsed_subrsCFF::subr_subsetter_t1159*2d1272b8SAndroid Build Coastguard Worker   void compact_parsed_subrs () const
1160*2d1272b8SAndroid Build Coastguard Worker   {
1161*2d1272b8SAndroid Build Coastguard Worker     for (auto &cs : parsed_global_subrs_storage)
1162*2d1272b8SAndroid Build Coastguard Worker       cs.compact ();
1163*2d1272b8SAndroid Build Coastguard Worker     for (auto &vec : parsed_local_subrs_storage)
1164*2d1272b8SAndroid Build Coastguard Worker       for (auto &cs : vec)
1165*2d1272b8SAndroid Build Coastguard Worker 	cs.compact ();
1166*2d1272b8SAndroid Build Coastguard Worker   }
1167*2d1272b8SAndroid Build Coastguard Worker 
populate_subset_acceleratorCFF::subr_subsetter_t1168*2d1272b8SAndroid Build Coastguard Worker   void populate_subset_accelerator () const
1169*2d1272b8SAndroid Build Coastguard Worker   {
1170*2d1272b8SAndroid Build Coastguard Worker     if (!plan->inprogress_accelerator) return;
1171*2d1272b8SAndroid Build Coastguard Worker 
1172*2d1272b8SAndroid Build Coastguard Worker     compact_parsed_subrs ();
1173*2d1272b8SAndroid Build Coastguard Worker 
1174*2d1272b8SAndroid Build Coastguard Worker     acc.cff_accelerator =
1175*2d1272b8SAndroid Build Coastguard Worker         cff_subset_accelerator_t::create(acc.blob,
1176*2d1272b8SAndroid Build Coastguard Worker                                          parsed_charstrings,
1177*2d1272b8SAndroid Build Coastguard Worker                                          parsed_global_subrs_storage,
1178*2d1272b8SAndroid Build Coastguard Worker                                          parsed_local_subrs_storage);
1179*2d1272b8SAndroid Build Coastguard Worker   }
1180*2d1272b8SAndroid Build Coastguard Worker 
get_parsed_charstringCFF::subr_subsetter_t1181*2d1272b8SAndroid Build Coastguard Worker   const parsed_cs_str_t& get_parsed_charstring (unsigned i) const
1182*2d1272b8SAndroid Build Coastguard Worker   {
1183*2d1272b8SAndroid Build Coastguard Worker     if (cached_charstrings) return *(cached_charstrings[i]);
1184*2d1272b8SAndroid Build Coastguard Worker     return parsed_charstrings[i];
1185*2d1272b8SAndroid Build Coastguard Worker   }
1186*2d1272b8SAndroid Build Coastguard Worker 
1187*2d1272b8SAndroid Build Coastguard Worker   protected:
1188*2d1272b8SAndroid Build Coastguard Worker   const ACC			&acc;
1189*2d1272b8SAndroid Build Coastguard Worker   const hb_subset_plan_t	*plan;
1190*2d1272b8SAndroid Build Coastguard Worker 
1191*2d1272b8SAndroid Build Coastguard Worker   subr_closures_t		closures;
1192*2d1272b8SAndroid Build Coastguard Worker 
1193*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<const parsed_cs_str_t*>     cached_charstrings;
1194*2d1272b8SAndroid Build Coastguard Worker   const parsed_cs_str_vec_t*              parsed_global_subrs;
1195*2d1272b8SAndroid Build Coastguard Worker   const hb_vector_t<parsed_cs_str_vec_t>* parsed_local_subrs;
1196*2d1272b8SAndroid Build Coastguard Worker 
1197*2d1272b8SAndroid Build Coastguard Worker   subr_remaps_t			remaps;
1198*2d1272b8SAndroid Build Coastguard Worker 
1199*2d1272b8SAndroid Build Coastguard Worker   private:
1200*2d1272b8SAndroid Build Coastguard Worker 
1201*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_vec_t		parsed_charstrings;
1202*2d1272b8SAndroid Build Coastguard Worker   parsed_cs_str_vec_t		parsed_global_subrs_storage;
1203*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<parsed_cs_str_vec_t>  parsed_local_subrs_storage;
1204*2d1272b8SAndroid Build Coastguard Worker   typedef typename SUBRS::count_type subr_count_type;
1205*2d1272b8SAndroid Build Coastguard Worker };
1206*2d1272b8SAndroid Build Coastguard Worker 
1207*2d1272b8SAndroid Build Coastguard Worker } /* namespace CFF */
1208*2d1272b8SAndroid Build Coastguard Worker 
1209*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool
1210*2d1272b8SAndroid Build Coastguard Worker hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
1211*2d1272b8SAndroid Build Coastguard Worker 			    unsigned int fdCount,
1212*2d1272b8SAndroid Build Coastguard Worker 			    const CFF::FDSelect &src, /* IN */
1213*2d1272b8SAndroid Build Coastguard Worker 			    unsigned int &subset_fd_count /* OUT */,
1214*2d1272b8SAndroid Build Coastguard Worker 			    unsigned int &subset_fdselect_size /* OUT */,
1215*2d1272b8SAndroid Build Coastguard Worker 			    unsigned int &subset_fdselect_format /* OUT */,
1216*2d1272b8SAndroid Build Coastguard Worker 			    hb_vector_t<CFF::code_pair_t> &fdselect_ranges /* OUT */,
1217*2d1272b8SAndroid Build Coastguard Worker 			    hb_inc_bimap_t &fdmap /* OUT */);
1218*2d1272b8SAndroid Build Coastguard Worker 
1219*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool
1220*2d1272b8SAndroid Build Coastguard Worker hb_serialize_cff_fdselect (hb_serialize_context_t *c,
1221*2d1272b8SAndroid Build Coastguard Worker 			  unsigned int num_glyphs,
1222*2d1272b8SAndroid Build Coastguard Worker 			  const CFF::FDSelect &src,
1223*2d1272b8SAndroid Build Coastguard Worker 			  unsigned int fd_count,
1224*2d1272b8SAndroid Build Coastguard Worker 			  unsigned int fdselect_format,
1225*2d1272b8SAndroid Build Coastguard Worker 			  unsigned int size,
1226*2d1272b8SAndroid Build Coastguard Worker 			  const hb_vector_t<CFF::code_pair_t> &fdselect_ranges);
1227*2d1272b8SAndroid Build Coastguard Worker 
1228*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_SUBSET_CFF_COMMON_HH */
1229