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