xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-subset-plan.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2018  Google, 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  * Google Author(s): Garret Rieger, Roderick Sheeter
25*2d1272b8SAndroid Build Coastguard Worker  */
26*2d1272b8SAndroid Build Coastguard Worker 
27*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-plan.hh"
28*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-accelerator.hh"
29*2d1272b8SAndroid Build Coastguard Worker #include "hb-map.hh"
30*2d1272b8SAndroid Build Coastguard Worker #include "hb-multimap.hh"
31*2d1272b8SAndroid Build Coastguard Worker #include "hb-set.hh"
32*2d1272b8SAndroid Build Coastguard Worker 
33*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-cmap-table.hh"
34*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-glyf-table.hh"
35*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-layout-base-table.hh"
36*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-layout-gdef-table.hh"
37*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-layout-gpos-table.hh"
38*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-layout-gsub-table.hh"
39*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-cff1-table.hh"
40*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-cff2-table.hh"
41*2d1272b8SAndroid Build Coastguard Worker #include "OT/Color/COLR/COLR.hh"
42*2d1272b8SAndroid Build Coastguard Worker #include "OT/Color/COLR/colrv1-closure.hh"
43*2d1272b8SAndroid Build Coastguard Worker #include "OT/Color/CPAL/CPAL.hh"
44*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-var-fvar-table.hh"
45*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-var-avar-table.hh"
46*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-stat-table.hh"
47*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-math-table.hh"
48*2d1272b8SAndroid Build Coastguard Worker 
49*2d1272b8SAndroid Build Coastguard Worker using OT::Layout::GSUB;
50*2d1272b8SAndroid Build Coastguard Worker using OT::Layout::GPOS;
51*2d1272b8SAndroid Build Coastguard Worker 
52*2d1272b8SAndroid Build Coastguard Worker 
~hb_subset_accelerator_t()53*2d1272b8SAndroid Build Coastguard Worker hb_subset_accelerator_t::~hb_subset_accelerator_t ()
54*2d1272b8SAndroid Build Coastguard Worker {
55*2d1272b8SAndroid Build Coastguard Worker   if (cmap_cache && destroy_cmap_cache)
56*2d1272b8SAndroid Build Coastguard Worker     destroy_cmap_cache ((void*) cmap_cache);
57*2d1272b8SAndroid Build Coastguard Worker 
58*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_CFF
59*2d1272b8SAndroid Build Coastguard Worker   cff1_accel.fini ();
60*2d1272b8SAndroid Build Coastguard Worker   cff2_accel.fini ();
61*2d1272b8SAndroid Build Coastguard Worker #endif
62*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (source);
63*2d1272b8SAndroid Build Coastguard Worker }
64*2d1272b8SAndroid Build Coastguard Worker 
65*2d1272b8SAndroid Build Coastguard Worker 
66*2d1272b8SAndroid Build Coastguard Worker typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
67*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_CFF
68*2d1272b8SAndroid Build Coastguard Worker static inline bool
_add_cff_seac_components(const OT::cff1::accelerator_subset_t & cff,hb_codepoint_t gid,hb_set_t * gids_to_retain)69*2d1272b8SAndroid Build Coastguard Worker _add_cff_seac_components (const OT::cff1::accelerator_subset_t &cff,
70*2d1272b8SAndroid Build Coastguard Worker 			  hb_codepoint_t gid,
71*2d1272b8SAndroid Build Coastguard Worker 			  hb_set_t *gids_to_retain)
72*2d1272b8SAndroid Build Coastguard Worker {
73*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t base_gid, accent_gid;
74*2d1272b8SAndroid Build Coastguard Worker   if (cff.get_seac_components (gid, &base_gid, &accent_gid))
75*2d1272b8SAndroid Build Coastguard Worker   {
76*2d1272b8SAndroid Build Coastguard Worker     gids_to_retain->add (base_gid);
77*2d1272b8SAndroid Build Coastguard Worker     gids_to_retain->add (accent_gid);
78*2d1272b8SAndroid Build Coastguard Worker     return true;
79*2d1272b8SAndroid Build Coastguard Worker   }
80*2d1272b8SAndroid Build Coastguard Worker   return false;
81*2d1272b8SAndroid Build Coastguard Worker }
82*2d1272b8SAndroid Build Coastguard Worker #endif
83*2d1272b8SAndroid Build Coastguard Worker 
84*2d1272b8SAndroid Build Coastguard Worker static void
_remap_palette_indexes(const hb_set_t * palette_indexes,hb_map_t * mapping)85*2d1272b8SAndroid Build Coastguard Worker _remap_palette_indexes (const hb_set_t *palette_indexes,
86*2d1272b8SAndroid Build Coastguard Worker 			hb_map_t       *mapping /* OUT */)
87*2d1272b8SAndroid Build Coastguard Worker {
88*2d1272b8SAndroid Build Coastguard Worker   unsigned new_idx = 0;
89*2d1272b8SAndroid Build Coastguard Worker   for (unsigned palette_index : palette_indexes->iter ())
90*2d1272b8SAndroid Build Coastguard Worker   {
91*2d1272b8SAndroid Build Coastguard Worker     if (palette_index == 0xFFFF)
92*2d1272b8SAndroid Build Coastguard Worker     {
93*2d1272b8SAndroid Build Coastguard Worker       mapping->set (palette_index, palette_index);
94*2d1272b8SAndroid Build Coastguard Worker       continue;
95*2d1272b8SAndroid Build Coastguard Worker     }
96*2d1272b8SAndroid Build Coastguard Worker     mapping->set (palette_index, new_idx);
97*2d1272b8SAndroid Build Coastguard Worker     new_idx++;
98*2d1272b8SAndroid Build Coastguard Worker   }
99*2d1272b8SAndroid Build Coastguard Worker }
100*2d1272b8SAndroid Build Coastguard Worker 
101*2d1272b8SAndroid Build Coastguard Worker static void
_remap_indexes(const hb_set_t * indexes,hb_map_t * mapping)102*2d1272b8SAndroid Build Coastguard Worker _remap_indexes (const hb_set_t *indexes,
103*2d1272b8SAndroid Build Coastguard Worker 		hb_map_t       *mapping /* OUT */)
104*2d1272b8SAndroid Build Coastguard Worker {
105*2d1272b8SAndroid Build Coastguard Worker   for (auto _ : + hb_enumerate (indexes->iter ()))
106*2d1272b8SAndroid Build Coastguard Worker     mapping->set (_.second, _.first);
107*2d1272b8SAndroid Build Coastguard Worker 
108*2d1272b8SAndroid Build Coastguard Worker }
109*2d1272b8SAndroid Build Coastguard Worker 
110*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_LAYOUT
111*2d1272b8SAndroid Build Coastguard Worker 
112*2d1272b8SAndroid Build Coastguard Worker /*
113*2d1272b8SAndroid Build Coastguard Worker  * Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates.
114*2d1272b8SAndroid Build Coastguard Worker  * Returns true if anything was removed (not including duplicates).
115*2d1272b8SAndroid Build Coastguard Worker  */
_filter_tag_list(hb_vector_t<hb_tag_t> * tags,const hb_set_t * filter)116*2d1272b8SAndroid Build Coastguard Worker static bool _filter_tag_list(hb_vector_t<hb_tag_t>* tags, /* IN/OUT */
117*2d1272b8SAndroid Build Coastguard Worker                              const hb_set_t* filter)
118*2d1272b8SAndroid Build Coastguard Worker {
119*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<hb_tag_t> out;
120*2d1272b8SAndroid Build Coastguard Worker   out.alloc (tags->get_size() + 1); // +1 is to allocate room for the null terminator.
121*2d1272b8SAndroid Build Coastguard Worker 
122*2d1272b8SAndroid Build Coastguard Worker   bool removed = false;
123*2d1272b8SAndroid Build Coastguard Worker   hb_set_t visited;
124*2d1272b8SAndroid Build Coastguard Worker 
125*2d1272b8SAndroid Build Coastguard Worker   for (hb_tag_t tag : *tags)
126*2d1272b8SAndroid Build Coastguard Worker   {
127*2d1272b8SAndroid Build Coastguard Worker     if (!tag) continue;
128*2d1272b8SAndroid Build Coastguard Worker     if (visited.has (tag)) continue;
129*2d1272b8SAndroid Build Coastguard Worker 
130*2d1272b8SAndroid Build Coastguard Worker     if (!filter->has (tag))
131*2d1272b8SAndroid Build Coastguard Worker     {
132*2d1272b8SAndroid Build Coastguard Worker       removed = true;
133*2d1272b8SAndroid Build Coastguard Worker       continue;
134*2d1272b8SAndroid Build Coastguard Worker     }
135*2d1272b8SAndroid Build Coastguard Worker 
136*2d1272b8SAndroid Build Coastguard Worker     visited.add (tag);
137*2d1272b8SAndroid Build Coastguard Worker     out.push (tag);
138*2d1272b8SAndroid Build Coastguard Worker   }
139*2d1272b8SAndroid Build Coastguard Worker 
140*2d1272b8SAndroid Build Coastguard Worker   // The collect function needs a null element to signal end of the array.
141*2d1272b8SAndroid Build Coastguard Worker   out.push (HB_TAG_NONE);
142*2d1272b8SAndroid Build Coastguard Worker 
143*2d1272b8SAndroid Build Coastguard Worker   hb_swap (out, *tags);
144*2d1272b8SAndroid Build Coastguard Worker   return removed;
145*2d1272b8SAndroid Build Coastguard Worker }
146*2d1272b8SAndroid Build Coastguard Worker 
147*2d1272b8SAndroid Build Coastguard Worker template <typename T>
_collect_layout_indices(hb_subset_plan_t * plan,const T & table,hb_set_t * lookup_indices,hb_set_t * feature_indices,hb_hashmap_t<unsigned,hb::shared_ptr<hb_set_t>> * feature_record_cond_idx_map,hb_hashmap_t<unsigned,const OT::Feature * > * feature_substitutes_map,hb_set_t & catch_all_record_feature_idxes,hb_hashmap_t<unsigned,hb_pair_t<const void *,const void * >> & catch_all_record_idx_feature_map)148*2d1272b8SAndroid Build Coastguard Worker static void _collect_layout_indices (hb_subset_plan_t     *plan,
149*2d1272b8SAndroid Build Coastguard Worker                                      const T&              table,
150*2d1272b8SAndroid Build Coastguard Worker                                      hb_set_t		  *lookup_indices, /* OUT */
151*2d1272b8SAndroid Build Coastguard Worker                                      hb_set_t		  *feature_indices, /* OUT */
152*2d1272b8SAndroid Build Coastguard Worker                                      hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */
153*2d1272b8SAndroid Build Coastguard Worker                                      hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, /* OUT */
154*2d1272b8SAndroid Build Coastguard Worker                                      hb_set_t& catch_all_record_feature_idxes, /* OUT */
155*2d1272b8SAndroid Build Coastguard Worker                                      hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>>& catch_all_record_idx_feature_map /* OUT */)
156*2d1272b8SAndroid Build Coastguard Worker {
157*2d1272b8SAndroid Build Coastguard Worker   unsigned num_features = table.get_feature_count ();
158*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<hb_tag_t> features;
159*2d1272b8SAndroid Build Coastguard Worker   if (!plan->check_success (features.resize (num_features))) return;
160*2d1272b8SAndroid Build Coastguard Worker   table.get_feature_tags (0, &num_features, features.arrayZ);
161*2d1272b8SAndroid Build Coastguard Worker   bool retain_all_features = !_filter_tag_list (&features, &plan->layout_features);
162*2d1272b8SAndroid Build Coastguard Worker 
163*2d1272b8SAndroid Build Coastguard Worker   unsigned num_scripts = table.get_script_count ();
164*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<hb_tag_t> scripts;
165*2d1272b8SAndroid Build Coastguard Worker   if (!plan->check_success (scripts.resize (num_scripts))) return;
166*2d1272b8SAndroid Build Coastguard Worker   table.get_script_tags (0, &num_scripts, scripts.arrayZ);
167*2d1272b8SAndroid Build Coastguard Worker   bool retain_all_scripts = !_filter_tag_list (&scripts, &plan->layout_scripts);
168*2d1272b8SAndroid Build Coastguard Worker 
169*2d1272b8SAndroid Build Coastguard Worker   if (!plan->check_success (!features.in_error ()) || !features
170*2d1272b8SAndroid Build Coastguard Worker       || !plan->check_success (!scripts.in_error ()) || !scripts)
171*2d1272b8SAndroid Build Coastguard Worker     return;
172*2d1272b8SAndroid Build Coastguard Worker 
173*2d1272b8SAndroid Build Coastguard Worker   hb_ot_layout_collect_features (plan->source,
174*2d1272b8SAndroid Build Coastguard Worker                                  T::tableTag,
175*2d1272b8SAndroid Build Coastguard Worker                                  retain_all_scripts ? nullptr : scripts.arrayZ,
176*2d1272b8SAndroid Build Coastguard Worker                                  nullptr,
177*2d1272b8SAndroid Build Coastguard Worker                                  retain_all_features ? nullptr : features.arrayZ,
178*2d1272b8SAndroid Build Coastguard Worker                                  feature_indices);
179*2d1272b8SAndroid Build Coastguard Worker 
180*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
181*2d1272b8SAndroid Build Coastguard Worker   // collect feature substitutes with variations
182*2d1272b8SAndroid Build Coastguard Worker   if (!plan->user_axes_location.is_empty ())
183*2d1272b8SAndroid Build Coastguard Worker   {
184*2d1272b8SAndroid Build Coastguard Worker     hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> conditionset_map;
185*2d1272b8SAndroid Build Coastguard Worker     OT::hb_collect_feature_substitutes_with_var_context_t c =
186*2d1272b8SAndroid Build Coastguard Worker     {
187*2d1272b8SAndroid Build Coastguard Worker       &plan->axes_old_index_tag_map,
188*2d1272b8SAndroid Build Coastguard Worker       &plan->axes_location,
189*2d1272b8SAndroid Build Coastguard Worker       feature_record_cond_idx_map,
190*2d1272b8SAndroid Build Coastguard Worker       feature_substitutes_map,
191*2d1272b8SAndroid Build Coastguard Worker       catch_all_record_feature_idxes,
192*2d1272b8SAndroid Build Coastguard Worker       feature_indices,
193*2d1272b8SAndroid Build Coastguard Worker       false,
194*2d1272b8SAndroid Build Coastguard Worker       false,
195*2d1272b8SAndroid Build Coastguard Worker       false,
196*2d1272b8SAndroid Build Coastguard Worker       0,
197*2d1272b8SAndroid Build Coastguard Worker       &conditionset_map
198*2d1272b8SAndroid Build Coastguard Worker     };
199*2d1272b8SAndroid Build Coastguard Worker     table.collect_feature_substitutes_with_variations (&c);
200*2d1272b8SAndroid Build Coastguard Worker   }
201*2d1272b8SAndroid Build Coastguard Worker #endif
202*2d1272b8SAndroid Build Coastguard Worker 
203*2d1272b8SAndroid Build Coastguard Worker   for (unsigned feature_index : *feature_indices)
204*2d1272b8SAndroid Build Coastguard Worker   {
205*2d1272b8SAndroid Build Coastguard Worker     const OT::Feature* f = &(table.get_feature (feature_index));
206*2d1272b8SAndroid Build Coastguard Worker     const OT::Feature **p = nullptr;
207*2d1272b8SAndroid Build Coastguard Worker     if (feature_substitutes_map->has (feature_index, &p))
208*2d1272b8SAndroid Build Coastguard Worker       f = *p;
209*2d1272b8SAndroid Build Coastguard Worker 
210*2d1272b8SAndroid Build Coastguard Worker     f->add_lookup_indexes_to (lookup_indices);
211*2d1272b8SAndroid Build Coastguard Worker   }
212*2d1272b8SAndroid Build Coastguard Worker 
213*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
214*2d1272b8SAndroid Build Coastguard Worker   if (catch_all_record_feature_idxes)
215*2d1272b8SAndroid Build Coastguard Worker   {
216*2d1272b8SAndroid Build Coastguard Worker     for (unsigned feature_index : catch_all_record_feature_idxes)
217*2d1272b8SAndroid Build Coastguard Worker     {
218*2d1272b8SAndroid Build Coastguard Worker       const OT::Feature& f = table.get_feature (feature_index);
219*2d1272b8SAndroid Build Coastguard Worker       f.add_lookup_indexes_to (lookup_indices);
220*2d1272b8SAndroid Build Coastguard Worker       const void *tag = reinterpret_cast<const void*> (&(table.get_feature_list ().get_tag (feature_index)));
221*2d1272b8SAndroid Build Coastguard Worker       catch_all_record_idx_feature_map.set (feature_index, hb_pair (&f, tag));
222*2d1272b8SAndroid Build Coastguard Worker     }
223*2d1272b8SAndroid Build Coastguard Worker   }
224*2d1272b8SAndroid Build Coastguard Worker 
225*2d1272b8SAndroid Build Coastguard Worker   // If all axes are pinned then all feature variations will be dropped so there's no need
226*2d1272b8SAndroid Build Coastguard Worker   // to collect lookups from them.
227*2d1272b8SAndroid Build Coastguard Worker   if (!plan->all_axes_pinned)
228*2d1272b8SAndroid Build Coastguard Worker     table.feature_variation_collect_lookups (feature_indices,
229*2d1272b8SAndroid Build Coastguard Worker                                              plan->user_axes_location.is_empty () ? nullptr: feature_record_cond_idx_map,
230*2d1272b8SAndroid Build Coastguard Worker                                              lookup_indices);
231*2d1272b8SAndroid Build Coastguard Worker #endif
232*2d1272b8SAndroid Build Coastguard Worker }
233*2d1272b8SAndroid Build Coastguard Worker 
234*2d1272b8SAndroid Build Coastguard Worker 
235*2d1272b8SAndroid Build Coastguard Worker static inline void
_GSUBGPOS_find_duplicate_features(const OT::GSUBGPOS & g,const hb_map_t * lookup_indices,const hb_set_t * feature_indices,const hb_hashmap_t<unsigned,const OT::Feature * > * feature_substitutes_map,hb_map_t * duplicate_feature_map)236*2d1272b8SAndroid Build Coastguard Worker _GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
237*2d1272b8SAndroid Build Coastguard Worker 				   const hb_map_t *lookup_indices,
238*2d1272b8SAndroid Build Coastguard Worker 				   const hb_set_t *feature_indices,
239*2d1272b8SAndroid Build Coastguard Worker 				   const hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
240*2d1272b8SAndroid Build Coastguard Worker 				   hb_map_t *duplicate_feature_map /* OUT */)
241*2d1272b8SAndroid Build Coastguard Worker {
242*2d1272b8SAndroid Build Coastguard Worker   if (feature_indices->is_empty ()) return;
243*2d1272b8SAndroid Build Coastguard Worker   hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features;
244*2d1272b8SAndroid Build Coastguard Worker   //find out duplicate features after subset
245*2d1272b8SAndroid Build Coastguard Worker   for (unsigned i : feature_indices->iter ())
246*2d1272b8SAndroid Build Coastguard Worker   {
247*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t t = g.get_feature_tag (i);
248*2d1272b8SAndroid Build Coastguard Worker     if (t == HB_MAP_VALUE_INVALID) continue;
249*2d1272b8SAndroid Build Coastguard Worker     if (!unique_features.has (t))
250*2d1272b8SAndroid Build Coastguard Worker     {
251*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
252*2d1272b8SAndroid Build Coastguard Worker 	return;
253*2d1272b8SAndroid Build Coastguard Worker       if (unique_features.has (t))
254*2d1272b8SAndroid Build Coastguard Worker 	unique_features.get (t)->add (i);
255*2d1272b8SAndroid Build Coastguard Worker       duplicate_feature_map->set (i, i);
256*2d1272b8SAndroid Build Coastguard Worker       continue;
257*2d1272b8SAndroid Build Coastguard Worker     }
258*2d1272b8SAndroid Build Coastguard Worker 
259*2d1272b8SAndroid Build Coastguard Worker     bool found = false;
260*2d1272b8SAndroid Build Coastguard Worker 
261*2d1272b8SAndroid Build Coastguard Worker     hb_set_t* same_tag_features = unique_features.get (t);
262*2d1272b8SAndroid Build Coastguard Worker     for (unsigned other_f_index : same_tag_features->iter ())
263*2d1272b8SAndroid Build Coastguard Worker     {
264*2d1272b8SAndroid Build Coastguard Worker       const OT::Feature* f = &(g.get_feature (i));
265*2d1272b8SAndroid Build Coastguard Worker       const OT::Feature **p = nullptr;
266*2d1272b8SAndroid Build Coastguard Worker       if (feature_substitutes_map->has (i, &p))
267*2d1272b8SAndroid Build Coastguard Worker         f = *p;
268*2d1272b8SAndroid Build Coastguard Worker 
269*2d1272b8SAndroid Build Coastguard Worker       const OT::Feature* other_f = &(g.get_feature (other_f_index));
270*2d1272b8SAndroid Build Coastguard Worker       if (feature_substitutes_map->has (other_f_index, &p))
271*2d1272b8SAndroid Build Coastguard Worker         other_f = *p;
272*2d1272b8SAndroid Build Coastguard Worker 
273*2d1272b8SAndroid Build Coastguard Worker       auto f_iter =
274*2d1272b8SAndroid Build Coastguard Worker       + hb_iter (f->lookupIndex)
275*2d1272b8SAndroid Build Coastguard Worker       | hb_filter (lookup_indices)
276*2d1272b8SAndroid Build Coastguard Worker       ;
277*2d1272b8SAndroid Build Coastguard Worker 
278*2d1272b8SAndroid Build Coastguard Worker       auto other_f_iter =
279*2d1272b8SAndroid Build Coastguard Worker       + hb_iter (other_f->lookupIndex)
280*2d1272b8SAndroid Build Coastguard Worker       | hb_filter (lookup_indices)
281*2d1272b8SAndroid Build Coastguard Worker       ;
282*2d1272b8SAndroid Build Coastguard Worker 
283*2d1272b8SAndroid Build Coastguard Worker       bool is_equal = true;
284*2d1272b8SAndroid Build Coastguard Worker       for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
285*2d1272b8SAndroid Build Coastguard Worker       {
286*2d1272b8SAndroid Build Coastguard Worker 	unsigned a = *f_iter;
287*2d1272b8SAndroid Build Coastguard Worker 	unsigned b = *other_f_iter;
288*2d1272b8SAndroid Build Coastguard Worker 	if (a != b) { is_equal = false; break; }
289*2d1272b8SAndroid Build Coastguard Worker       }
290*2d1272b8SAndroid Build Coastguard Worker 
291*2d1272b8SAndroid Build Coastguard Worker       if (is_equal == false || f_iter || other_f_iter) continue;
292*2d1272b8SAndroid Build Coastguard Worker 
293*2d1272b8SAndroid Build Coastguard Worker       found = true;
294*2d1272b8SAndroid Build Coastguard Worker       duplicate_feature_map->set (i, other_f_index);
295*2d1272b8SAndroid Build Coastguard Worker       break;
296*2d1272b8SAndroid Build Coastguard Worker     }
297*2d1272b8SAndroid Build Coastguard Worker 
298*2d1272b8SAndroid Build Coastguard Worker     if (found == false)
299*2d1272b8SAndroid Build Coastguard Worker     {
300*2d1272b8SAndroid Build Coastguard Worker       same_tag_features->add (i);
301*2d1272b8SAndroid Build Coastguard Worker       duplicate_feature_map->set (i, i);
302*2d1272b8SAndroid Build Coastguard Worker     }
303*2d1272b8SAndroid Build Coastguard Worker   }
304*2d1272b8SAndroid Build Coastguard Worker }
305*2d1272b8SAndroid Build Coastguard Worker 
306*2d1272b8SAndroid Build Coastguard Worker template <typename T>
307*2d1272b8SAndroid Build Coastguard Worker static inline void
_closure_glyphs_lookups_features(hb_subset_plan_t * plan,hb_set_t * gids_to_retain,hb_map_t * lookups,hb_map_t * features,script_langsys_map * langsys_map,hb_hashmap_t<unsigned,hb::shared_ptr<hb_set_t>> * feature_record_cond_idx_map,hb_hashmap_t<unsigned,const OT::Feature * > * feature_substitutes_map,hb_set_t & catch_all_record_feature_idxes,hb_hashmap_t<unsigned,hb_pair_t<const void *,const void * >> & catch_all_record_idx_feature_map)308*2d1272b8SAndroid Build Coastguard Worker _closure_glyphs_lookups_features (hb_subset_plan_t   *plan,
309*2d1272b8SAndroid Build Coastguard Worker 				  hb_set_t	     *gids_to_retain,
310*2d1272b8SAndroid Build Coastguard Worker 				  hb_map_t	     *lookups,
311*2d1272b8SAndroid Build Coastguard Worker 				  hb_map_t	     *features,
312*2d1272b8SAndroid Build Coastguard Worker 				  script_langsys_map *langsys_map,
313*2d1272b8SAndroid Build Coastguard Worker 				  hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
314*2d1272b8SAndroid Build Coastguard Worker 				  hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
315*2d1272b8SAndroid Build Coastguard Worker                                   hb_set_t &catch_all_record_feature_idxes,
316*2d1272b8SAndroid Build Coastguard Worker                                   hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>>& catch_all_record_idx_feature_map)
317*2d1272b8SAndroid Build Coastguard Worker {
318*2d1272b8SAndroid Build Coastguard Worker   hb_blob_ptr_t<T> table = plan->source_table<T> ();
319*2d1272b8SAndroid Build Coastguard Worker   hb_tag_t table_tag = table->tableTag;
320*2d1272b8SAndroid Build Coastguard Worker   hb_set_t lookup_indices, feature_indices;
321*2d1272b8SAndroid Build Coastguard Worker   _collect_layout_indices<T> (plan,
322*2d1272b8SAndroid Build Coastguard Worker                               *table,
323*2d1272b8SAndroid Build Coastguard Worker                               &lookup_indices,
324*2d1272b8SAndroid Build Coastguard Worker                               &feature_indices,
325*2d1272b8SAndroid Build Coastguard Worker                               feature_record_cond_idx_map,
326*2d1272b8SAndroid Build Coastguard Worker                               feature_substitutes_map,
327*2d1272b8SAndroid Build Coastguard Worker                               catch_all_record_feature_idxes,
328*2d1272b8SAndroid Build Coastguard Worker                               catch_all_record_idx_feature_map);
329*2d1272b8SAndroid Build Coastguard Worker 
330*2d1272b8SAndroid Build Coastguard Worker   if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE))
331*2d1272b8SAndroid Build Coastguard Worker     hb_ot_layout_lookups_substitute_closure (plan->source,
332*2d1272b8SAndroid Build Coastguard Worker                                              &lookup_indices,
333*2d1272b8SAndroid Build Coastguard Worker 					     gids_to_retain);
334*2d1272b8SAndroid Build Coastguard Worker   table->closure_lookups (plan->source,
335*2d1272b8SAndroid Build Coastguard Worker 			  gids_to_retain,
336*2d1272b8SAndroid Build Coastguard Worker                           &lookup_indices);
337*2d1272b8SAndroid Build Coastguard Worker   _remap_indexes (&lookup_indices, lookups);
338*2d1272b8SAndroid Build Coastguard Worker 
339*2d1272b8SAndroid Build Coastguard Worker   // prune features
340*2d1272b8SAndroid Build Coastguard Worker   table->prune_features (lookups,
341*2d1272b8SAndroid Build Coastguard Worker                          plan->user_axes_location.is_empty () ? nullptr : feature_record_cond_idx_map,
342*2d1272b8SAndroid Build Coastguard Worker                          feature_substitutes_map,
343*2d1272b8SAndroid Build Coastguard Worker                          &feature_indices);
344*2d1272b8SAndroid Build Coastguard Worker   hb_map_t duplicate_feature_map;
345*2d1272b8SAndroid Build Coastguard Worker   _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map);
346*2d1272b8SAndroid Build Coastguard Worker 
347*2d1272b8SAndroid Build Coastguard Worker   feature_indices.clear ();
348*2d1272b8SAndroid Build Coastguard Worker   table->prune_langsys (&duplicate_feature_map, &plan->layout_scripts, langsys_map, &feature_indices);
349*2d1272b8SAndroid Build Coastguard Worker   _remap_indexes (&feature_indices, features);
350*2d1272b8SAndroid Build Coastguard Worker 
351*2d1272b8SAndroid Build Coastguard Worker   table.destroy ();
352*2d1272b8SAndroid Build Coastguard Worker }
353*2d1272b8SAndroid Build Coastguard Worker 
354*2d1272b8SAndroid Build Coastguard Worker #endif
355*2d1272b8SAndroid Build Coastguard Worker 
356*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
357*2d1272b8SAndroid Build Coastguard Worker static inline void
_generate_varstore_inner_maps(const hb_set_t & varidx_set,unsigned subtable_count,hb_vector_t<hb_inc_bimap_t> & inner_maps)358*2d1272b8SAndroid Build Coastguard Worker _generate_varstore_inner_maps (const hb_set_t& varidx_set,
359*2d1272b8SAndroid Build Coastguard Worker                                unsigned subtable_count,
360*2d1272b8SAndroid Build Coastguard Worker                                hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */)
361*2d1272b8SAndroid Build Coastguard Worker {
362*2d1272b8SAndroid Build Coastguard Worker   if (varidx_set.is_empty () || subtable_count == 0) return;
363*2d1272b8SAndroid Build Coastguard Worker 
364*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!inner_maps.resize (subtable_count))) return;
365*2d1272b8SAndroid Build Coastguard Worker   for (unsigned idx : varidx_set)
366*2d1272b8SAndroid Build Coastguard Worker   {
367*2d1272b8SAndroid Build Coastguard Worker     uint16_t major = idx >> 16;
368*2d1272b8SAndroid Build Coastguard Worker     uint16_t minor = idx & 0xFFFF;
369*2d1272b8SAndroid Build Coastguard Worker 
370*2d1272b8SAndroid Build Coastguard Worker     if (major >= subtable_count)
371*2d1272b8SAndroid Build Coastguard Worker       continue;
372*2d1272b8SAndroid Build Coastguard Worker     inner_maps[major].add (minor);
373*2d1272b8SAndroid Build Coastguard Worker   }
374*2d1272b8SAndroid Build Coastguard Worker }
375*2d1272b8SAndroid Build Coastguard Worker 
376*2d1272b8SAndroid Build Coastguard Worker static inline hb_font_t*
_get_hb_font_with_variations(const hb_subset_plan_t * plan)377*2d1272b8SAndroid Build Coastguard Worker _get_hb_font_with_variations (const hb_subset_plan_t *plan)
378*2d1272b8SAndroid Build Coastguard Worker {
379*2d1272b8SAndroid Build Coastguard Worker   hb_font_t *font = hb_font_create (plan->source);
380*2d1272b8SAndroid Build Coastguard Worker 
381*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t<hb_variation_t> vars;
382*2d1272b8SAndroid Build Coastguard Worker   if (!vars.alloc (plan->user_axes_location.get_population ())) {
383*2d1272b8SAndroid Build Coastguard Worker     hb_font_destroy (font);
384*2d1272b8SAndroid Build Coastguard Worker     return nullptr;
385*2d1272b8SAndroid Build Coastguard Worker   }
386*2d1272b8SAndroid Build Coastguard Worker 
387*2d1272b8SAndroid Build Coastguard Worker   for (auto _ : plan->user_axes_location)
388*2d1272b8SAndroid Build Coastguard Worker   {
389*2d1272b8SAndroid Build Coastguard Worker     hb_variation_t var;
390*2d1272b8SAndroid Build Coastguard Worker     var.tag = _.first;
391*2d1272b8SAndroid Build Coastguard Worker     var.value = _.second.middle;
392*2d1272b8SAndroid Build Coastguard Worker     vars.push (var);
393*2d1272b8SAndroid Build Coastguard Worker   }
394*2d1272b8SAndroid Build Coastguard Worker 
395*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
396*2d1272b8SAndroid Build Coastguard Worker   hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
397*2d1272b8SAndroid Build Coastguard Worker #endif
398*2d1272b8SAndroid Build Coastguard Worker   return font;
399*2d1272b8SAndroid Build Coastguard Worker }
400*2d1272b8SAndroid Build Coastguard Worker 
401*2d1272b8SAndroid Build Coastguard Worker static inline void
_remap_variation_indices(const OT::ItemVariationStore & var_store,const hb_set_t & variation_indices,const hb_vector_t<int> & normalized_coords,bool calculate_delta,bool no_variations,hb_hashmap_t<unsigned,hb_pair_t<unsigned,int>> & variation_idx_delta_map)402*2d1272b8SAndroid Build Coastguard Worker _remap_variation_indices (const OT::ItemVariationStore &var_store,
403*2d1272b8SAndroid Build Coastguard Worker                           const hb_set_t &variation_indices,
404*2d1272b8SAndroid Build Coastguard Worker                           const hb_vector_t<int>& normalized_coords,
405*2d1272b8SAndroid Build Coastguard Worker                           bool calculate_delta, /* not pinned at default */
406*2d1272b8SAndroid Build Coastguard Worker                           bool no_variations, /* all axes pinned */
407*2d1272b8SAndroid Build Coastguard Worker                           hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map /* OUT */)
408*2d1272b8SAndroid Build Coastguard Worker {
409*2d1272b8SAndroid Build Coastguard Worker   if (&var_store == &Null (OT::ItemVariationStore)) return;
410*2d1272b8SAndroid Build Coastguard Worker   unsigned subtable_count = var_store.get_sub_table_count ();
411*2d1272b8SAndroid Build Coastguard Worker   float *store_cache = var_store.create_cache ();
412*2d1272b8SAndroid Build Coastguard Worker 
413*2d1272b8SAndroid Build Coastguard Worker   unsigned new_major = 0, new_minor = 0;
414*2d1272b8SAndroid Build Coastguard Worker   unsigned last_major = (variation_indices.get_min ()) >> 16;
415*2d1272b8SAndroid Build Coastguard Worker   for (unsigned idx : variation_indices)
416*2d1272b8SAndroid Build Coastguard Worker   {
417*2d1272b8SAndroid Build Coastguard Worker     int delta = 0;
418*2d1272b8SAndroid Build Coastguard Worker     if (calculate_delta)
419*2d1272b8SAndroid Build Coastguard Worker       delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ,
420*2d1272b8SAndroid Build Coastguard Worker                                            normalized_coords.length, store_cache));
421*2d1272b8SAndroid Build Coastguard Worker 
422*2d1272b8SAndroid Build Coastguard Worker     if (no_variations)
423*2d1272b8SAndroid Build Coastguard Worker     {
424*2d1272b8SAndroid Build Coastguard Worker       variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
425*2d1272b8SAndroid Build Coastguard Worker       continue;
426*2d1272b8SAndroid Build Coastguard Worker     }
427*2d1272b8SAndroid Build Coastguard Worker 
428*2d1272b8SAndroid Build Coastguard Worker     uint16_t major = idx >> 16;
429*2d1272b8SAndroid Build Coastguard Worker     if (major >= subtable_count) break;
430*2d1272b8SAndroid Build Coastguard Worker     if (major != last_major)
431*2d1272b8SAndroid Build Coastguard Worker     {
432*2d1272b8SAndroid Build Coastguard Worker       new_minor = 0;
433*2d1272b8SAndroid Build Coastguard Worker       ++new_major;
434*2d1272b8SAndroid Build Coastguard Worker     }
435*2d1272b8SAndroid Build Coastguard Worker 
436*2d1272b8SAndroid Build Coastguard Worker     unsigned new_idx = (new_major << 16) + new_minor;
437*2d1272b8SAndroid Build Coastguard Worker     variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
438*2d1272b8SAndroid Build Coastguard Worker     ++new_minor;
439*2d1272b8SAndroid Build Coastguard Worker     last_major = major;
440*2d1272b8SAndroid Build Coastguard Worker   }
441*2d1272b8SAndroid Build Coastguard Worker   var_store.destroy_cache (store_cache);
442*2d1272b8SAndroid Build Coastguard Worker }
443*2d1272b8SAndroid Build Coastguard Worker 
444*2d1272b8SAndroid Build Coastguard Worker static inline void
_collect_layout_variation_indices(hb_subset_plan_t * plan)445*2d1272b8SAndroid Build Coastguard Worker _collect_layout_variation_indices (hb_subset_plan_t* plan)
446*2d1272b8SAndroid Build Coastguard Worker {
447*2d1272b8SAndroid Build Coastguard Worker   hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
448*2d1272b8SAndroid Build Coastguard Worker   hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
449*2d1272b8SAndroid Build Coastguard Worker 
450*2d1272b8SAndroid Build Coastguard Worker   if (!gdef->has_data () || !gdef->has_var_store ())
451*2d1272b8SAndroid Build Coastguard Worker   {
452*2d1272b8SAndroid Build Coastguard Worker     gdef.destroy ();
453*2d1272b8SAndroid Build Coastguard Worker     gpos.destroy ();
454*2d1272b8SAndroid Build Coastguard Worker     return;
455*2d1272b8SAndroid Build Coastguard Worker   }
456*2d1272b8SAndroid Build Coastguard Worker 
457*2d1272b8SAndroid Build Coastguard Worker   hb_set_t varidx_set;
458*2d1272b8SAndroid Build Coastguard Worker   OT::hb_collect_variation_indices_context_t c (&varidx_set,
459*2d1272b8SAndroid Build Coastguard Worker                                                 &plan->_glyphset_gsub,
460*2d1272b8SAndroid Build Coastguard Worker                                                 &plan->gpos_lookups);
461*2d1272b8SAndroid Build Coastguard Worker   gdef->collect_variation_indices (&c);
462*2d1272b8SAndroid Build Coastguard Worker 
463*2d1272b8SAndroid Build Coastguard Worker   if (hb_ot_layout_has_positioning (plan->source))
464*2d1272b8SAndroid Build Coastguard Worker     gpos->collect_variation_indices (&c);
465*2d1272b8SAndroid Build Coastguard Worker 
466*2d1272b8SAndroid Build Coastguard Worker   _remap_variation_indices (gdef->get_var_store (),
467*2d1272b8SAndroid Build Coastguard Worker                             varidx_set, plan->normalized_coords,
468*2d1272b8SAndroid Build Coastguard Worker                             !plan->pinned_at_default,
469*2d1272b8SAndroid Build Coastguard Worker                             plan->all_axes_pinned,
470*2d1272b8SAndroid Build Coastguard Worker                             plan->layout_variation_idx_delta_map);
471*2d1272b8SAndroid Build Coastguard Worker 
472*2d1272b8SAndroid Build Coastguard Worker   unsigned subtable_count = gdef->get_var_store ().get_sub_table_count ();
473*2d1272b8SAndroid Build Coastguard Worker   _generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps);
474*2d1272b8SAndroid Build Coastguard Worker 
475*2d1272b8SAndroid Build Coastguard Worker   gdef.destroy ();
476*2d1272b8SAndroid Build Coastguard Worker   gpos.destroy ();
477*2d1272b8SAndroid Build Coastguard Worker }
478*2d1272b8SAndroid Build Coastguard Worker 
479*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BASE
480*2d1272b8SAndroid Build Coastguard Worker static inline void
_collect_base_variation_indices(hb_subset_plan_t * plan)481*2d1272b8SAndroid Build Coastguard Worker _collect_base_variation_indices (hb_subset_plan_t* plan)
482*2d1272b8SAndroid Build Coastguard Worker {
483*2d1272b8SAndroid Build Coastguard Worker   hb_blob_ptr_t<OT::BASE> base = plan->source_table<OT::BASE> ();
484*2d1272b8SAndroid Build Coastguard Worker   if (!base->has_var_store ())
485*2d1272b8SAndroid Build Coastguard Worker   {
486*2d1272b8SAndroid Build Coastguard Worker     base.destroy ();
487*2d1272b8SAndroid Build Coastguard Worker     return;
488*2d1272b8SAndroid Build Coastguard Worker   }
489*2d1272b8SAndroid Build Coastguard Worker 
490*2d1272b8SAndroid Build Coastguard Worker   hb_set_t varidx_set;
491*2d1272b8SAndroid Build Coastguard Worker   base->collect_variation_indices (plan, varidx_set);
492*2d1272b8SAndroid Build Coastguard Worker   const OT::ItemVariationStore &var_store = base->get_var_store ();
493*2d1272b8SAndroid Build Coastguard Worker   unsigned subtable_count = var_store.get_sub_table_count ();
494*2d1272b8SAndroid Build Coastguard Worker 
495*2d1272b8SAndroid Build Coastguard Worker 
496*2d1272b8SAndroid Build Coastguard Worker   _remap_variation_indices (var_store, varidx_set,
497*2d1272b8SAndroid Build Coastguard Worker                             plan->normalized_coords,
498*2d1272b8SAndroid Build Coastguard Worker                             !plan->pinned_at_default,
499*2d1272b8SAndroid Build Coastguard Worker                             plan->all_axes_pinned,
500*2d1272b8SAndroid Build Coastguard Worker                             plan->base_variation_idx_map);
501*2d1272b8SAndroid Build Coastguard Worker   _generate_varstore_inner_maps (varidx_set, subtable_count, plan->base_varstore_inner_maps);
502*2d1272b8SAndroid Build Coastguard Worker 
503*2d1272b8SAndroid Build Coastguard Worker   base.destroy ();
504*2d1272b8SAndroid Build Coastguard Worker }
505*2d1272b8SAndroid Build Coastguard Worker 
506*2d1272b8SAndroid Build Coastguard Worker #endif
507*2d1272b8SAndroid Build Coastguard Worker #endif
508*2d1272b8SAndroid Build Coastguard Worker 
509*2d1272b8SAndroid Build Coastguard Worker static inline void
_cmap_closure(hb_face_t * face,const hb_set_t * unicodes,hb_set_t * glyphset)510*2d1272b8SAndroid Build Coastguard Worker _cmap_closure (hb_face_t	   *face,
511*2d1272b8SAndroid Build Coastguard Worker 	       const hb_set_t	   *unicodes,
512*2d1272b8SAndroid Build Coastguard Worker 	       hb_set_t		   *glyphset)
513*2d1272b8SAndroid Build Coastguard Worker {
514*2d1272b8SAndroid Build Coastguard Worker   OT::cmap::accelerator_t cmap (face);
515*2d1272b8SAndroid Build Coastguard Worker   cmap.table->closure_glyphs (unicodes, glyphset);
516*2d1272b8SAndroid Build Coastguard Worker }
517*2d1272b8SAndroid Build Coastguard Worker 
518*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
519*2d1272b8SAndroid Build Coastguard Worker static void
_remap_colrv1_delta_set_index_indices(const OT::DeltaSetIndexMap & index_map,const hb_set_t & delta_set_idxes,hb_hashmap_t<unsigned,hb_pair_t<unsigned,int>> & variation_idx_delta_map,hb_map_t & new_deltaset_idx_varidx_map)520*2d1272b8SAndroid Build Coastguard Worker _remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map,
521*2d1272b8SAndroid Build Coastguard Worker                                        const hb_set_t &delta_set_idxes,
522*2d1272b8SAndroid Build Coastguard Worker                                        hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map, /* IN/OUT */
523*2d1272b8SAndroid Build Coastguard Worker                                        hb_map_t &new_deltaset_idx_varidx_map /* OUT */)
524*2d1272b8SAndroid Build Coastguard Worker {
525*2d1272b8SAndroid Build Coastguard Worker   if (!index_map.get_map_count ())
526*2d1272b8SAndroid Build Coastguard Worker     return;
527*2d1272b8SAndroid Build Coastguard Worker 
528*2d1272b8SAndroid Build Coastguard Worker   hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> delta_set_idx_delta_map;
529*2d1272b8SAndroid Build Coastguard Worker   unsigned new_delta_set_idx = 0;
530*2d1272b8SAndroid Build Coastguard Worker   for (unsigned delta_set_idx : delta_set_idxes)
531*2d1272b8SAndroid Build Coastguard Worker   {
532*2d1272b8SAndroid Build Coastguard Worker     unsigned var_idx = index_map.map (delta_set_idx);
533*2d1272b8SAndroid Build Coastguard Worker     unsigned new_varidx = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
534*2d1272b8SAndroid Build Coastguard Worker     int delta = 0;
535*2d1272b8SAndroid Build Coastguard Worker 
536*2d1272b8SAndroid Build Coastguard Worker     if (var_idx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
537*2d1272b8SAndroid Build Coastguard Worker     {
538*2d1272b8SAndroid Build Coastguard Worker       hb_pair_t<unsigned, int> *new_varidx_delta;
539*2d1272b8SAndroid Build Coastguard Worker       if (!variation_idx_delta_map.has (var_idx, &new_varidx_delta)) continue;
540*2d1272b8SAndroid Build Coastguard Worker 
541*2d1272b8SAndroid Build Coastguard Worker       new_varidx = hb_first (*new_varidx_delta);
542*2d1272b8SAndroid Build Coastguard Worker       delta = hb_second (*new_varidx_delta);
543*2d1272b8SAndroid Build Coastguard Worker     }
544*2d1272b8SAndroid Build Coastguard Worker 
545*2d1272b8SAndroid Build Coastguard Worker     new_deltaset_idx_varidx_map.set (new_delta_set_idx, new_varidx);
546*2d1272b8SAndroid Build Coastguard Worker     delta_set_idx_delta_map.set (delta_set_idx, hb_pair_t<unsigned, int> (new_delta_set_idx, delta));
547*2d1272b8SAndroid Build Coastguard Worker     new_delta_set_idx++;
548*2d1272b8SAndroid Build Coastguard Worker   }
549*2d1272b8SAndroid Build Coastguard Worker   variation_idx_delta_map = std::move (delta_set_idx_delta_map);
550*2d1272b8SAndroid Build Coastguard Worker }
551*2d1272b8SAndroid Build Coastguard Worker #endif
552*2d1272b8SAndroid Build Coastguard Worker 
_colr_closure(hb_subset_plan_t * plan,hb_set_t * glyphs_colred)553*2d1272b8SAndroid Build Coastguard Worker static void _colr_closure (hb_subset_plan_t* plan,
554*2d1272b8SAndroid Build Coastguard Worker                            hb_set_t *glyphs_colred)
555*2d1272b8SAndroid Build Coastguard Worker {
556*2d1272b8SAndroid Build Coastguard Worker   OT::COLR::accelerator_t colr (plan->source);
557*2d1272b8SAndroid Build Coastguard Worker   if (!colr.is_valid ()) return;
558*2d1272b8SAndroid Build Coastguard Worker 
559*2d1272b8SAndroid Build Coastguard Worker   hb_set_t palette_indices, layer_indices;
560*2d1272b8SAndroid Build Coastguard Worker   // Collect all glyphs referenced by COLRv0
561*2d1272b8SAndroid Build Coastguard Worker   hb_set_t glyphset_colrv0;
562*2d1272b8SAndroid Build Coastguard Worker   for (hb_codepoint_t gid : *glyphs_colred)
563*2d1272b8SAndroid Build Coastguard Worker     colr.closure_glyphs (gid, &glyphset_colrv0);
564*2d1272b8SAndroid Build Coastguard Worker 
565*2d1272b8SAndroid Build Coastguard Worker   glyphs_colred->union_ (glyphset_colrv0);
566*2d1272b8SAndroid Build Coastguard Worker 
567*2d1272b8SAndroid Build Coastguard Worker   //closure for COLRv1
568*2d1272b8SAndroid Build Coastguard Worker   hb_set_t variation_indices, delta_set_indices;
569*2d1272b8SAndroid Build Coastguard Worker   colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices, &variation_indices, &delta_set_indices);
570*2d1272b8SAndroid Build Coastguard Worker 
571*2d1272b8SAndroid Build Coastguard Worker   colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
572*2d1272b8SAndroid Build Coastguard Worker   _remap_indexes (&layer_indices, &plan->colrv1_layers);
573*2d1272b8SAndroid Build Coastguard Worker   _remap_palette_indexes (&palette_indices, &plan->colr_palettes);
574*2d1272b8SAndroid Build Coastguard Worker 
575*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
576*2d1272b8SAndroid Build Coastguard Worker   if (!colr.has_var_store () || !variation_indices) return;
577*2d1272b8SAndroid Build Coastguard Worker 
578*2d1272b8SAndroid Build Coastguard Worker   const OT::ItemVariationStore &var_store = colr.get_var_store ();
579*2d1272b8SAndroid Build Coastguard Worker   // generated inner_maps is used by ItemVariationStore serialize(), which is subset only
580*2d1272b8SAndroid Build Coastguard Worker   unsigned subtable_count = var_store.get_sub_table_count ();
581*2d1272b8SAndroid Build Coastguard Worker   _generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps);
582*2d1272b8SAndroid Build Coastguard Worker 
583*2d1272b8SAndroid Build Coastguard Worker   /* colr variation indices mapping during planning phase:
584*2d1272b8SAndroid Build Coastguard Worker    * generate colrv1_variation_idx_delta_map. When delta set index map is not
585*2d1272b8SAndroid Build Coastguard Worker    * included, it's a mapping from varIdx-> (new varIdx,delta). Otherwise, it's
586*2d1272b8SAndroid Build Coastguard Worker    * a mapping from old delta set idx-> (new delta set idx, delta). Mapping
587*2d1272b8SAndroid Build Coastguard Worker    * delta set indices is the same as gid mapping.
588*2d1272b8SAndroid Build Coastguard Worker    * Besides, we need to generate a delta set idx-> new var_idx map for updating
589*2d1272b8SAndroid Build Coastguard Worker    * delta set index map if exists. This map will be updated again after
590*2d1272b8SAndroid Build Coastguard Worker    * instancing. */
591*2d1272b8SAndroid Build Coastguard Worker   if (!plan->all_axes_pinned)
592*2d1272b8SAndroid Build Coastguard Worker   {
593*2d1272b8SAndroid Build Coastguard Worker     _remap_variation_indices (var_store,
594*2d1272b8SAndroid Build Coastguard Worker                               variation_indices,
595*2d1272b8SAndroid Build Coastguard Worker                               plan->normalized_coords,
596*2d1272b8SAndroid Build Coastguard Worker                               false, /* no need to calculate delta for COLR during planning */
597*2d1272b8SAndroid Build Coastguard Worker                               plan->all_axes_pinned,
598*2d1272b8SAndroid Build Coastguard Worker                               plan->colrv1_variation_idx_delta_map);
599*2d1272b8SAndroid Build Coastguard Worker 
600*2d1272b8SAndroid Build Coastguard Worker     if (colr.has_delta_set_index_map ())
601*2d1272b8SAndroid Build Coastguard Worker       _remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (),
602*2d1272b8SAndroid Build Coastguard Worker                                              delta_set_indices,
603*2d1272b8SAndroid Build Coastguard Worker                                              plan->colrv1_variation_idx_delta_map,
604*2d1272b8SAndroid Build Coastguard Worker                                              plan->colrv1_new_deltaset_idx_varidx_map);
605*2d1272b8SAndroid Build Coastguard Worker   }
606*2d1272b8SAndroid Build Coastguard Worker #endif
607*2d1272b8SAndroid Build Coastguard Worker }
608*2d1272b8SAndroid Build Coastguard Worker 
609*2d1272b8SAndroid Build Coastguard Worker static inline void
_math_closure(hb_subset_plan_t * plan,hb_set_t * glyphset)610*2d1272b8SAndroid Build Coastguard Worker _math_closure (hb_subset_plan_t *plan,
611*2d1272b8SAndroid Build Coastguard Worker                hb_set_t         *glyphset)
612*2d1272b8SAndroid Build Coastguard Worker {
613*2d1272b8SAndroid Build Coastguard Worker   hb_blob_ptr_t<OT::MATH> math = plan->source_table<OT::MATH> ();
614*2d1272b8SAndroid Build Coastguard Worker   if (math->has_data ())
615*2d1272b8SAndroid Build Coastguard Worker     math->closure_glyphs (glyphset);
616*2d1272b8SAndroid Build Coastguard Worker   math.destroy ();
617*2d1272b8SAndroid Build Coastguard Worker }
618*2d1272b8SAndroid Build Coastguard Worker 
619*2d1272b8SAndroid Build Coastguard Worker static inline void
_remap_used_mark_sets(hb_subset_plan_t * plan,hb_map_t & used_mark_sets_map)620*2d1272b8SAndroid Build Coastguard Worker _remap_used_mark_sets (hb_subset_plan_t *plan,
621*2d1272b8SAndroid Build Coastguard Worker                        hb_map_t& used_mark_sets_map)
622*2d1272b8SAndroid Build Coastguard Worker {
623*2d1272b8SAndroid Build Coastguard Worker   hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
624*2d1272b8SAndroid Build Coastguard Worker 
625*2d1272b8SAndroid Build Coastguard Worker   if (!gdef->has_data () || !gdef->has_mark_glyph_sets ())
626*2d1272b8SAndroid Build Coastguard Worker   {
627*2d1272b8SAndroid Build Coastguard Worker     gdef.destroy ();
628*2d1272b8SAndroid Build Coastguard Worker     return;
629*2d1272b8SAndroid Build Coastguard Worker   }
630*2d1272b8SAndroid Build Coastguard Worker 
631*2d1272b8SAndroid Build Coastguard Worker   hb_set_t used_mark_sets;
632*2d1272b8SAndroid Build Coastguard Worker   gdef->get_mark_glyph_sets ().collect_used_mark_sets (plan->_glyphset_gsub, used_mark_sets);
633*2d1272b8SAndroid Build Coastguard Worker   gdef.destroy ();
634*2d1272b8SAndroid Build Coastguard Worker 
635*2d1272b8SAndroid Build Coastguard Worker   _remap_indexes (&used_mark_sets, &used_mark_sets_map);
636*2d1272b8SAndroid Build Coastguard Worker }
637*2d1272b8SAndroid Build Coastguard Worker 
638*2d1272b8SAndroid Build Coastguard Worker static inline void
_remove_invalid_gids(hb_set_t * glyphs,unsigned int num_glyphs)639*2d1272b8SAndroid Build Coastguard Worker _remove_invalid_gids (hb_set_t *glyphs,
640*2d1272b8SAndroid Build Coastguard Worker 		      unsigned int num_glyphs)
641*2d1272b8SAndroid Build Coastguard Worker {
642*2d1272b8SAndroid Build Coastguard Worker   glyphs->del_range (num_glyphs, HB_SET_VALUE_INVALID);
643*2d1272b8SAndroid Build Coastguard Worker }
644*2d1272b8SAndroid Build Coastguard Worker 
645*2d1272b8SAndroid Build Coastguard Worker template<bool GID_ALWAYS_EXISTS = false, typename I, typename F, typename G, hb_requires (hb_is_iterator (I))>
646*2d1272b8SAndroid Build Coastguard Worker static void
_fill_unicode_and_glyph_map(hb_subset_plan_t * plan,I unicode_iterator,F unicode_to_gid_for_iterator,G unicode_to_gid_general)647*2d1272b8SAndroid Build Coastguard Worker _fill_unicode_and_glyph_map(hb_subset_plan_t *plan,
648*2d1272b8SAndroid Build Coastguard Worker                             I unicode_iterator,
649*2d1272b8SAndroid Build Coastguard Worker                             F unicode_to_gid_for_iterator,
650*2d1272b8SAndroid Build Coastguard Worker                             G unicode_to_gid_general)
651*2d1272b8SAndroid Build Coastguard Worker {
652*2d1272b8SAndroid Build Coastguard Worker   for (hb_codepoint_t cp : unicode_iterator)
653*2d1272b8SAndroid Build Coastguard Worker   {
654*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t gid = unicode_to_gid_for_iterator(cp);
655*2d1272b8SAndroid Build Coastguard Worker     if (!GID_ALWAYS_EXISTS && gid == HB_MAP_VALUE_INVALID)
656*2d1272b8SAndroid Build Coastguard Worker     {
657*2d1272b8SAndroid Build Coastguard Worker       DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
658*2d1272b8SAndroid Build Coastguard Worker       continue;
659*2d1272b8SAndroid Build Coastguard Worker     }
660*2d1272b8SAndroid Build Coastguard Worker 
661*2d1272b8SAndroid Build Coastguard Worker     plan->codepoint_to_glyph->set (cp, gid);
662*2d1272b8SAndroid Build Coastguard Worker     plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
663*2d1272b8SAndroid Build Coastguard Worker   }
664*2d1272b8SAndroid Build Coastguard Worker }
665*2d1272b8SAndroid Build Coastguard Worker 
666*2d1272b8SAndroid Build Coastguard Worker template<bool GID_ALWAYS_EXISTS = false, typename I, typename F, hb_requires (hb_is_iterator (I))>
667*2d1272b8SAndroid Build Coastguard Worker static void
_fill_unicode_and_glyph_map(hb_subset_plan_t * plan,I unicode_iterator,F unicode_to_gid_for_iterator)668*2d1272b8SAndroid Build Coastguard Worker _fill_unicode_and_glyph_map(hb_subset_plan_t *plan,
669*2d1272b8SAndroid Build Coastguard Worker                             I unicode_iterator,
670*2d1272b8SAndroid Build Coastguard Worker                             F unicode_to_gid_for_iterator)
671*2d1272b8SAndroid Build Coastguard Worker {
672*2d1272b8SAndroid Build Coastguard Worker   _fill_unicode_and_glyph_map(plan, unicode_iterator, unicode_to_gid_for_iterator, unicode_to_gid_for_iterator);
673*2d1272b8SAndroid Build Coastguard Worker }
674*2d1272b8SAndroid Build Coastguard Worker 
675*2d1272b8SAndroid Build Coastguard Worker static void
_populate_unicodes_to_retain(const hb_set_t * unicodes,const hb_set_t * glyphs,hb_subset_plan_t * plan)676*2d1272b8SAndroid Build Coastguard Worker _populate_unicodes_to_retain (const hb_set_t *unicodes,
677*2d1272b8SAndroid Build Coastguard Worker                               const hb_set_t *glyphs,
678*2d1272b8SAndroid Build Coastguard Worker                               hb_subset_plan_t *plan)
679*2d1272b8SAndroid Build Coastguard Worker {
680*2d1272b8SAndroid Build Coastguard Worker   OT::cmap::accelerator_t cmap (plan->source);
681*2d1272b8SAndroid Build Coastguard Worker   unsigned size_threshold = plan->source->get_num_glyphs ();
682*2d1272b8SAndroid Build Coastguard Worker   if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
683*2d1272b8SAndroid Build Coastguard Worker   {
684*2d1272b8SAndroid Build Coastguard Worker 
685*2d1272b8SAndroid Build Coastguard Worker     const hb_map_t* unicode_to_gid = nullptr;
686*2d1272b8SAndroid Build Coastguard Worker     if (plan->accelerator)
687*2d1272b8SAndroid Build Coastguard Worker       unicode_to_gid = &plan->accelerator->unicode_to_gid;
688*2d1272b8SAndroid Build Coastguard Worker 
689*2d1272b8SAndroid Build Coastguard Worker     // This is approach to collection is faster, but can only be used  if glyphs
690*2d1272b8SAndroid Build Coastguard Worker     // are not being explicitly added to the subset and the input unicodes set is
691*2d1272b8SAndroid Build Coastguard Worker     // not excessively large (eg. an inverted set).
692*2d1272b8SAndroid Build Coastguard Worker     plan->unicode_to_new_gid_list.alloc (unicodes->get_population ());
693*2d1272b8SAndroid Build Coastguard Worker     if (!unicode_to_gid) {
694*2d1272b8SAndroid Build Coastguard Worker       _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
695*2d1272b8SAndroid Build Coastguard Worker         hb_codepoint_t gid;
696*2d1272b8SAndroid Build Coastguard Worker         if (!cmap.get_nominal_glyph (cp, &gid)) {
697*2d1272b8SAndroid Build Coastguard Worker           return HB_MAP_VALUE_INVALID;
698*2d1272b8SAndroid Build Coastguard Worker         }
699*2d1272b8SAndroid Build Coastguard Worker         return gid;
700*2d1272b8SAndroid Build Coastguard Worker       });
701*2d1272b8SAndroid Build Coastguard Worker     } else {
702*2d1272b8SAndroid Build Coastguard Worker       // Use in memory unicode to gid map it's faster then looking up from
703*2d1272b8SAndroid Build Coastguard Worker       // the map. This code is mostly duplicated from above to avoid doing
704*2d1272b8SAndroid Build Coastguard Worker       // conditionals on the presence of the unicode_to_gid map each
705*2d1272b8SAndroid Build Coastguard Worker       // iteration.
706*2d1272b8SAndroid Build Coastguard Worker       _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
707*2d1272b8SAndroid Build Coastguard Worker         return unicode_to_gid->get (cp);
708*2d1272b8SAndroid Build Coastguard Worker       });
709*2d1272b8SAndroid Build Coastguard Worker     }
710*2d1272b8SAndroid Build Coastguard Worker   }
711*2d1272b8SAndroid Build Coastguard Worker   else
712*2d1272b8SAndroid Build Coastguard Worker   {
713*2d1272b8SAndroid Build Coastguard Worker     // This approach is slower, but can handle adding in glyphs to the subset and will match
714*2d1272b8SAndroid Build Coastguard Worker     // them with cmap entries.
715*2d1272b8SAndroid Build Coastguard Worker 
716*2d1272b8SAndroid Build Coastguard Worker     hb_map_t unicode_glyphid_map_storage;
717*2d1272b8SAndroid Build Coastguard Worker     hb_set_t cmap_unicodes_storage;
718*2d1272b8SAndroid Build Coastguard Worker     const hb_map_t* unicode_glyphid_map = &unicode_glyphid_map_storage;
719*2d1272b8SAndroid Build Coastguard Worker     const hb_set_t* cmap_unicodes = &cmap_unicodes_storage;
720*2d1272b8SAndroid Build Coastguard Worker 
721*2d1272b8SAndroid Build Coastguard Worker     if (!plan->accelerator) {
722*2d1272b8SAndroid Build Coastguard Worker       cmap.collect_mapping (&cmap_unicodes_storage, &unicode_glyphid_map_storage);
723*2d1272b8SAndroid Build Coastguard Worker       plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population ()
724*2d1272b8SAndroid Build Coastguard Worker                                                   + glyphs->get_population (),
725*2d1272b8SAndroid Build Coastguard Worker                                                   cmap_unicodes->get_population ()));
726*2d1272b8SAndroid Build Coastguard Worker     } else {
727*2d1272b8SAndroid Build Coastguard Worker       unicode_glyphid_map = &plan->accelerator->unicode_to_gid;
728*2d1272b8SAndroid Build Coastguard Worker       cmap_unicodes = &plan->accelerator->unicodes;
729*2d1272b8SAndroid Build Coastguard Worker     }
730*2d1272b8SAndroid Build Coastguard Worker 
731*2d1272b8SAndroid Build Coastguard Worker     if (plan->accelerator &&
732*2d1272b8SAndroid Build Coastguard Worker 	unicodes->get_population () < cmap_unicodes->get_population () &&
733*2d1272b8SAndroid Build Coastguard Worker 	glyphs->get_population () < cmap_unicodes->get_population ())
734*2d1272b8SAndroid Build Coastguard Worker     {
735*2d1272b8SAndroid Build Coastguard Worker       plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ());
736*2d1272b8SAndroid Build Coastguard Worker 
737*2d1272b8SAndroid Build Coastguard Worker       auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes;
738*2d1272b8SAndroid Build Coastguard Worker 
739*2d1272b8SAndroid Build Coastguard Worker       for (hb_codepoint_t gid : *glyphs)
740*2d1272b8SAndroid Build Coastguard Worker       {
741*2d1272b8SAndroid Build Coastguard Worker         auto unicodes = gid_to_unicodes.get (gid);
742*2d1272b8SAndroid Build Coastguard Worker         _fill_unicode_and_glyph_map<true>(plan, unicodes, [&] (hb_codepoint_t cp) {
743*2d1272b8SAndroid Build Coastguard Worker           return gid;
744*2d1272b8SAndroid Build Coastguard Worker         },
745*2d1272b8SAndroid Build Coastguard Worker         [&] (hb_codepoint_t cp) {
746*2d1272b8SAndroid Build Coastguard Worker           return unicode_glyphid_map->get(cp);
747*2d1272b8SAndroid Build Coastguard Worker         });
748*2d1272b8SAndroid Build Coastguard Worker       }
749*2d1272b8SAndroid Build Coastguard Worker 
750*2d1272b8SAndroid Build Coastguard Worker       _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
751*2d1272b8SAndroid Build Coastguard Worker           /* Don't double-add entry. */
752*2d1272b8SAndroid Build Coastguard Worker 	if (plan->codepoint_to_glyph->has (cp))
753*2d1272b8SAndroid Build Coastguard Worker           return HB_MAP_VALUE_INVALID;
754*2d1272b8SAndroid Build Coastguard Worker 
755*2d1272b8SAndroid Build Coastguard Worker         return unicode_glyphid_map->get(cp);
756*2d1272b8SAndroid Build Coastguard Worker       },
757*2d1272b8SAndroid Build Coastguard Worker       [&] (hb_codepoint_t cp) {
758*2d1272b8SAndroid Build Coastguard Worker           return unicode_glyphid_map->get(cp);
759*2d1272b8SAndroid Build Coastguard Worker       });
760*2d1272b8SAndroid Build Coastguard Worker 
761*2d1272b8SAndroid Build Coastguard Worker       plan->unicode_to_new_gid_list.qsort ();
762*2d1272b8SAndroid Build Coastguard Worker     }
763*2d1272b8SAndroid Build Coastguard Worker     else
764*2d1272b8SAndroid Build Coastguard Worker     {
765*2d1272b8SAndroid Build Coastguard Worker       plan->codepoint_to_glyph->alloc (cmap_unicodes->get_population ());
766*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t first = HB_SET_VALUE_INVALID, last = HB_SET_VALUE_INVALID;
767*2d1272b8SAndroid Build Coastguard Worker       for (; cmap_unicodes->next_range (&first, &last); )
768*2d1272b8SAndroid Build Coastguard Worker       {
769*2d1272b8SAndroid Build Coastguard Worker         _fill_unicode_and_glyph_map(plan, hb_range(first, last + 1), [&] (hb_codepoint_t cp) {
770*2d1272b8SAndroid Build Coastguard Worker           hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
771*2d1272b8SAndroid Build Coastguard Worker 	  if (!unicodes->has (cp) && !glyphs->has (gid))
772*2d1272b8SAndroid Build Coastguard Worker 	    return HB_MAP_VALUE_INVALID;
773*2d1272b8SAndroid Build Coastguard Worker           return gid;
774*2d1272b8SAndroid Build Coastguard Worker         },
775*2d1272b8SAndroid Build Coastguard Worker         [&] (hb_codepoint_t cp) {
776*2d1272b8SAndroid Build Coastguard Worker           return unicode_glyphid_map->get(cp);
777*2d1272b8SAndroid Build Coastguard Worker         });
778*2d1272b8SAndroid Build Coastguard Worker       }
779*2d1272b8SAndroid Build Coastguard Worker     }
780*2d1272b8SAndroid Build Coastguard Worker 
781*2d1272b8SAndroid Build Coastguard Worker     /* Add gids which where requested, but not mapped in cmap */
782*2d1272b8SAndroid Build Coastguard Worker     unsigned num_glyphs = plan->source->get_num_glyphs ();
783*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t first = HB_SET_VALUE_INVALID, last = HB_SET_VALUE_INVALID;
784*2d1272b8SAndroid Build Coastguard Worker     for (; glyphs->next_range (&first, &last); )
785*2d1272b8SAndroid Build Coastguard Worker     {
786*2d1272b8SAndroid Build Coastguard Worker       if (first >= num_glyphs)
787*2d1272b8SAndroid Build Coastguard Worker 	break;
788*2d1272b8SAndroid Build Coastguard Worker       if (last >= num_glyphs)
789*2d1272b8SAndroid Build Coastguard Worker         last = num_glyphs - 1;
790*2d1272b8SAndroid Build Coastguard Worker       plan->_glyphset_gsub.add_range (first, last);
791*2d1272b8SAndroid Build Coastguard Worker     }
792*2d1272b8SAndroid Build Coastguard Worker   }
793*2d1272b8SAndroid Build Coastguard Worker 
794*2d1272b8SAndroid Build Coastguard Worker   auto &arr = plan->unicode_to_new_gid_list;
795*2d1272b8SAndroid Build Coastguard Worker   if (arr.length)
796*2d1272b8SAndroid Build Coastguard Worker   {
797*2d1272b8SAndroid Build Coastguard Worker     plan->unicodes.add_sorted_array (&arr.arrayZ->first, arr.length, sizeof (*arr.arrayZ));
798*2d1272b8SAndroid Build Coastguard Worker     plan->_glyphset_gsub.add_array (&arr.arrayZ->second, arr.length, sizeof (*arr.arrayZ));
799*2d1272b8SAndroid Build Coastguard Worker   }
800*2d1272b8SAndroid Build Coastguard Worker }
801*2d1272b8SAndroid Build Coastguard Worker 
802*2d1272b8SAndroid Build Coastguard Worker static unsigned
_glyf_add_gid_and_children(const OT::glyf_accelerator_t & glyf,hb_codepoint_t gid,hb_set_t * gids_to_retain,int operation_count,unsigned depth=0)803*2d1272b8SAndroid Build Coastguard Worker _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
804*2d1272b8SAndroid Build Coastguard Worker 			    hb_codepoint_t gid,
805*2d1272b8SAndroid Build Coastguard Worker 			    hb_set_t *gids_to_retain,
806*2d1272b8SAndroid Build Coastguard Worker 			    int operation_count,
807*2d1272b8SAndroid Build Coastguard Worker 			    unsigned depth = 0)
808*2d1272b8SAndroid Build Coastguard Worker {
809*2d1272b8SAndroid Build Coastguard Worker   /* Check if is already visited */
810*2d1272b8SAndroid Build Coastguard Worker   if (gids_to_retain->has (gid)) return operation_count;
811*2d1272b8SAndroid Build Coastguard Worker 
812*2d1272b8SAndroid Build Coastguard Worker   gids_to_retain->add (gid);
813*2d1272b8SAndroid Build Coastguard Worker 
814*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
815*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (--operation_count < 0)) return operation_count;
816*2d1272b8SAndroid Build Coastguard Worker 
817*2d1272b8SAndroid Build Coastguard Worker   auto glyph = glyf.glyph_for_gid (gid);
818*2d1272b8SAndroid Build Coastguard Worker 
819*2d1272b8SAndroid Build Coastguard Worker   for (auto &item : glyph.get_composite_iterator ())
820*2d1272b8SAndroid Build Coastguard Worker     operation_count =
821*2d1272b8SAndroid Build Coastguard Worker       _glyf_add_gid_and_children (glyf,
822*2d1272b8SAndroid Build Coastguard Worker 				  item.get_gid (),
823*2d1272b8SAndroid Build Coastguard Worker 				  gids_to_retain,
824*2d1272b8SAndroid Build Coastguard Worker 				  operation_count,
825*2d1272b8SAndroid Build Coastguard Worker 				  depth);
826*2d1272b8SAndroid Build Coastguard Worker 
827*2d1272b8SAndroid Build Coastguard Worker   return operation_count;
828*2d1272b8SAndroid Build Coastguard Worker }
829*2d1272b8SAndroid Build Coastguard Worker 
830*2d1272b8SAndroid Build Coastguard Worker static void
_nameid_closure(hb_subset_plan_t * plan,hb_set_t * drop_tables)831*2d1272b8SAndroid Build Coastguard Worker _nameid_closure (hb_subset_plan_t* plan,
832*2d1272b8SAndroid Build Coastguard Worker 		 hb_set_t* drop_tables)
833*2d1272b8SAndroid Build Coastguard Worker {
834*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_STYLE
835*2d1272b8SAndroid Build Coastguard Worker   plan->source->table.STAT->collect_name_ids (&plan->user_axes_location, &plan->name_ids);
836*2d1272b8SAndroid Build Coastguard Worker #endif
837*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
838*2d1272b8SAndroid Build Coastguard Worker   if (!plan->all_axes_pinned)
839*2d1272b8SAndroid Build Coastguard Worker     plan->source->table.fvar->collect_name_ids (&plan->user_axes_location, &plan->axes_old_index_tag_map, &plan->name_ids);
840*2d1272b8SAndroid Build Coastguard Worker #endif
841*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_COLOR
842*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables->has (HB_OT_TAG_CPAL))
843*2d1272b8SAndroid Build Coastguard Worker     plan->source->table.CPAL->collect_name_ids (&plan->colr_palettes, &plan->name_ids);
844*2d1272b8SAndroid Build Coastguard Worker #endif
845*2d1272b8SAndroid Build Coastguard Worker 
846*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_LAYOUT
847*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables->has (HB_OT_TAG_GPOS))
848*2d1272b8SAndroid Build Coastguard Worker   {
849*2d1272b8SAndroid Build Coastguard Worker     hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
850*2d1272b8SAndroid Build Coastguard Worker     gpos->collect_name_ids (&plan->gpos_features, &plan->name_ids);
851*2d1272b8SAndroid Build Coastguard Worker     gpos.destroy ();
852*2d1272b8SAndroid Build Coastguard Worker   }
853*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables->has (HB_OT_TAG_GSUB))
854*2d1272b8SAndroid Build Coastguard Worker   {
855*2d1272b8SAndroid Build Coastguard Worker     hb_blob_ptr_t<GSUB> gsub = plan->source_table<GSUB> ();
856*2d1272b8SAndroid Build Coastguard Worker     gsub->collect_name_ids (&plan->gsub_features, &plan->name_ids);
857*2d1272b8SAndroid Build Coastguard Worker     gsub.destroy ();
858*2d1272b8SAndroid Build Coastguard Worker   }
859*2d1272b8SAndroid Build Coastguard Worker #endif
860*2d1272b8SAndroid Build Coastguard Worker }
861*2d1272b8SAndroid Build Coastguard Worker 
862*2d1272b8SAndroid Build Coastguard Worker static void
_populate_gids_to_retain(hb_subset_plan_t * plan,hb_set_t * drop_tables)863*2d1272b8SAndroid Build Coastguard Worker _populate_gids_to_retain (hb_subset_plan_t* plan,
864*2d1272b8SAndroid Build Coastguard Worker 		          hb_set_t* drop_tables)
865*2d1272b8SAndroid Build Coastguard Worker {
866*2d1272b8SAndroid Build Coastguard Worker   OT::glyf_accelerator_t glyf (plan->source);
867*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_CFF
868*2d1272b8SAndroid Build Coastguard Worker   // Note: we cannot use inprogress_accelerator here, since it has not been
869*2d1272b8SAndroid Build Coastguard Worker   // created yet. So in case of preprocessed-face (and otherwise), we do an
870*2d1272b8SAndroid Build Coastguard Worker   // extra sanitize pass here, which is not ideal.
871*2d1272b8SAndroid Build Coastguard Worker   OT::cff1::accelerator_subset_t stack_cff (plan->accelerator ? nullptr : plan->source);
872*2d1272b8SAndroid Build Coastguard Worker   const OT::cff1::accelerator_subset_t *cff (plan->accelerator ? plan->accelerator->cff1_accel.get () : &stack_cff);
873*2d1272b8SAndroid Build Coastguard Worker #endif
874*2d1272b8SAndroid Build Coastguard Worker 
875*2d1272b8SAndroid Build Coastguard Worker   plan->_glyphset_gsub.add (0); // Not-def
876*2d1272b8SAndroid Build Coastguard Worker 
877*2d1272b8SAndroid Build Coastguard Worker   _cmap_closure (plan->source, &plan->unicodes, &plan->_glyphset_gsub);
878*2d1272b8SAndroid Build Coastguard Worker 
879*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_LAYOUT
880*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables->has (HB_OT_TAG_GSUB))
881*2d1272b8SAndroid Build Coastguard Worker     // closure all glyphs/lookups/features needed for GSUB substitutions.
882*2d1272b8SAndroid Build Coastguard Worker     _closure_glyphs_lookups_features<GSUB> (
883*2d1272b8SAndroid Build Coastguard Worker         plan,
884*2d1272b8SAndroid Build Coastguard Worker         &plan->_glyphset_gsub,
885*2d1272b8SAndroid Build Coastguard Worker         &plan->gsub_lookups,
886*2d1272b8SAndroid Build Coastguard Worker         &plan->gsub_features,
887*2d1272b8SAndroid Build Coastguard Worker         &plan->gsub_langsys,
888*2d1272b8SAndroid Build Coastguard Worker         &plan->gsub_feature_record_cond_idx_map,
889*2d1272b8SAndroid Build Coastguard Worker         &plan->gsub_feature_substitutes_map,
890*2d1272b8SAndroid Build Coastguard Worker         plan->gsub_old_features,
891*2d1272b8SAndroid Build Coastguard Worker         plan->gsub_old_feature_idx_tag_map);
892*2d1272b8SAndroid Build Coastguard Worker 
893*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables->has (HB_OT_TAG_GPOS))
894*2d1272b8SAndroid Build Coastguard Worker     _closure_glyphs_lookups_features<GPOS> (
895*2d1272b8SAndroid Build Coastguard Worker         plan,
896*2d1272b8SAndroid Build Coastguard Worker         &plan->_glyphset_gsub,
897*2d1272b8SAndroid Build Coastguard Worker         &plan->gpos_lookups,
898*2d1272b8SAndroid Build Coastguard Worker         &plan->gpos_features,
899*2d1272b8SAndroid Build Coastguard Worker         &plan->gpos_langsys,
900*2d1272b8SAndroid Build Coastguard Worker         &plan->gpos_feature_record_cond_idx_map,
901*2d1272b8SAndroid Build Coastguard Worker         &plan->gpos_feature_substitutes_map,
902*2d1272b8SAndroid Build Coastguard Worker         plan->gpos_old_features,
903*2d1272b8SAndroid Build Coastguard Worker         plan->gpos_old_feature_idx_tag_map);
904*2d1272b8SAndroid Build Coastguard Worker #endif
905*2d1272b8SAndroid Build Coastguard Worker   _remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ());
906*2d1272b8SAndroid Build Coastguard Worker 
907*2d1272b8SAndroid Build Coastguard Worker   plan->_glyphset_mathed = plan->_glyphset_gsub;
908*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables->has (HB_OT_TAG_MATH))
909*2d1272b8SAndroid Build Coastguard Worker   {
910*2d1272b8SAndroid Build Coastguard Worker     _math_closure (plan, &plan->_glyphset_mathed);
911*2d1272b8SAndroid Build Coastguard Worker     _remove_invalid_gids (&plan->_glyphset_mathed, plan->source->get_num_glyphs ());
912*2d1272b8SAndroid Build Coastguard Worker   }
913*2d1272b8SAndroid Build Coastguard Worker 
914*2d1272b8SAndroid Build Coastguard Worker   hb_set_t cur_glyphset = plan->_glyphset_mathed;
915*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables->has (HB_OT_TAG_COLR))
916*2d1272b8SAndroid Build Coastguard Worker   {
917*2d1272b8SAndroid Build Coastguard Worker     _colr_closure (plan, &cur_glyphset);
918*2d1272b8SAndroid Build Coastguard Worker     _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
919*2d1272b8SAndroid Build Coastguard Worker   }
920*2d1272b8SAndroid Build Coastguard Worker 
921*2d1272b8SAndroid Build Coastguard Worker   plan->_glyphset_colred = cur_glyphset;
922*2d1272b8SAndroid Build Coastguard Worker 
923*2d1272b8SAndroid Build Coastguard Worker   // XXX TODO VARC closure / subset
924*2d1272b8SAndroid Build Coastguard Worker 
925*2d1272b8SAndroid Build Coastguard Worker   _nameid_closure (plan, drop_tables);
926*2d1272b8SAndroid Build Coastguard Worker   /* Populate a full set of glyphs to retain by adding all referenced
927*2d1272b8SAndroid Build Coastguard Worker    * composite glyphs. */
928*2d1272b8SAndroid Build Coastguard Worker   if (glyf.has_data ())
929*2d1272b8SAndroid Build Coastguard Worker     for (hb_codepoint_t gid : cur_glyphset)
930*2d1272b8SAndroid Build Coastguard Worker       _glyf_add_gid_and_children (glyf, gid, &plan->_glyphset,
931*2d1272b8SAndroid Build Coastguard Worker 				  cur_glyphset.get_population () * HB_MAX_COMPOSITE_OPERATIONS_PER_GLYPH);
932*2d1272b8SAndroid Build Coastguard Worker   else
933*2d1272b8SAndroid Build Coastguard Worker     plan->_glyphset.union_ (cur_glyphset);
934*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_CFF
935*2d1272b8SAndroid Build Coastguard Worker   if (!plan->accelerator || plan->accelerator->has_seac)
936*2d1272b8SAndroid Build Coastguard Worker   {
937*2d1272b8SAndroid Build Coastguard Worker     bool has_seac = false;
938*2d1272b8SAndroid Build Coastguard Worker     if (cff->is_valid ())
939*2d1272b8SAndroid Build Coastguard Worker       for (hb_codepoint_t gid : cur_glyphset)
940*2d1272b8SAndroid Build Coastguard Worker 	if (_add_cff_seac_components (*cff, gid, &plan->_glyphset))
941*2d1272b8SAndroid Build Coastguard Worker 	  has_seac = true;
942*2d1272b8SAndroid Build Coastguard Worker     plan->has_seac = has_seac;
943*2d1272b8SAndroid Build Coastguard Worker   }
944*2d1272b8SAndroid Build Coastguard Worker #endif
945*2d1272b8SAndroid Build Coastguard Worker 
946*2d1272b8SAndroid Build Coastguard Worker   _remove_invalid_gids (&plan->_glyphset, plan->source->get_num_glyphs ());
947*2d1272b8SAndroid Build Coastguard Worker 
948*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
949*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables->has (HB_OT_TAG_GDEF))
950*2d1272b8SAndroid Build Coastguard Worker     _collect_layout_variation_indices (plan);
951*2d1272b8SAndroid Build Coastguard Worker #endif
952*2d1272b8SAndroid Build Coastguard Worker }
953*2d1272b8SAndroid Build Coastguard Worker 
954*2d1272b8SAndroid Build Coastguard Worker static void
_create_glyph_map_gsub(const hb_set_t * glyph_set_gsub,const hb_map_t * glyph_map,hb_map_t * out)955*2d1272b8SAndroid Build Coastguard Worker _create_glyph_map_gsub (const hb_set_t* glyph_set_gsub,
956*2d1272b8SAndroid Build Coastguard Worker                         const hb_map_t* glyph_map,
957*2d1272b8SAndroid Build Coastguard Worker                         hb_map_t* out)
958*2d1272b8SAndroid Build Coastguard Worker {
959*2d1272b8SAndroid Build Coastguard Worker   out->alloc (glyph_set_gsub->get_population ());
960*2d1272b8SAndroid Build Coastguard Worker   + hb_iter (glyph_set_gsub)
961*2d1272b8SAndroid Build Coastguard Worker   | hb_map ([&] (hb_codepoint_t gid) {
962*2d1272b8SAndroid Build Coastguard Worker     return hb_codepoint_pair_t (gid, glyph_map->get (gid));
963*2d1272b8SAndroid Build Coastguard Worker   })
964*2d1272b8SAndroid Build Coastguard Worker   | hb_sink (out)
965*2d1272b8SAndroid Build Coastguard Worker   ;
966*2d1272b8SAndroid Build Coastguard Worker }
967*2d1272b8SAndroid Build Coastguard Worker 
968*2d1272b8SAndroid Build Coastguard Worker static bool
_create_old_gid_to_new_gid_map(const hb_face_t * face,bool retain_gids,const hb_set_t * all_gids_to_retain,const hb_map_t * requested_glyph_map,hb_map_t * glyph_map,hb_map_t * reverse_glyph_map,hb_sorted_vector_t<hb_codepoint_pair_t> * new_to_old_gid_list,unsigned int * num_glyphs)969*2d1272b8SAndroid Build Coastguard Worker _create_old_gid_to_new_gid_map (const hb_face_t *face,
970*2d1272b8SAndroid Build Coastguard Worker 				bool		 retain_gids,
971*2d1272b8SAndroid Build Coastguard Worker 				const hb_set_t	*all_gids_to_retain,
972*2d1272b8SAndroid Build Coastguard Worker                                 const hb_map_t  *requested_glyph_map,
973*2d1272b8SAndroid Build Coastguard Worker 				hb_map_t	*glyph_map, /* OUT */
974*2d1272b8SAndroid Build Coastguard Worker 				hb_map_t	*reverse_glyph_map, /* OUT */
975*2d1272b8SAndroid Build Coastguard Worker 				hb_sorted_vector_t<hb_codepoint_pair_t> *new_to_old_gid_list /* OUT */,
976*2d1272b8SAndroid Build Coastguard Worker 				unsigned int	*num_glyphs /* OUT */)
977*2d1272b8SAndroid Build Coastguard Worker {
978*2d1272b8SAndroid Build Coastguard Worker   unsigned pop = all_gids_to_retain->get_population ();
979*2d1272b8SAndroid Build Coastguard Worker   reverse_glyph_map->alloc (pop);
980*2d1272b8SAndroid Build Coastguard Worker   glyph_map->alloc (pop);
981*2d1272b8SAndroid Build Coastguard Worker   new_to_old_gid_list->alloc (pop);
982*2d1272b8SAndroid Build Coastguard Worker 
983*2d1272b8SAndroid Build Coastguard Worker   if (*requested_glyph_map)
984*2d1272b8SAndroid Build Coastguard Worker   {
985*2d1272b8SAndroid Build Coastguard Worker     hb_set_t new_gids(requested_glyph_map->values());
986*2d1272b8SAndroid Build Coastguard Worker     if (new_gids.get_population() != requested_glyph_map->get_population())
987*2d1272b8SAndroid Build Coastguard Worker     {
988*2d1272b8SAndroid Build Coastguard Worker       DEBUG_MSG (SUBSET, nullptr, "The provided custom glyph mapping is not unique.");
989*2d1272b8SAndroid Build Coastguard Worker       return false;
990*2d1272b8SAndroid Build Coastguard Worker     }
991*2d1272b8SAndroid Build Coastguard Worker 
992*2d1272b8SAndroid Build Coastguard Worker     if (retain_gids)
993*2d1272b8SAndroid Build Coastguard Worker     {
994*2d1272b8SAndroid Build Coastguard Worker       DEBUG_MSG (SUBSET, nullptr,
995*2d1272b8SAndroid Build Coastguard Worker         "HB_SUBSET_FLAGS_RETAIN_GIDS cannot be set if "
996*2d1272b8SAndroid Build Coastguard Worker         "a custom glyph mapping has been provided.");
997*2d1272b8SAndroid Build Coastguard Worker       return false;
998*2d1272b8SAndroid Build Coastguard Worker     }
999*2d1272b8SAndroid Build Coastguard Worker 
1000*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t max_glyph = 0;
1001*2d1272b8SAndroid Build Coastguard Worker     hb_set_t remaining;
1002*2d1272b8SAndroid Build Coastguard Worker     for (auto old_gid : all_gids_to_retain->iter ())
1003*2d1272b8SAndroid Build Coastguard Worker     {
1004*2d1272b8SAndroid Build Coastguard Worker       if (old_gid == 0) {
1005*2d1272b8SAndroid Build Coastguard Worker 	new_to_old_gid_list->push (hb_pair<hb_codepoint_t, hb_codepoint_t> (0u, 0u));
1006*2d1272b8SAndroid Build Coastguard Worker         continue;
1007*2d1272b8SAndroid Build Coastguard Worker       }
1008*2d1272b8SAndroid Build Coastguard Worker 
1009*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t* new_gid;
1010*2d1272b8SAndroid Build Coastguard Worker       if (!requested_glyph_map->has (old_gid, &new_gid))
1011*2d1272b8SAndroid Build Coastguard Worker       {
1012*2d1272b8SAndroid Build Coastguard Worker         remaining.add(old_gid);
1013*2d1272b8SAndroid Build Coastguard Worker         continue;
1014*2d1272b8SAndroid Build Coastguard Worker       }
1015*2d1272b8SAndroid Build Coastguard Worker 
1016*2d1272b8SAndroid Build Coastguard Worker       if (*new_gid > max_glyph)
1017*2d1272b8SAndroid Build Coastguard Worker         max_glyph = *new_gid;
1018*2d1272b8SAndroid Build Coastguard Worker       new_to_old_gid_list->push (hb_pair (*new_gid, old_gid));
1019*2d1272b8SAndroid Build Coastguard Worker     }
1020*2d1272b8SAndroid Build Coastguard Worker     new_to_old_gid_list->qsort ();
1021*2d1272b8SAndroid Build Coastguard Worker 
1022*2d1272b8SAndroid Build Coastguard Worker     // Anything that wasn't mapped by the requested mapping should
1023*2d1272b8SAndroid Build Coastguard Worker     // be placed after the requested mapping.
1024*2d1272b8SAndroid Build Coastguard Worker     for (auto old_gid : remaining)
1025*2d1272b8SAndroid Build Coastguard Worker       new_to_old_gid_list->push (hb_pair (++max_glyph, old_gid));
1026*2d1272b8SAndroid Build Coastguard Worker 
1027*2d1272b8SAndroid Build Coastguard Worker     *num_glyphs = max_glyph + 1;
1028*2d1272b8SAndroid Build Coastguard Worker   }
1029*2d1272b8SAndroid Build Coastguard Worker   else if (!retain_gids)
1030*2d1272b8SAndroid Build Coastguard Worker   {
1031*2d1272b8SAndroid Build Coastguard Worker     + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0)
1032*2d1272b8SAndroid Build Coastguard Worker     | hb_sink (new_to_old_gid_list)
1033*2d1272b8SAndroid Build Coastguard Worker     ;
1034*2d1272b8SAndroid Build Coastguard Worker     *num_glyphs = new_to_old_gid_list->length;
1035*2d1272b8SAndroid Build Coastguard Worker   }
1036*2d1272b8SAndroid Build Coastguard Worker   else
1037*2d1272b8SAndroid Build Coastguard Worker   {
1038*2d1272b8SAndroid Build Coastguard Worker     + hb_iter (all_gids_to_retain)
1039*2d1272b8SAndroid Build Coastguard Worker     | hb_map ([] (hb_codepoint_t _) {
1040*2d1272b8SAndroid Build Coastguard Worker 		return hb_codepoint_pair_t (_, _);
1041*2d1272b8SAndroid Build Coastguard Worker 	      })
1042*2d1272b8SAndroid Build Coastguard Worker     | hb_sink (new_to_old_gid_list)
1043*2d1272b8SAndroid Build Coastguard Worker     ;
1044*2d1272b8SAndroid Build Coastguard Worker 
1045*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID;
1046*2d1272b8SAndroid Build Coastguard Worker     hb_set_previous (all_gids_to_retain, &max_glyph);
1047*2d1272b8SAndroid Build Coastguard Worker 
1048*2d1272b8SAndroid Build Coastguard Worker     *num_glyphs = max_glyph + 1;
1049*2d1272b8SAndroid Build Coastguard Worker   }
1050*2d1272b8SAndroid Build Coastguard Worker 
1051*2d1272b8SAndroid Build Coastguard Worker   reverse_glyph_map->alloc (reverse_glyph_map->get_population () + new_to_old_gid_list->length);
1052*2d1272b8SAndroid Build Coastguard Worker   + hb_iter (new_to_old_gid_list)
1053*2d1272b8SAndroid Build Coastguard Worker   | hb_sink (reverse_glyph_map)
1054*2d1272b8SAndroid Build Coastguard Worker   ;
1055*2d1272b8SAndroid Build Coastguard Worker   glyph_map->alloc (glyph_map->get_population () + new_to_old_gid_list->length);
1056*2d1272b8SAndroid Build Coastguard Worker   + hb_iter (new_to_old_gid_list)
1057*2d1272b8SAndroid Build Coastguard Worker   | hb_map (&hb_codepoint_pair_t::reverse)
1058*2d1272b8SAndroid Build Coastguard Worker   | hb_sink (glyph_map)
1059*2d1272b8SAndroid Build Coastguard Worker   ;
1060*2d1272b8SAndroid Build Coastguard Worker 
1061*2d1272b8SAndroid Build Coastguard Worker   return true;
1062*2d1272b8SAndroid Build Coastguard Worker }
1063*2d1272b8SAndroid Build Coastguard Worker 
1064*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
1065*2d1272b8SAndroid Build Coastguard Worker static void
_normalize_axes_location(hb_face_t * face,hb_subset_plan_t * plan)1066*2d1272b8SAndroid Build Coastguard Worker _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
1067*2d1272b8SAndroid Build Coastguard Worker {
1068*2d1272b8SAndroid Build Coastguard Worker   if (plan->user_axes_location.is_empty ())
1069*2d1272b8SAndroid Build Coastguard Worker     return;
1070*2d1272b8SAndroid Build Coastguard Worker 
1071*2d1272b8SAndroid Build Coastguard Worker   hb_array_t<const OT::AxisRecord> axes = face->table.fvar->get_axes ();
1072*2d1272b8SAndroid Build Coastguard Worker   plan->normalized_coords.resize (axes.length);
1073*2d1272b8SAndroid Build Coastguard Worker 
1074*2d1272b8SAndroid Build Coastguard Worker   bool has_avar = face->table.avar->has_data ();
1075*2d1272b8SAndroid Build Coastguard Worker   const OT::SegmentMaps *seg_maps = nullptr;
1076*2d1272b8SAndroid Build Coastguard Worker   unsigned avar_axis_count = 0;
1077*2d1272b8SAndroid Build Coastguard Worker   if (has_avar)
1078*2d1272b8SAndroid Build Coastguard Worker   {
1079*2d1272b8SAndroid Build Coastguard Worker     seg_maps = face->table.avar->get_segment_maps ();
1080*2d1272b8SAndroid Build Coastguard Worker     avar_axis_count = face->table.avar->get_axis_count();
1081*2d1272b8SAndroid Build Coastguard Worker   }
1082*2d1272b8SAndroid Build Coastguard Worker 
1083*2d1272b8SAndroid Build Coastguard Worker   bool axis_not_pinned = false;
1084*2d1272b8SAndroid Build Coastguard Worker   unsigned old_axis_idx = 0, new_axis_idx = 0;
1085*2d1272b8SAndroid Build Coastguard Worker   for (const auto& axis : axes)
1086*2d1272b8SAndroid Build Coastguard Worker   {
1087*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t axis_tag = axis.get_axis_tag ();
1088*2d1272b8SAndroid Build Coastguard Worker     plan->axes_old_index_tag_map.set (old_axis_idx, axis_tag);
1089*2d1272b8SAndroid Build Coastguard Worker 
1090*2d1272b8SAndroid Build Coastguard Worker     if (!plan->user_axes_location.has (axis_tag) ||
1091*2d1272b8SAndroid Build Coastguard Worker         !plan->user_axes_location.get (axis_tag).is_point ())
1092*2d1272b8SAndroid Build Coastguard Worker     {
1093*2d1272b8SAndroid Build Coastguard Worker       axis_not_pinned = true;
1094*2d1272b8SAndroid Build Coastguard Worker       plan->axes_index_map.set (old_axis_idx, new_axis_idx);
1095*2d1272b8SAndroid Build Coastguard Worker       plan->axis_tags.push (axis_tag);
1096*2d1272b8SAndroid Build Coastguard Worker       new_axis_idx++;
1097*2d1272b8SAndroid Build Coastguard Worker     }
1098*2d1272b8SAndroid Build Coastguard Worker 
1099*2d1272b8SAndroid Build Coastguard Worker     Triple *axis_range;
1100*2d1272b8SAndroid Build Coastguard Worker     if (plan->user_axes_location.has (axis_tag, &axis_range))
1101*2d1272b8SAndroid Build Coastguard Worker     {
1102*2d1272b8SAndroid Build Coastguard Worker       plan->axes_triple_distances.set (axis_tag, axis.get_triple_distances ());
1103*2d1272b8SAndroid Build Coastguard Worker 
1104*2d1272b8SAndroid Build Coastguard Worker       int normalized_min = axis.normalize_axis_value (axis_range->minimum);
1105*2d1272b8SAndroid Build Coastguard Worker       int normalized_default = axis.normalize_axis_value (axis_range->middle);
1106*2d1272b8SAndroid Build Coastguard Worker       int normalized_max = axis.normalize_axis_value (axis_range->maximum);
1107*2d1272b8SAndroid Build Coastguard Worker 
1108*2d1272b8SAndroid Build Coastguard Worker       if (has_avar && old_axis_idx < avar_axis_count)
1109*2d1272b8SAndroid Build Coastguard Worker       {
1110*2d1272b8SAndroid Build Coastguard Worker         normalized_min = seg_maps->map (normalized_min);
1111*2d1272b8SAndroid Build Coastguard Worker         normalized_default = seg_maps->map (normalized_default);
1112*2d1272b8SAndroid Build Coastguard Worker         normalized_max = seg_maps->map (normalized_max);
1113*2d1272b8SAndroid Build Coastguard Worker       }
1114*2d1272b8SAndroid Build Coastguard Worker       plan->axes_location.set (axis_tag, Triple (static_cast<double> (normalized_min / 16384.0),
1115*2d1272b8SAndroid Build Coastguard Worker                                                  static_cast<double> (normalized_default / 16384.0),
1116*2d1272b8SAndroid Build Coastguard Worker                                                  static_cast<double> (normalized_max / 16384.0)));
1117*2d1272b8SAndroid Build Coastguard Worker 
1118*2d1272b8SAndroid Build Coastguard Worker       if (normalized_default != 0)
1119*2d1272b8SAndroid Build Coastguard Worker         plan->pinned_at_default = false;
1120*2d1272b8SAndroid Build Coastguard Worker 
1121*2d1272b8SAndroid Build Coastguard Worker       plan->normalized_coords[old_axis_idx] = normalized_default;
1122*2d1272b8SAndroid Build Coastguard Worker     }
1123*2d1272b8SAndroid Build Coastguard Worker 
1124*2d1272b8SAndroid Build Coastguard Worker     old_axis_idx++;
1125*2d1272b8SAndroid Build Coastguard Worker 
1126*2d1272b8SAndroid Build Coastguard Worker     if (has_avar && old_axis_idx < avar_axis_count)
1127*2d1272b8SAndroid Build Coastguard Worker       seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
1128*2d1272b8SAndroid Build Coastguard Worker   }
1129*2d1272b8SAndroid Build Coastguard Worker   plan->all_axes_pinned = !axis_not_pinned;
1130*2d1272b8SAndroid Build Coastguard Worker }
1131*2d1272b8SAndroid Build Coastguard Worker 
1132*2d1272b8SAndroid Build Coastguard Worker static void
_update_instance_metrics_map_from_cff2(hb_subset_plan_t * plan)1133*2d1272b8SAndroid Build Coastguard Worker _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
1134*2d1272b8SAndroid Build Coastguard Worker {
1135*2d1272b8SAndroid Build Coastguard Worker   if (!plan->normalized_coords) return;
1136*2d1272b8SAndroid Build Coastguard Worker   OT::cff2::accelerator_t cff2 (plan->source);
1137*2d1272b8SAndroid Build Coastguard Worker   if (!cff2.is_valid ()) return;
1138*2d1272b8SAndroid Build Coastguard Worker 
1139*2d1272b8SAndroid Build Coastguard Worker   hb_font_t *font = _get_hb_font_with_variations (plan);
1140*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!plan->check_success (font != nullptr)))
1141*2d1272b8SAndroid Build Coastguard Worker   {
1142*2d1272b8SAndroid Build Coastguard Worker     hb_font_destroy (font);
1143*2d1272b8SAndroid Build Coastguard Worker     return;
1144*2d1272b8SAndroid Build Coastguard Worker   }
1145*2d1272b8SAndroid Build Coastguard Worker 
1146*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_extents_t extents = {0x7FFF, -0x7FFF};
1147*2d1272b8SAndroid Build Coastguard Worker   OT::hmtx_accelerator_t _hmtx (plan->source);
1148*2d1272b8SAndroid Build Coastguard Worker   float *hvar_store_cache = nullptr;
1149*2d1272b8SAndroid Build Coastguard Worker   if (_hmtx.has_data () && _hmtx.var_table.get_length ())
1150*2d1272b8SAndroid Build Coastguard Worker     hvar_store_cache = _hmtx.var_table->get_var_store ().create_cache ();
1151*2d1272b8SAndroid Build Coastguard Worker 
1152*2d1272b8SAndroid Build Coastguard Worker   OT::vmtx_accelerator_t _vmtx (plan->source);
1153*2d1272b8SAndroid Build Coastguard Worker   float *vvar_store_cache = nullptr;
1154*2d1272b8SAndroid Build Coastguard Worker   if (_vmtx.has_data () && _vmtx.var_table.get_length ())
1155*2d1272b8SAndroid Build Coastguard Worker     vvar_store_cache = _vmtx.var_table->get_var_store ().create_cache ();
1156*2d1272b8SAndroid Build Coastguard Worker 
1157*2d1272b8SAndroid Build Coastguard Worker   for (auto p : *plan->glyph_map)
1158*2d1272b8SAndroid Build Coastguard Worker   {
1159*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t old_gid = p.first;
1160*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t new_gid = p.second;
1161*2d1272b8SAndroid Build Coastguard Worker     if (!cff2.get_extents (font, old_gid, &extents)) continue;
1162*2d1272b8SAndroid Build Coastguard Worker     bool has_bounds_info = true;
1163*2d1272b8SAndroid Build Coastguard Worker     if (extents.x_bearing == 0 && extents.width == 0 &&
1164*2d1272b8SAndroid Build Coastguard Worker         extents.height == 0 && extents.y_bearing == 0)
1165*2d1272b8SAndroid Build Coastguard Worker       has_bounds_info = false;
1166*2d1272b8SAndroid Build Coastguard Worker 
1167*2d1272b8SAndroid Build Coastguard Worker     if (has_bounds_info)
1168*2d1272b8SAndroid Build Coastguard Worker     {
1169*2d1272b8SAndroid Build Coastguard Worker       plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, extents.x_bearing);
1170*2d1272b8SAndroid Build Coastguard Worker       plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, extents.x_bearing + extents.width);
1171*2d1272b8SAndroid Build Coastguard Worker       plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, extents.y_bearing);
1172*2d1272b8SAndroid Build Coastguard Worker       plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, extents.y_bearing + extents.height);
1173*2d1272b8SAndroid Build Coastguard Worker     }
1174*2d1272b8SAndroid Build Coastguard Worker 
1175*2d1272b8SAndroid Build Coastguard Worker     if (_hmtx.has_data ())
1176*2d1272b8SAndroid Build Coastguard Worker     {
1177*2d1272b8SAndroid Build Coastguard Worker       int hori_aw = _hmtx.get_advance_without_var_unscaled (old_gid);
1178*2d1272b8SAndroid Build Coastguard Worker       if (_hmtx.var_table.get_length ())
1179*2d1272b8SAndroid Build Coastguard Worker         hori_aw += (int) roundf (_hmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords,
1180*2d1272b8SAndroid Build Coastguard Worker                                                                               hvar_store_cache));
1181*2d1272b8SAndroid Build Coastguard Worker       int lsb = extents.x_bearing;
1182*2d1272b8SAndroid Build Coastguard Worker       if (!has_bounds_info)
1183*2d1272b8SAndroid Build Coastguard Worker       {
1184*2d1272b8SAndroid Build Coastguard Worker         if (!_hmtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
1185*2d1272b8SAndroid Build Coastguard Worker           continue;
1186*2d1272b8SAndroid Build Coastguard Worker       }
1187*2d1272b8SAndroid Build Coastguard Worker       plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
1188*2d1272b8SAndroid Build Coastguard Worker       plan->bounds_width_vec[new_gid] = extents.width;
1189*2d1272b8SAndroid Build Coastguard Worker     }
1190*2d1272b8SAndroid Build Coastguard Worker 
1191*2d1272b8SAndroid Build Coastguard Worker     if (_vmtx.has_data ())
1192*2d1272b8SAndroid Build Coastguard Worker     {
1193*2d1272b8SAndroid Build Coastguard Worker       int vert_aw = _vmtx.get_advance_without_var_unscaled (old_gid);
1194*2d1272b8SAndroid Build Coastguard Worker       if (_vmtx.var_table.get_length ())
1195*2d1272b8SAndroid Build Coastguard Worker         vert_aw += (int) roundf (_vmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords,
1196*2d1272b8SAndroid Build Coastguard Worker                                                                               vvar_store_cache));
1197*2d1272b8SAndroid Build Coastguard Worker 
1198*2d1272b8SAndroid Build Coastguard Worker       int tsb = extents.y_bearing;
1199*2d1272b8SAndroid Build Coastguard Worker       if (!has_bounds_info)
1200*2d1272b8SAndroid Build Coastguard Worker       {
1201*2d1272b8SAndroid Build Coastguard Worker         if (!_vmtx.get_leading_bearing_without_var_unscaled (old_gid, &tsb))
1202*2d1272b8SAndroid Build Coastguard Worker           continue;
1203*2d1272b8SAndroid Build Coastguard Worker       }
1204*2d1272b8SAndroid Build Coastguard Worker       plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
1205*2d1272b8SAndroid Build Coastguard Worker       plan->bounds_height_vec[new_gid] = extents.height;
1206*2d1272b8SAndroid Build Coastguard Worker     }
1207*2d1272b8SAndroid Build Coastguard Worker   }
1208*2d1272b8SAndroid Build Coastguard Worker   hb_font_destroy (font);
1209*2d1272b8SAndroid Build Coastguard Worker   if (hvar_store_cache)
1210*2d1272b8SAndroid Build Coastguard Worker     _hmtx.var_table->get_var_store ().destroy_cache (hvar_store_cache);
1211*2d1272b8SAndroid Build Coastguard Worker   if (vvar_store_cache)
1212*2d1272b8SAndroid Build Coastguard Worker     _vmtx.var_table->get_var_store ().destroy_cache (vvar_store_cache);
1213*2d1272b8SAndroid Build Coastguard Worker }
1214*2d1272b8SAndroid Build Coastguard Worker 
1215*2d1272b8SAndroid Build Coastguard Worker static bool
_get_instance_glyphs_contour_points(hb_subset_plan_t * plan)1216*2d1272b8SAndroid Build Coastguard Worker _get_instance_glyphs_contour_points (hb_subset_plan_t *plan)
1217*2d1272b8SAndroid Build Coastguard Worker {
1218*2d1272b8SAndroid Build Coastguard Worker   /* contour_points vector only needed for updating gvar table (infer delta and
1219*2d1272b8SAndroid Build Coastguard Worker    * iup delta optimization) during partial instancing */
1220*2d1272b8SAndroid Build Coastguard Worker   if (plan->user_axes_location.is_empty () || plan->all_axes_pinned)
1221*2d1272b8SAndroid Build Coastguard Worker     return true;
1222*2d1272b8SAndroid Build Coastguard Worker 
1223*2d1272b8SAndroid Build Coastguard Worker   OT::glyf_accelerator_t glyf (plan->source);
1224*2d1272b8SAndroid Build Coastguard Worker 
1225*2d1272b8SAndroid Build Coastguard Worker   for (auto &_ : plan->new_to_old_gid_list)
1226*2d1272b8SAndroid Build Coastguard Worker   {
1227*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t new_gid = _.first;
1228*2d1272b8SAndroid Build Coastguard Worker     contour_point_vector_t all_points;
1229*2d1272b8SAndroid Build Coastguard Worker     if (new_gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
1230*2d1272b8SAndroid Build Coastguard Worker     {
1231*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points)))
1232*2d1272b8SAndroid Build Coastguard Worker         return false;
1233*2d1272b8SAndroid Build Coastguard Worker       continue;
1234*2d1272b8SAndroid Build Coastguard Worker     }
1235*2d1272b8SAndroid Build Coastguard Worker 
1236*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t old_gid = _.second;
1237*2d1272b8SAndroid Build Coastguard Worker     auto glyph = glyf.glyph_for_gid (old_gid);
1238*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!glyph.get_all_points_without_var (plan->source, all_points)))
1239*2d1272b8SAndroid Build Coastguard Worker       return false;
1240*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points)))
1241*2d1272b8SAndroid Build Coastguard Worker       return false;
1242*2d1272b8SAndroid Build Coastguard Worker 
1243*2d1272b8SAndroid Build Coastguard Worker     /* composite new gids are only needed by iup delta optimization */
1244*2d1272b8SAndroid Build Coastguard Worker     if ((plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS) && glyph.is_composite ())
1245*2d1272b8SAndroid Build Coastguard Worker       plan->composite_new_gids.add (new_gid);
1246*2d1272b8SAndroid Build Coastguard Worker   }
1247*2d1272b8SAndroid Build Coastguard Worker   return true;
1248*2d1272b8SAndroid Build Coastguard Worker }
1249*2d1272b8SAndroid Build Coastguard Worker #endif
1250*2d1272b8SAndroid Build Coastguard Worker 
hb_subset_plan_t(hb_face_t * face,const hb_subset_input_t * input)1251*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
1252*2d1272b8SAndroid Build Coastguard Worker 				    const hb_subset_input_t *input)
1253*2d1272b8SAndroid Build Coastguard Worker {
1254*2d1272b8SAndroid Build Coastguard Worker   successful = true;
1255*2d1272b8SAndroid Build Coastguard Worker   flags = input->flags;
1256*2d1272b8SAndroid Build Coastguard Worker 
1257*2d1272b8SAndroid Build Coastguard Worker   unicode_to_new_gid_list.init ();
1258*2d1272b8SAndroid Build Coastguard Worker 
1259*2d1272b8SAndroid Build Coastguard Worker   name_ids = *input->sets.name_ids;
1260*2d1272b8SAndroid Build Coastguard Worker   name_languages = *input->sets.name_languages;
1261*2d1272b8SAndroid Build Coastguard Worker   layout_features = *input->sets.layout_features;
1262*2d1272b8SAndroid Build Coastguard Worker   layout_scripts = *input->sets.layout_scripts;
1263*2d1272b8SAndroid Build Coastguard Worker   glyphs_requested = *input->sets.glyphs;
1264*2d1272b8SAndroid Build Coastguard Worker   drop_tables = *input->sets.drop_tables;
1265*2d1272b8SAndroid Build Coastguard Worker   no_subset_tables = *input->sets.no_subset_tables;
1266*2d1272b8SAndroid Build Coastguard Worker   source = hb_face_reference (face);
1267*2d1272b8SAndroid Build Coastguard Worker   dest = hb_face_builder_create ();
1268*2d1272b8SAndroid Build Coastguard Worker 
1269*2d1272b8SAndroid Build Coastguard Worker   codepoint_to_glyph = hb_map_create ();
1270*2d1272b8SAndroid Build Coastguard Worker   glyph_map = hb_map_create ();
1271*2d1272b8SAndroid Build Coastguard Worker   reverse_glyph_map = hb_map_create ();
1272*2d1272b8SAndroid Build Coastguard Worker 
1273*2d1272b8SAndroid Build Coastguard Worker   gsub_insert_catch_all_feature_variation_rec = false;
1274*2d1272b8SAndroid Build Coastguard Worker   gpos_insert_catch_all_feature_variation_rec = false;
1275*2d1272b8SAndroid Build Coastguard Worker   gdef_varstore_inner_maps.init ();
1276*2d1272b8SAndroid Build Coastguard Worker 
1277*2d1272b8SAndroid Build Coastguard Worker   user_axes_location = input->axes_location;
1278*2d1272b8SAndroid Build Coastguard Worker   all_axes_pinned = false;
1279*2d1272b8SAndroid Build Coastguard Worker   pinned_at_default = true;
1280*2d1272b8SAndroid Build Coastguard Worker   has_gdef_varstore = false;
1281*2d1272b8SAndroid Build Coastguard Worker 
1282*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_EXPERIMENTAL_API
1283*2d1272b8SAndroid Build Coastguard Worker   for (auto _ : input->name_table_overrides)
1284*2d1272b8SAndroid Build Coastguard Worker   {
1285*2d1272b8SAndroid Build Coastguard Worker     hb_bytes_t name_bytes = _.second;
1286*2d1272b8SAndroid Build Coastguard Worker     unsigned len = name_bytes.length;
1287*2d1272b8SAndroid Build Coastguard Worker     char *name_str = (char *) hb_malloc (len);
1288*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!check_success (name_str)))
1289*2d1272b8SAndroid Build Coastguard Worker       break;
1290*2d1272b8SAndroid Build Coastguard Worker 
1291*2d1272b8SAndroid Build Coastguard Worker     hb_memcpy (name_str, name_bytes.arrayZ, len);
1292*2d1272b8SAndroid Build Coastguard Worker     name_table_overrides.set (_.first, hb_bytes_t (name_str, len));
1293*2d1272b8SAndroid Build Coastguard Worker   }
1294*2d1272b8SAndroid Build Coastguard Worker #endif
1295*2d1272b8SAndroid Build Coastguard Worker 
1296*2d1272b8SAndroid Build Coastguard Worker   void* accel = hb_face_get_user_data(face, hb_subset_accelerator_t::user_data_key());
1297*2d1272b8SAndroid Build Coastguard Worker 
1298*2d1272b8SAndroid Build Coastguard Worker   attach_accelerator_data = input->attach_accelerator_data;
1299*2d1272b8SAndroid Build Coastguard Worker   force_long_loca = input->force_long_loca;
1300*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_EXPERIMENTAL_API
1301*2d1272b8SAndroid Build Coastguard Worker   force_long_loca = force_long_loca || (flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS);
1302*2d1272b8SAndroid Build Coastguard Worker #endif
1303*2d1272b8SAndroid Build Coastguard Worker 
1304*2d1272b8SAndroid Build Coastguard Worker   if (accel)
1305*2d1272b8SAndroid Build Coastguard Worker     accelerator = (hb_subset_accelerator_t*) accel;
1306*2d1272b8SAndroid Build Coastguard Worker 
1307*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (in_error ()))
1308*2d1272b8SAndroid Build Coastguard Worker     return;
1309*2d1272b8SAndroid Build Coastguard Worker 
1310*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
1311*2d1272b8SAndroid Build Coastguard Worker   _normalize_axes_location (face, this);
1312*2d1272b8SAndroid Build Coastguard Worker #endif
1313*2d1272b8SAndroid Build Coastguard Worker 
1314*2d1272b8SAndroid Build Coastguard Worker   _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this);
1315*2d1272b8SAndroid Build Coastguard Worker 
1316*2d1272b8SAndroid Build Coastguard Worker   _populate_gids_to_retain (this, input->sets.drop_tables);
1317*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (in_error ()))
1318*2d1272b8SAndroid Build Coastguard Worker     return;
1319*2d1272b8SAndroid Build Coastguard Worker 
1320*2d1272b8SAndroid Build Coastguard Worker   if (!check_success(_create_old_gid_to_new_gid_map(
1321*2d1272b8SAndroid Build Coastguard Worker           face,
1322*2d1272b8SAndroid Build Coastguard Worker           input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,
1323*2d1272b8SAndroid Build Coastguard Worker           &_glyphset,
1324*2d1272b8SAndroid Build Coastguard Worker           &input->glyph_map,
1325*2d1272b8SAndroid Build Coastguard Worker           glyph_map,
1326*2d1272b8SAndroid Build Coastguard Worker           reverse_glyph_map,
1327*2d1272b8SAndroid Build Coastguard Worker 	  &new_to_old_gid_list,
1328*2d1272b8SAndroid Build Coastguard Worker           &_num_output_glyphs))) {
1329*2d1272b8SAndroid Build Coastguard Worker     return;
1330*2d1272b8SAndroid Build Coastguard Worker   }
1331*2d1272b8SAndroid Build Coastguard Worker 
1332*2d1272b8SAndroid Build Coastguard Worker   _create_glyph_map_gsub (
1333*2d1272b8SAndroid Build Coastguard Worker       &_glyphset_gsub,
1334*2d1272b8SAndroid Build Coastguard Worker       glyph_map,
1335*2d1272b8SAndroid Build Coastguard Worker       &glyph_map_gsub);
1336*2d1272b8SAndroid Build Coastguard Worker 
1337*2d1272b8SAndroid Build Coastguard Worker   // Now that we have old to new gid map update the unicode to new gid list.
1338*2d1272b8SAndroid Build Coastguard Worker   for (unsigned i = 0; i < unicode_to_new_gid_list.length; i++)
1339*2d1272b8SAndroid Build Coastguard Worker   {
1340*2d1272b8SAndroid Build Coastguard Worker     // Use raw array access for performance.
1341*2d1272b8SAndroid Build Coastguard Worker     unicode_to_new_gid_list.arrayZ[i].second =
1342*2d1272b8SAndroid Build Coastguard Worker         glyph_map->get(unicode_to_new_gid_list.arrayZ[i].second);
1343*2d1272b8SAndroid Build Coastguard Worker   }
1344*2d1272b8SAndroid Build Coastguard Worker 
1345*2d1272b8SAndroid Build Coastguard Worker   bounds_width_vec.resize (_num_output_glyphs, false);
1346*2d1272b8SAndroid Build Coastguard Worker   for (auto &v : bounds_width_vec)
1347*2d1272b8SAndroid Build Coastguard Worker     v = 0xFFFFFFFF;
1348*2d1272b8SAndroid Build Coastguard Worker   bounds_height_vec.resize (_num_output_glyphs, false);
1349*2d1272b8SAndroid Build Coastguard Worker   for (auto &v : bounds_height_vec)
1350*2d1272b8SAndroid Build Coastguard Worker     v = 0xFFFFFFFF;
1351*2d1272b8SAndroid Build Coastguard Worker 
1352*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables.has (HB_OT_TAG_GDEF))
1353*2d1272b8SAndroid Build Coastguard Worker     _remap_used_mark_sets (this, used_mark_sets_map);
1354*2d1272b8SAndroid Build Coastguard Worker 
1355*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
1356*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BASE
1357*2d1272b8SAndroid Build Coastguard Worker   if (!drop_tables.has (HB_OT_TAG_BASE))
1358*2d1272b8SAndroid Build Coastguard Worker     _collect_base_variation_indices (this);
1359*2d1272b8SAndroid Build Coastguard Worker #endif
1360*2d1272b8SAndroid Build Coastguard Worker #endif
1361*2d1272b8SAndroid Build Coastguard Worker 
1362*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (in_error ()))
1363*2d1272b8SAndroid Build Coastguard Worker     return;
1364*2d1272b8SAndroid Build Coastguard Worker 
1365*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
1366*2d1272b8SAndroid Build Coastguard Worker   _update_instance_metrics_map_from_cff2 (this);
1367*2d1272b8SAndroid Build Coastguard Worker   if (!check_success (_get_instance_glyphs_contour_points (this)))
1368*2d1272b8SAndroid Build Coastguard Worker       return;
1369*2d1272b8SAndroid Build Coastguard Worker #endif
1370*2d1272b8SAndroid Build Coastguard Worker 
1371*2d1272b8SAndroid Build Coastguard Worker   if (attach_accelerator_data)
1372*2d1272b8SAndroid Build Coastguard Worker   {
1373*2d1272b8SAndroid Build Coastguard Worker     inprogress_accelerator =
1374*2d1272b8SAndroid Build Coastguard Worker       hb_subset_accelerator_t::create (source,
1375*2d1272b8SAndroid Build Coastguard Worker 				       *codepoint_to_glyph,
1376*2d1272b8SAndroid Build Coastguard Worker                                        unicodes,
1377*2d1272b8SAndroid Build Coastguard Worker 				       has_seac);
1378*2d1272b8SAndroid Build Coastguard Worker 
1379*2d1272b8SAndroid Build Coastguard Worker     check_success (inprogress_accelerator);
1380*2d1272b8SAndroid Build Coastguard Worker   }
1381*2d1272b8SAndroid Build Coastguard Worker 
1382*2d1272b8SAndroid Build Coastguard Worker #define HB_SUBSET_PLAN_MEMBER(Type, Name) check_success (!Name.in_error ());
1383*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-plan-member-list.hh"
1384*2d1272b8SAndroid Build Coastguard Worker #undef HB_SUBSET_PLAN_MEMBER
1385*2d1272b8SAndroid Build Coastguard Worker }
1386*2d1272b8SAndroid Build Coastguard Worker 
~hb_subset_plan_t()1387*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_t::~hb_subset_plan_t()
1388*2d1272b8SAndroid Build Coastguard Worker {
1389*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (dest);
1390*2d1272b8SAndroid Build Coastguard Worker 
1391*2d1272b8SAndroid Build Coastguard Worker   hb_map_destroy (codepoint_to_glyph);
1392*2d1272b8SAndroid Build Coastguard Worker   hb_map_destroy (glyph_map);
1393*2d1272b8SAndroid Build Coastguard Worker   hb_map_destroy (reverse_glyph_map);
1394*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_CFF
1395*2d1272b8SAndroid Build Coastguard Worker   cff1_accel.fini ();
1396*2d1272b8SAndroid Build Coastguard Worker   cff2_accel.fini ();
1397*2d1272b8SAndroid Build Coastguard Worker #endif
1398*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (source);
1399*2d1272b8SAndroid Build Coastguard Worker 
1400*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_EXPERIMENTAL_API
1401*2d1272b8SAndroid Build Coastguard Worker   for (auto _ : name_table_overrides.iter_ref ())
1402*2d1272b8SAndroid Build Coastguard Worker     _.second.fini ();
1403*2d1272b8SAndroid Build Coastguard Worker #endif
1404*2d1272b8SAndroid Build Coastguard Worker 
1405*2d1272b8SAndroid Build Coastguard Worker   if (inprogress_accelerator)
1406*2d1272b8SAndroid Build Coastguard Worker     hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
1407*2d1272b8SAndroid Build Coastguard Worker }
1408*2d1272b8SAndroid Build Coastguard Worker 
1409*2d1272b8SAndroid Build Coastguard Worker 
1410*2d1272b8SAndroid Build Coastguard Worker /**
1411*2d1272b8SAndroid Build Coastguard Worker  * hb_subset_plan_create_or_fail:
1412*2d1272b8SAndroid Build Coastguard Worker  * @face: font face to create the plan for.
1413*2d1272b8SAndroid Build Coastguard Worker  * @input: a #hb_subset_input_t input.
1414*2d1272b8SAndroid Build Coastguard Worker  *
1415*2d1272b8SAndroid Build Coastguard Worker  * Computes a plan for subsetting the supplied face according
1416*2d1272b8SAndroid Build Coastguard Worker  * to a provided input. The plan describes
1417*2d1272b8SAndroid Build Coastguard Worker  * which tables and glyphs should be retained.
1418*2d1272b8SAndroid Build Coastguard Worker  *
1419*2d1272b8SAndroid Build Coastguard Worker  * Return value: (transfer full): New subset plan. Destroy with
1420*2d1272b8SAndroid Build Coastguard Worker  * hb_subset_plan_destroy(). If there is a failure creating the plan
1421*2d1272b8SAndroid Build Coastguard Worker  * nullptr will be returned.
1422*2d1272b8SAndroid Build Coastguard Worker  *
1423*2d1272b8SAndroid Build Coastguard Worker  * Since: 4.0.0
1424*2d1272b8SAndroid Build Coastguard Worker  **/
1425*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_t *
hb_subset_plan_create_or_fail(hb_face_t * face,const hb_subset_input_t * input)1426*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_create_or_fail (hb_face_t	 *face,
1427*2d1272b8SAndroid Build Coastguard Worker                                const hb_subset_input_t *input)
1428*2d1272b8SAndroid Build Coastguard Worker {
1429*2d1272b8SAndroid Build Coastguard Worker   hb_subset_plan_t *plan;
1430*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> (face, input))))
1431*2d1272b8SAndroid Build Coastguard Worker     return nullptr;
1432*2d1272b8SAndroid Build Coastguard Worker 
1433*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (plan->in_error ()))
1434*2d1272b8SAndroid Build Coastguard Worker   {
1435*2d1272b8SAndroid Build Coastguard Worker     hb_subset_plan_destroy (plan);
1436*2d1272b8SAndroid Build Coastguard Worker     return nullptr;
1437*2d1272b8SAndroid Build Coastguard Worker   }
1438*2d1272b8SAndroid Build Coastguard Worker 
1439*2d1272b8SAndroid Build Coastguard Worker   return plan;
1440*2d1272b8SAndroid Build Coastguard Worker }
1441*2d1272b8SAndroid Build Coastguard Worker 
1442*2d1272b8SAndroid Build Coastguard Worker /**
1443*2d1272b8SAndroid Build Coastguard Worker  * hb_subset_plan_destroy:
1444*2d1272b8SAndroid Build Coastguard Worker  * @plan: a #hb_subset_plan_t
1445*2d1272b8SAndroid Build Coastguard Worker  *
1446*2d1272b8SAndroid Build Coastguard Worker  * Decreases the reference count on @plan, and if it reaches zero, destroys
1447*2d1272b8SAndroid Build Coastguard Worker  * @plan, freeing all memory.
1448*2d1272b8SAndroid Build Coastguard Worker  *
1449*2d1272b8SAndroid Build Coastguard Worker  * Since: 4.0.0
1450*2d1272b8SAndroid Build Coastguard Worker  **/
1451*2d1272b8SAndroid Build Coastguard Worker void
hb_subset_plan_destroy(hb_subset_plan_t * plan)1452*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_destroy (hb_subset_plan_t *plan)
1453*2d1272b8SAndroid Build Coastguard Worker {
1454*2d1272b8SAndroid Build Coastguard Worker   if (!hb_object_destroy (plan)) return;
1455*2d1272b8SAndroid Build Coastguard Worker 
1456*2d1272b8SAndroid Build Coastguard Worker   hb_free (plan);
1457*2d1272b8SAndroid Build Coastguard Worker }
1458*2d1272b8SAndroid Build Coastguard Worker 
1459*2d1272b8SAndroid Build Coastguard Worker /**
1460*2d1272b8SAndroid Build Coastguard Worker  * hb_subset_plan_old_to_new_glyph_mapping:
1461*2d1272b8SAndroid Build Coastguard Worker  * @plan: a subsetting plan.
1462*2d1272b8SAndroid Build Coastguard Worker  *
1463*2d1272b8SAndroid Build Coastguard Worker  * Returns the mapping between glyphs in the original font to glyphs in the
1464*2d1272b8SAndroid Build Coastguard Worker  * subset that will be produced by @plan
1465*2d1272b8SAndroid Build Coastguard Worker  *
1466*2d1272b8SAndroid Build Coastguard Worker  * Return value: (transfer none):
1467*2d1272b8SAndroid Build Coastguard Worker  * A pointer to the #hb_map_t of the mapping.
1468*2d1272b8SAndroid Build Coastguard Worker  *
1469*2d1272b8SAndroid Build Coastguard Worker  * Since: 4.0.0
1470*2d1272b8SAndroid Build Coastguard Worker  **/
1471*2d1272b8SAndroid Build Coastguard Worker hb_map_t *
hb_subset_plan_old_to_new_glyph_mapping(const hb_subset_plan_t * plan)1472*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan)
1473*2d1272b8SAndroid Build Coastguard Worker {
1474*2d1272b8SAndroid Build Coastguard Worker   return plan->glyph_map;
1475*2d1272b8SAndroid Build Coastguard Worker }
1476*2d1272b8SAndroid Build Coastguard Worker 
1477*2d1272b8SAndroid Build Coastguard Worker /**
1478*2d1272b8SAndroid Build Coastguard Worker  * hb_subset_plan_new_to_old_glyph_mapping:
1479*2d1272b8SAndroid Build Coastguard Worker  * @plan: a subsetting plan.
1480*2d1272b8SAndroid Build Coastguard Worker  *
1481*2d1272b8SAndroid Build Coastguard Worker  * Returns the mapping between glyphs in the subset that will be produced by
1482*2d1272b8SAndroid Build Coastguard Worker  * @plan and the glyph in the original font.
1483*2d1272b8SAndroid Build Coastguard Worker  *
1484*2d1272b8SAndroid Build Coastguard Worker  * Return value: (transfer none):
1485*2d1272b8SAndroid Build Coastguard Worker  * A pointer to the #hb_map_t of the mapping.
1486*2d1272b8SAndroid Build Coastguard Worker  *
1487*2d1272b8SAndroid Build Coastguard Worker  * Since: 4.0.0
1488*2d1272b8SAndroid Build Coastguard Worker  **/
1489*2d1272b8SAndroid Build Coastguard Worker hb_map_t *
hb_subset_plan_new_to_old_glyph_mapping(const hb_subset_plan_t * plan)1490*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan)
1491*2d1272b8SAndroid Build Coastguard Worker {
1492*2d1272b8SAndroid Build Coastguard Worker   return plan->reverse_glyph_map;
1493*2d1272b8SAndroid Build Coastguard Worker }
1494*2d1272b8SAndroid Build Coastguard Worker 
1495*2d1272b8SAndroid Build Coastguard Worker /**
1496*2d1272b8SAndroid Build Coastguard Worker  * hb_subset_plan_unicode_to_old_glyph_mapping:
1497*2d1272b8SAndroid Build Coastguard Worker  * @plan: a subsetting plan.
1498*2d1272b8SAndroid Build Coastguard Worker  *
1499*2d1272b8SAndroid Build Coastguard Worker  * Returns the mapping between codepoints in the original font and the
1500*2d1272b8SAndroid Build Coastguard Worker  * associated glyph id in the original font.
1501*2d1272b8SAndroid Build Coastguard Worker  *
1502*2d1272b8SAndroid Build Coastguard Worker  * Return value: (transfer none):
1503*2d1272b8SAndroid Build Coastguard Worker  * A pointer to the #hb_map_t of the mapping.
1504*2d1272b8SAndroid Build Coastguard Worker  *
1505*2d1272b8SAndroid Build Coastguard Worker  * Since: 4.0.0
1506*2d1272b8SAndroid Build Coastguard Worker  **/
1507*2d1272b8SAndroid Build Coastguard Worker hb_map_t *
hb_subset_plan_unicode_to_old_glyph_mapping(const hb_subset_plan_t * plan)1508*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan)
1509*2d1272b8SAndroid Build Coastguard Worker {
1510*2d1272b8SAndroid Build Coastguard Worker   return plan->codepoint_to_glyph;
1511*2d1272b8SAndroid Build Coastguard Worker }
1512*2d1272b8SAndroid Build Coastguard Worker 
1513*2d1272b8SAndroid Build Coastguard Worker /**
1514*2d1272b8SAndroid Build Coastguard Worker  * hb_subset_plan_reference: (skip)
1515*2d1272b8SAndroid Build Coastguard Worker  * @plan: a #hb_subset_plan_t object.
1516*2d1272b8SAndroid Build Coastguard Worker  *
1517*2d1272b8SAndroid Build Coastguard Worker  * Increases the reference count on @plan.
1518*2d1272b8SAndroid Build Coastguard Worker  *
1519*2d1272b8SAndroid Build Coastguard Worker  * Return value: @plan.
1520*2d1272b8SAndroid Build Coastguard Worker  *
1521*2d1272b8SAndroid Build Coastguard Worker  * Since: 4.0.0
1522*2d1272b8SAndroid Build Coastguard Worker  **/
1523*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_t *
hb_subset_plan_reference(hb_subset_plan_t * plan)1524*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_reference (hb_subset_plan_t *plan)
1525*2d1272b8SAndroid Build Coastguard Worker {
1526*2d1272b8SAndroid Build Coastguard Worker   return hb_object_reference (plan);
1527*2d1272b8SAndroid Build Coastguard Worker }
1528*2d1272b8SAndroid Build Coastguard Worker 
1529*2d1272b8SAndroid Build Coastguard Worker /**
1530*2d1272b8SAndroid Build Coastguard Worker  * hb_subset_plan_set_user_data: (skip)
1531*2d1272b8SAndroid Build Coastguard Worker  * @plan: a #hb_subset_plan_t object.
1532*2d1272b8SAndroid Build Coastguard Worker  * @key: The user-data key to set
1533*2d1272b8SAndroid Build Coastguard Worker  * @data: A pointer to the user data
1534*2d1272b8SAndroid Build Coastguard Worker  * @destroy: (nullable): A callback to call when @data is not needed anymore
1535*2d1272b8SAndroid Build Coastguard Worker  * @replace: Whether to replace an existing data with the same key
1536*2d1272b8SAndroid Build Coastguard Worker  *
1537*2d1272b8SAndroid Build Coastguard Worker  * Attaches a user-data key/data pair to the given subset plan object.
1538*2d1272b8SAndroid Build Coastguard Worker  *
1539*2d1272b8SAndroid Build Coastguard Worker  * Return value: `true` if success, `false` otherwise
1540*2d1272b8SAndroid Build Coastguard Worker  *
1541*2d1272b8SAndroid Build Coastguard Worker  * Since: 4.0.0
1542*2d1272b8SAndroid Build Coastguard Worker  **/
1543*2d1272b8SAndroid Build Coastguard Worker hb_bool_t
hb_subset_plan_set_user_data(hb_subset_plan_t * plan,hb_user_data_key_t * key,void * data,hb_destroy_func_t destroy,hb_bool_t replace)1544*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_set_user_data (hb_subset_plan_t   *plan,
1545*2d1272b8SAndroid Build Coastguard Worker                               hb_user_data_key_t *key,
1546*2d1272b8SAndroid Build Coastguard Worker                               void               *data,
1547*2d1272b8SAndroid Build Coastguard Worker                               hb_destroy_func_t   destroy,
1548*2d1272b8SAndroid Build Coastguard Worker                               hb_bool_t	          replace)
1549*2d1272b8SAndroid Build Coastguard Worker {
1550*2d1272b8SAndroid Build Coastguard Worker   return hb_object_set_user_data (plan, key, data, destroy, replace);
1551*2d1272b8SAndroid Build Coastguard Worker }
1552*2d1272b8SAndroid Build Coastguard Worker 
1553*2d1272b8SAndroid Build Coastguard Worker /**
1554*2d1272b8SAndroid Build Coastguard Worker  * hb_subset_plan_get_user_data: (skip)
1555*2d1272b8SAndroid Build Coastguard Worker  * @plan: a #hb_subset_plan_t object.
1556*2d1272b8SAndroid Build Coastguard Worker  * @key: The user-data key to query
1557*2d1272b8SAndroid Build Coastguard Worker  *
1558*2d1272b8SAndroid Build Coastguard Worker  * Fetches the user data associated with the specified key,
1559*2d1272b8SAndroid Build Coastguard Worker  * attached to the specified subset plan object.
1560*2d1272b8SAndroid Build Coastguard Worker  *
1561*2d1272b8SAndroid Build Coastguard Worker  * Return value: (transfer none): A pointer to the user data
1562*2d1272b8SAndroid Build Coastguard Worker  *
1563*2d1272b8SAndroid Build Coastguard Worker  * Since: 4.0.0
1564*2d1272b8SAndroid Build Coastguard Worker  **/
1565*2d1272b8SAndroid Build Coastguard Worker void *
hb_subset_plan_get_user_data(const hb_subset_plan_t * plan,hb_user_data_key_t * key)1566*2d1272b8SAndroid Build Coastguard Worker hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
1567*2d1272b8SAndroid Build Coastguard Worker                               hb_user_data_key_t     *key)
1568*2d1272b8SAndroid Build Coastguard Worker {
1569*2d1272b8SAndroid Build Coastguard Worker   return hb_object_get_user_data (plan, key);
1570*2d1272b8SAndroid Build Coastguard Worker }
1571