/work/workdir/UnpackedTarball/harfbuzz/src/hb-subset-plan-layout.cc
Line | Count | Source |
1 | | /* |
2 | | * Copyright © 2023 Google, Inc. |
3 | | * |
4 | | * This is part of HarfBuzz, a text shaping library. |
5 | | * |
6 | | * Permission is hereby granted, without written agreement and without |
7 | | * license or royalty fees, to use, copy, modify, and distribute this |
8 | | * software and its documentation for any purpose, provided that the |
9 | | * above copyright notice and the following two paragraphs appear in |
10 | | * all copies of this software. |
11 | | * |
12 | | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
13 | | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
14 | | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
15 | | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
16 | | * DAMAGE. |
17 | | * |
18 | | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
19 | | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
20 | | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
21 | | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
22 | | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
23 | | * |
24 | | * Google Author(s): Garret Rieger, Qunxin Liu, Roderick Sheeter |
25 | | */ |
26 | | |
27 | | #include "hb-subset-plan.hh" |
28 | | |
29 | | #include "hb-ot-layout-gdef-table.hh" |
30 | | #include "hb-ot-layout-gpos-table.hh" |
31 | | #include "hb-ot-layout-gsub-table.hh" |
32 | | |
33 | | using OT::Layout::GSUB; |
34 | | using OT::Layout::GPOS; |
35 | | |
36 | | #ifndef HB_NO_SUBSET_LAYOUT |
37 | | |
38 | | float |
39 | | hb_subset_plan_t::layout_variation_delta (unsigned var_idx HB_UNUSED) |
40 | 0 | { |
41 | 0 | #ifndef HB_NO_VAR |
42 | 0 | hb_blob_ptr_t<OT::GDEF> gdef = source_table<OT::GDEF> (); |
43 | 0 | float delta = gdef->get_var_store ().get_delta (var_idx, |
44 | 0 | normalized_coords.as_array ()); |
45 | 0 | gdef.destroy (); |
46 | 0 | return delta; |
47 | | #else |
48 | | return 0.f; |
49 | | #endif |
50 | 0 | } |
51 | | |
52 | | void |
53 | | remap_used_mark_sets (hb_subset_plan_t *plan, |
54 | | hb_map_t& used_mark_sets_map) |
55 | 0 | { |
56 | 0 | hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> (); |
57 | |
|
58 | 0 | if (!gdef->has_data () || !gdef->has_mark_glyph_sets ()) |
59 | 0 | { |
60 | 0 | gdef.destroy (); |
61 | 0 | return; |
62 | 0 | } |
63 | | |
64 | 0 | hb_set_t used_mark_sets; |
65 | 0 | gdef->get_mark_glyph_sets ().collect_used_mark_sets (plan->_glyphset_gsub, used_mark_sets); |
66 | 0 | gdef.destroy (); |
67 | |
|
68 | 0 | remap_indexes (&used_mark_sets, &used_mark_sets_map); |
69 | 0 | } |
70 | | |
71 | | /* |
72 | | * Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates. |
73 | | * Returns true if anything was removed (not including duplicates). |
74 | | */ |
75 | | static bool _filter_tag_list(hb_vector_t<hb_tag_t>* tags, /* IN/OUT */ |
76 | | const hb_set_t* filter) |
77 | 0 | { |
78 | 0 | hb_vector_t<hb_tag_t> out; |
79 | 0 | out.alloc (tags->get_size() + 1); // +1 is to allocate room for the null terminator. |
80 | |
|
81 | 0 | bool removed = false; |
82 | 0 | hb_set_t visited; |
83 | |
|
84 | 0 | for (hb_tag_t tag : *tags) |
85 | 0 | { |
86 | 0 | if (!tag) continue; |
87 | 0 | if (visited.has (tag)) continue; |
88 | | |
89 | 0 | if (!filter->has (tag)) |
90 | 0 | { |
91 | 0 | removed = true; |
92 | 0 | continue; |
93 | 0 | } |
94 | | |
95 | 0 | visited.add (tag); |
96 | 0 | out.push (tag); |
97 | 0 | } |
98 | | |
99 | | // The collect function needs a null element to signal end of the array. |
100 | 0 | out.push (HB_TAG_NONE); |
101 | |
|
102 | 0 | hb_swap (out, *tags); |
103 | 0 | return removed; |
104 | 0 | } |
105 | | |
106 | | template <typename T> |
107 | | static bool |
108 | | _collect_instanced_lookup_variations ( |
109 | | hb_subset_plan_t *plan, |
110 | | const T& table, |
111 | | hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *lookup_variations) |
112 | 0 | { |
113 | 0 | hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> (); |
114 | 0 | OT::ItemVarStoreInstancer instancer (&gdef->get_var_store (), nullptr, |
115 | 0 | plan->normalized_coords.as_array ()); |
116 | 0 | hb_vector_t<unsigned> state; |
117 | 0 | unsigned variations_index; |
118 | 0 | bool success = table.get_feature_variations_state ( |
119 | 0 | plan->normalized_coords.arrayZ, |
120 | 0 | plan->normalized_coords.length, |
121 | 0 | &variations_index, |
122 | 0 | &instancer, |
123 | 0 | &state); |
124 | 0 | gdef.destroy (); |
125 | |
|
126 | 0 | if (unlikely (!success || state.in_error ())) |
127 | 0 | return plan->check_success (false); |
128 | | |
129 | 0 | unsigned i = 0; |
130 | 0 | while (i < state.length) |
131 | 0 | { |
132 | 0 | if (unlikely (state.length - i < 2)) |
133 | 0 | return plan->check_success (false); |
134 | | |
135 | 0 | unsigned feature_index = state[i++]; |
136 | 0 | unsigned lookup_count = state[i++]; |
137 | 0 | if (unlikely (lookup_count > state.length - i)) |
138 | 0 | return plan->check_success (false); |
139 | | |
140 | 0 | hb::shared_ptr<hb_set_t> lookups {hb_set_create ()}; |
141 | 0 | for (unsigned end = i + lookup_count; i < end; i++) |
142 | 0 | lookups->add (state[i]); |
143 | |
|
144 | 0 | if (unlikely (lookups->in_error () || |
145 | 0 | !lookup_variations->set (feature_index, lookups))) |
146 | 0 | return plan->check_success (false); |
147 | 0 | } |
148 | | |
149 | 0 | return true; |
150 | 0 | } Unexecuted instantiation: hb-subset-plan-layout.cc:bool _collect_instanced_lookup_variations<OT::Layout::GSUB>(hb_subset_plan_t*, OT::Layout::GSUB const&, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*) Unexecuted instantiation: hb-subset-plan-layout.cc:bool _collect_instanced_lookup_variations<OT::Layout::GPOS>(hb_subset_plan_t*, OT::Layout::GPOS const&, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*) |
151 | | |
152 | | template <typename T> |
153 | | static void _collect_layout_indices (hb_subset_plan_t *plan, |
154 | | const T& table, |
155 | | hb_set_t *lookup_indices, /* OUT */ |
156 | | hb_set_t *feature_indices, /* OUT */ |
157 | | hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */ |
158 | | hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, /* OUT */ |
159 | | hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *lookup_variations, /* OUT */ |
160 | | hb_set_t& catch_all_record_feature_idxes, /* OUT */ |
161 | | hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>>& catch_all_record_idx_feature_map /* OUT */) |
162 | 0 | { |
163 | 0 | unsigned num_features = table.get_feature_count (); |
164 | 0 | hb_vector_t<hb_tag_t> features; |
165 | 0 | if (!plan->check_success (features.resize (num_features))) return; |
166 | 0 | table.get_feature_tags (0, &num_features, features.arrayZ); |
167 | 0 | bool retain_all_features = !_filter_tag_list (&features, &plan->layout_features); |
168 | |
|
169 | 0 | unsigned num_scripts = table.get_script_count (); |
170 | 0 | hb_vector_t<hb_tag_t> scripts; |
171 | 0 | if (!plan->check_success (scripts.resize (num_scripts))) return; |
172 | 0 | table.get_script_tags (0, &num_scripts, scripts.arrayZ); |
173 | 0 | bool retain_all_scripts = !_filter_tag_list (&scripts, &plan->layout_scripts); |
174 | |
|
175 | 0 | if (!plan->check_success (!features.in_error ()) || !features |
176 | 0 | || !plan->check_success (!scripts.in_error ()) || !scripts) |
177 | 0 | return; |
178 | | |
179 | 0 | hb_ot_layout_collect_features (plan->source, |
180 | 0 | T::tableTag, |
181 | 0 | retain_all_scripts ? nullptr : scripts.arrayZ, |
182 | 0 | nullptr, |
183 | 0 | retain_all_features ? nullptr : features.arrayZ, |
184 | 0 | feature_indices); |
185 | |
|
186 | 0 | #ifndef HB_NO_VAR |
187 | | // collect feature substitutes with variations |
188 | 0 | if (!plan->user_axes_location.is_empty ()) |
189 | 0 | { |
190 | 0 | hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> (); |
191 | 0 | OT::ItemVarStoreInstancer instancer (&gdef->get_var_store (), nullptr, |
192 | 0 | plan->normalized_coords.as_array ()); |
193 | 0 | hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> conditionset_map; |
194 | 0 | OT::hb_collect_feature_substitutes_with_var_context_t c = |
195 | 0 | { |
196 | 0 | &plan->axes_old_index_tag_map, |
197 | 0 | &plan->axes_location, |
198 | 0 | feature_record_cond_idx_map, |
199 | 0 | feature_substitutes_map, |
200 | 0 | catch_all_record_feature_idxes, |
201 | 0 | feature_indices, |
202 | 0 | false, |
203 | 0 | false, |
204 | 0 | false, |
205 | 0 | 0, |
206 | 0 | &conditionset_map, |
207 | 0 | &instancer, |
208 | 0 | plan->all_axes_pinned |
209 | 0 | }; |
210 | 0 | table.collect_feature_substitutes_with_variations (&c); |
211 | 0 | gdef.destroy (); |
212 | 0 | } |
213 | 0 | #endif |
214 | |
|
215 | 0 | #ifndef HB_NO_VAR |
216 | 0 | if (plan->all_axes_pinned && |
217 | 0 | !_collect_instanced_lookup_variations (plan, table, lookup_variations)) |
218 | 0 | return; |
219 | 0 | #endif |
220 | | |
221 | 0 | for (unsigned feature_index : *feature_indices) |
222 | 0 | { |
223 | 0 | hb::shared_ptr<hb_set_t> *lookups; |
224 | 0 | if (lookup_variations->has (feature_index, &lookups)) |
225 | 0 | { |
226 | 0 | lookup_indices->union_ (**lookups); |
227 | 0 | continue; |
228 | 0 | } |
229 | | |
230 | 0 | const OT::Feature* f = &(table.get_feature (feature_index)); |
231 | 0 | const OT::Feature **p = nullptr; |
232 | 0 | if (feature_substitutes_map->has (feature_index, &p)) |
233 | 0 | f = *p; |
234 | |
|
235 | 0 | f->add_lookup_indexes_to (lookup_indices); |
236 | 0 | } |
237 | |
|
238 | 0 | #ifndef HB_NO_VAR |
239 | 0 | if (catch_all_record_feature_idxes) |
240 | 0 | { |
241 | 0 | for (unsigned feature_index : catch_all_record_feature_idxes) |
242 | 0 | { |
243 | 0 | const OT::Feature& f = table.get_feature (feature_index); |
244 | 0 | f.add_lookup_indexes_to (lookup_indices); |
245 | 0 | const void *tag = reinterpret_cast<const void*> (&(table.get_feature_list ().get_tag (feature_index))); |
246 | 0 | catch_all_record_idx_feature_map.set (feature_index, hb_pair (&f, tag)); |
247 | 0 | } |
248 | 0 | } |
249 | | |
250 | | // If all axes are pinned then all feature variations will be dropped so there's no need |
251 | | // to collect lookups from them. |
252 | 0 | if (!plan->all_axes_pinned) |
253 | 0 | table.feature_variation_collect_lookups (feature_indices, |
254 | 0 | plan->user_axes_location.is_empty () ? nullptr: feature_record_cond_idx_map, |
255 | 0 | lookup_indices); |
256 | 0 | #endif |
257 | 0 | } Unexecuted instantiation: hb-subset-plan-layout.cc:void _collect_layout_indices<OT::Layout::GSUB>(hb_subset_plan_t*, OT::Layout::GSUB const&, hb_set_t*, hb_set_t*, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*, hb_hashmap_t<unsigned int, OT::Feature const*, false>*, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*, hb_set_t&, hb_hashmap_t<unsigned int, hb_pair_t<void const*, void const*>, false>&) Unexecuted instantiation: hb-subset-plan-layout.cc:void _collect_layout_indices<OT::Layout::GPOS>(hb_subset_plan_t*, OT::Layout::GPOS const&, hb_set_t*, hb_set_t*, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*, hb_hashmap_t<unsigned int, OT::Feature const*, false>*, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*, hb_set_t&, hb_hashmap_t<unsigned int, hb_pair_t<void const*, void const*>, false>&) |
258 | | |
259 | | |
260 | | static inline void |
261 | | _GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g, |
262 | | const hb_map_t *lookup_indices, |
263 | | const hb_set_t *feature_indices, |
264 | | const hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, |
265 | | hb_map_t *duplicate_feature_map /* OUT */) |
266 | 0 | { |
267 | 0 | if (feature_indices->is_empty ()) return; |
268 | 0 | hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features; |
269 | | //find out duplicate features after subset |
270 | 0 | for (unsigned i : feature_indices->iter ()) |
271 | 0 | { |
272 | 0 | hb_tag_t t = g.get_feature_tag (i); |
273 | 0 | if (t == HB_MAP_VALUE_INVALID) continue; |
274 | 0 | if (!unique_features.has (t)) |
275 | 0 | { |
276 | 0 | if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()}))) |
277 | 0 | return; |
278 | 0 | if (unique_features.has (t)) |
279 | 0 | unique_features.get (t)->add (i); |
280 | 0 | duplicate_feature_map->set (i, i); |
281 | 0 | continue; |
282 | 0 | } |
283 | | |
284 | 0 | bool found = false; |
285 | |
|
286 | 0 | hb_set_t* same_tag_features = unique_features.get (t); |
287 | 0 | for (unsigned other_f_index : same_tag_features->iter ()) |
288 | 0 | { |
289 | 0 | #ifndef HB_NO_VAR |
290 | 0 | if (g.get_feature_variations ().has_lookup_variations (i) || |
291 | 0 | g.get_feature_variations ().has_lookup_variations (other_f_index)) |
292 | 0 | continue; |
293 | 0 | #endif |
294 | | |
295 | 0 | const OT::Feature* f = &(g.get_feature (i)); |
296 | 0 | const OT::Feature **p = nullptr; |
297 | 0 | if (feature_substitutes_map->has (i, &p)) |
298 | 0 | f = *p; |
299 | |
|
300 | 0 | const OT::Feature* other_f = &(g.get_feature (other_f_index)); |
301 | 0 | if (feature_substitutes_map->has (other_f_index, &p)) |
302 | 0 | other_f = *p; |
303 | |
|
304 | 0 | auto f_iter = |
305 | 0 | + hb_iter (f->lookupIndex) |
306 | 0 | | hb_filter (lookup_indices) |
307 | 0 | ; |
308 | |
|
309 | 0 | auto other_f_iter = |
310 | 0 | + hb_iter (other_f->lookupIndex) |
311 | 0 | | hb_filter (lookup_indices) |
312 | 0 | ; |
313 | |
|
314 | 0 | bool is_equal = true; |
315 | 0 | for (; f_iter && other_f_iter; f_iter++, other_f_iter++) |
316 | 0 | { |
317 | 0 | unsigned a = *f_iter; |
318 | 0 | unsigned b = *other_f_iter; |
319 | 0 | if (a != b) { is_equal = false; break; } |
320 | 0 | } |
321 | |
|
322 | 0 | if (is_equal == false || f_iter || other_f_iter) continue; |
323 | | |
324 | 0 | found = true; |
325 | 0 | duplicate_feature_map->set (i, other_f_index); |
326 | 0 | break; |
327 | 0 | } |
328 | |
|
329 | 0 | if (found == false) |
330 | 0 | { |
331 | 0 | same_tag_features->add (i); |
332 | 0 | duplicate_feature_map->set (i, i); |
333 | 0 | } |
334 | 0 | } |
335 | 0 | } |
336 | | |
337 | | static void |
338 | | remap_feature_indices (const hb_set_t &feature_indices, |
339 | | const hb_map_t &duplicate_feature_map, |
340 | | const hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>>& catch_all_record_idx_feature_map, |
341 | | hb_map_t *mapping, /* OUT */ |
342 | | hb_map_t *mapping_w_duplicates /* OUT */) |
343 | 0 | { |
344 | 0 | unsigned i = 0; |
345 | 0 | for (const auto _ : feature_indices) |
346 | 0 | { |
347 | | // retain those features in case we need to insert a catch-all record to reinstate the old features |
348 | 0 | if (catch_all_record_idx_feature_map.has (_)) |
349 | 0 | { |
350 | 0 | mapping->set (_, i); |
351 | 0 | mapping_w_duplicates->set (_, i); |
352 | 0 | i++; |
353 | 0 | } |
354 | 0 | else |
355 | 0 | { |
356 | 0 | uint32_t f_idx = duplicate_feature_map.get (_); |
357 | 0 | uint32_t *new_idx; |
358 | 0 | if (mapping-> has (f_idx, &new_idx)) |
359 | 0 | { |
360 | 0 | mapping_w_duplicates->set (_, *new_idx); |
361 | 0 | } |
362 | 0 | else |
363 | 0 | { |
364 | 0 | mapping->set (_, i); |
365 | 0 | mapping_w_duplicates->set (_, i); |
366 | 0 | i++; |
367 | 0 | } |
368 | 0 | } |
369 | 0 | } |
370 | 0 | } |
371 | | |
372 | | template <typename T> |
373 | | static void |
374 | | _closure_glyphs_lookups_features (hb_subset_plan_t *plan, |
375 | | hb_set_t *gids_to_retain, |
376 | | hb_map_t *lookups, |
377 | | hb_map_t *features, |
378 | | hb_map_t *features_w_duplicates, |
379 | | script_langsys_map *langsys_map, |
380 | | hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, |
381 | | hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, |
382 | | hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *lookup_variations, |
383 | | hb_set_t &catch_all_record_feature_idxes, |
384 | | hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>>& catch_all_record_idx_feature_map) |
385 | 0 | { |
386 | 0 | hb_blob_ptr_t<T> table = plan->source_table<T> (); |
387 | 0 | hb_tag_t table_tag = table->tableTag; |
388 | 0 | hb_set_t lookup_indices, feature_indices; |
389 | 0 | _collect_layout_indices<T> (plan, |
390 | 0 | *table, |
391 | 0 | &lookup_indices, |
392 | 0 | &feature_indices, |
393 | 0 | feature_record_cond_idx_map, |
394 | 0 | feature_substitutes_map, |
395 | 0 | lookup_variations, |
396 | 0 | catch_all_record_feature_idxes, |
397 | 0 | catch_all_record_idx_feature_map); |
398 | |
|
399 | 0 | if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE)) |
400 | 0 | hb_ot_layout_lookups_substitute_closure (plan->source, |
401 | 0 | &lookup_indices, |
402 | 0 | gids_to_retain); |
403 | 0 | table->closure_lookups (plan->source, |
404 | 0 | gids_to_retain, |
405 | 0 | &lookup_indices); |
406 | 0 | remap_indexes (&lookup_indices, lookups); |
407 | | |
408 | | // prune features |
409 | 0 | table->prune_features (lookups, |
410 | 0 | plan->user_axes_location.is_empty () ? nullptr : feature_record_cond_idx_map, |
411 | 0 | feature_substitutes_map, |
412 | 0 | &feature_indices); |
413 | 0 | hb_map_t duplicate_feature_map; |
414 | 0 | _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map); |
415 | |
|
416 | 0 | feature_indices.clear (); |
417 | 0 | table->prune_langsys (&duplicate_feature_map, &plan->layout_scripts, langsys_map, &feature_indices); |
418 | 0 | remap_feature_indices (feature_indices, duplicate_feature_map, catch_all_record_idx_feature_map, features, features_w_duplicates); |
419 | |
|
420 | 0 | table.destroy (); |
421 | 0 | } Unexecuted instantiation: hb-subset-plan-layout.cc:void _closure_glyphs_lookups_features<OT::Layout::GSUB>(hb_subset_plan_t*, hb_set_t*, hb_map_t*, hb_map_t*, hb_map_t*, hb_hashmap_t<unsigned int, hb::unique_ptr<hb_set_t>, false>*, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*, hb_hashmap_t<unsigned int, OT::Feature const*, false>*, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*, hb_set_t&, hb_hashmap_t<unsigned int, hb_pair_t<void const*, void const*>, false>&) Unexecuted instantiation: hb-subset-plan-layout.cc:void _closure_glyphs_lookups_features<OT::Layout::GPOS>(hb_subset_plan_t*, hb_set_t*, hb_map_t*, hb_map_t*, hb_map_t*, hb_hashmap_t<unsigned int, hb::unique_ptr<hb_set_t>, false>*, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*, hb_hashmap_t<unsigned int, OT::Feature const*, false>*, hb_hashmap_t<unsigned int, hb::shared_ptr<hb_set_t>, false>*, hb_set_t&, hb_hashmap_t<unsigned int, hb_pair_t<void const*, void const*>, false>&) |
422 | | |
423 | | void layout_nameid_closure (hb_subset_plan_t* plan, |
424 | | hb_set_t* drop_tables) |
425 | 16.3k | { |
426 | 16.3k | if (!drop_tables->has (HB_OT_TAG_GPOS)) |
427 | 0 | { |
428 | 0 | hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> (); |
429 | 0 | gpos->collect_name_ids (&plan->gpos_features, &plan->name_ids); |
430 | 0 | gpos.destroy (); |
431 | 0 | } |
432 | 16.3k | if (!drop_tables->has (HB_OT_TAG_GSUB)) |
433 | 0 | { |
434 | 0 | hb_blob_ptr_t<GSUB> gsub = plan->source_table<GSUB> (); |
435 | 0 | gsub->collect_name_ids (&plan->gsub_features, &plan->name_ids); |
436 | 0 | gsub.destroy (); |
437 | 0 | } |
438 | 16.3k | } |
439 | | |
440 | | void |
441 | | layout_populate_gids_to_retain (hb_subset_plan_t* plan, |
442 | 16.3k | hb_set_t* drop_tables) { |
443 | 16.3k | if (!drop_tables->has (HB_OT_TAG_GSUB)) |
444 | | // closure all glyphs/lookups/features needed for GSUB substitutions. |
445 | 0 | _closure_glyphs_lookups_features<GSUB> ( |
446 | 0 | plan, |
447 | 0 | &plan->_glyphset_gsub, |
448 | 0 | &plan->gsub_lookups, |
449 | 0 | &plan->gsub_features, |
450 | 0 | &plan->gsub_features_w_duplicates, |
451 | 0 | &plan->gsub_langsys, |
452 | 0 | &plan->gsub_feature_record_cond_idx_map, |
453 | 0 | &plan->gsub_feature_substitutes_map, |
454 | 0 | &plan->gsub_lookup_variations, |
455 | 0 | plan->gsub_old_features, |
456 | 0 | plan->gsub_old_feature_idx_tag_map); |
457 | | |
458 | 16.3k | if (!drop_tables->has (HB_OT_TAG_GPOS)) |
459 | 0 | _closure_glyphs_lookups_features<GPOS> ( |
460 | 0 | plan, |
461 | 0 | &plan->_glyphset_gsub, |
462 | 0 | &plan->gpos_lookups, |
463 | 0 | &plan->gpos_features, |
464 | 0 | &plan->gpos_features_w_duplicates, |
465 | 0 | &plan->gpos_langsys, |
466 | 0 | &plan->gpos_feature_record_cond_idx_map, |
467 | 0 | &plan->gpos_feature_substitutes_map, |
468 | 0 | &plan->gpos_lookup_variations, |
469 | 0 | plan->gpos_old_features, |
470 | 0 | plan->gpos_old_feature_idx_tag_map); |
471 | 16.3k | } |
472 | | |
473 | | #ifndef HB_NO_VAR |
474 | | void |
475 | | collect_layout_variation_indices (hb_subset_plan_t* plan) |
476 | 0 | { |
477 | 0 | hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> (); |
478 | 0 | hb_blob_ptr_t<GSUB> gsub = plan->source_table<GSUB> (); |
479 | 0 | hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> (); |
480 | |
|
481 | 0 | if (!gdef->has_data () || !gdef->has_var_store ()) |
482 | 0 | { |
483 | 0 | gdef.destroy (); |
484 | 0 | gsub.destroy (); |
485 | 0 | gpos.destroy (); |
486 | 0 | return; |
487 | 0 | } |
488 | | |
489 | 0 | hb_set_t varidx_set; |
490 | 0 | OT::hb_collect_variation_indices_context_t c (&varidx_set, |
491 | 0 | &plan->_glyphset_gsub, |
492 | 0 | &plan->gpos_lookups); |
493 | 0 | gdef->collect_variation_indices (&c); |
494 | |
|
495 | 0 | if (hb_ot_layout_has_substitution (plan->source)) |
496 | 0 | gsub->collect_feature_variation_indices (&c); |
497 | 0 | if (hb_ot_layout_has_positioning (plan->source)) |
498 | 0 | { |
499 | 0 | gpos->collect_feature_variation_indices (&c); |
500 | 0 | gpos->collect_variation_indices (&c); |
501 | 0 | } |
502 | |
|
503 | 0 | remap_variation_indices (gdef->get_var_store (), |
504 | 0 | varidx_set, plan->normalized_coords, |
505 | 0 | !plan->pinned_at_default, |
506 | 0 | plan->all_axes_pinned, |
507 | 0 | plan->layout_variation_idx_delta_map); |
508 | |
|
509 | 0 | unsigned subtable_count = gdef->get_var_store ().get_sub_table_count (); |
510 | 0 | generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps); |
511 | |
|
512 | 0 | gdef.destroy (); |
513 | 0 | gsub.destroy (); |
514 | 0 | gpos.destroy (); |
515 | 0 | } |
516 | | #endif |
517 | | |
518 | | #endif |