blob: 195378d0ee88f0d90678b309ffb8967f62c0b6cc [file] [log] [blame]
Garret Rieger1cfe6502018-02-05 15:22:30 -08001/*
2 * Copyright © 2018 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 *
Rod Sheeterd0ce3c62018-02-06 16:58:35 -080024 * Google Author(s): Garret Rieger, Roderick Sheeter
Garret Rieger1cfe6502018-02-05 15:22:30 -080025 */
26
Behdad Esfahbodaba0a942018-08-31 13:25:19 -070027#include "hb-subset-plan.hh"
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070028#include "hb-map.hh"
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070029#include "hb-set.hh"
Garret Rieger1cfe6502018-02-05 15:22:30 -080030
Behdad Esfahbodaf028122018-02-07 13:07:46 -050031#include "hb-ot-cmap-table.hh"
Garret Riegerdcac9fe2018-02-16 11:27:03 -070032#include "hb-ot-glyf-table.hh"
Qunxin Liud7c012a2020-02-26 13:11:42 -080033#include "hb-ot-layout-gdef-table.hh"
34#include "hb-ot-layout-gpos-table.hh"
Qunxin Liu973c47f2020-06-11 11:27:57 -070035#include "hb-ot-layout-gsub-table.hh"
Michiharu Ariza3787c072018-11-14 13:38:03 -080036#include "hb-ot-cff1-table.hh"
ckitagawaed857c42020-01-24 08:52:23 -050037#include "hb-ot-color-colr-table.hh"
Qunxin Liue59ffe52021-04-01 12:01:19 -070038#include "hb-ot-color-colrv1-closure.hh"
Qunxin Liu02e5e5d2019-05-13 09:38:42 -070039#include "hb-ot-var-fvar-table.hh"
40#include "hb-ot-stat-table.hh"
Behdad Esfahbodaf028122018-02-07 13:07:46 -050041
Qunxin Liu8200e482020-02-26 13:11:42 -080042
Qunxin Liu56ca4352021-01-28 15:21:26 -080043typedef hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> script_langsys_map;
Behdad Esfahboda20db492019-05-12 11:08:45 -070044#ifndef HB_NO_SUBSET_CFF
Behdad Esfahbodd43af332019-05-10 23:46:22 -070045static inline void
Michiharu Ariza3787c072018-11-14 13:38:03 -080046_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
Ebrahim Byagowic7621cf2019-10-08 13:24:26 +033047 hb_codepoint_t gid,
48 hb_set_t *gids_to_retain)
Michiharu Ariza3787c072018-11-14 13:38:03 -080049{
50 hb_codepoint_t base_gid, accent_gid;
51 if (cff.get_seac_components (gid, &base_gid, &accent_gid))
52 {
Ebrahim Byagowic7621cf2019-10-08 13:24:26 +033053 gids_to_retain->add (base_gid);
54 gids_to_retain->add (accent_gid);
Michiharu Ariza3787c072018-11-14 13:38:03 -080055 }
56}
Behdad Esfahboda20db492019-05-12 11:08:45 -070057#endif
Michiharu Ariza3787c072018-11-14 13:38:03 -080058
Qunxin Liu0b39c482019-10-22 16:00:43 -070059static void
Qunxin Liuf739e1d2021-05-11 11:44:32 -070060_remap_palette_indexes (const hb_set_t *palette_indexes,
61 hb_map_t *mapping /* OUT */)
62{
63 unsigned new_idx = 0;
64 for (unsigned palette_index : palette_indexes->iter ())
65 {
66 if (palette_index == 0xFFFF)
67 {
68 mapping->set (palette_index, palette_index);
69 continue;
70 }
71 mapping->set (palette_index, new_idx);
72 new_idx++;
73 }
74}
75
76static void
Qunxin Liu8ffc9ad2019-10-31 15:59:02 -070077_remap_indexes (const hb_set_t *indexes,
78 hb_map_t *mapping /* OUT */)
Qunxin Liu0b39c482019-10-22 16:00:43 -070079{
Qunxin Liu8ffc9ad2019-10-31 15:59:02 -070080 unsigned count = indexes->get_population ();
Qunxin Liu0b39c482019-10-22 16:00:43 -070081
Qunxin Liu8ffc9ad2019-10-31 15:59:02 -070082 for (auto _ : + hb_zip (indexes->iter (), hb_range (count)))
83 mapping->set (_.first, _.second);
Qunxin Liu0b39c482019-10-22 16:00:43 -070084
85}
86
Dominik Röttsches1dffb552021-05-18 12:31:14 +030087#ifndef HB_NO_SUBSET_LAYOUT
Qunxin Liucb5a6b52021-05-19 17:33:46 -070088typedef void (*layout_collect_func_t) (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, const hb_tag_t *languages, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */);
89
90static void _collect_subset_layout (hb_face_t *face,
91 hb_tag_t table_tag,
92 const hb_set_t *layout_features_to_retain,
93 bool retain_all_features,
94 layout_collect_func_t layout_collect_func,
95 hb_set_t *lookup_indices /* OUT */)
Garret Riegerfeb23892018-06-07 14:32:34 -070096{
Qunxin Liucb5a6b52021-05-19 17:33:46 -070097 if (retain_all_features)
98 {
99 layout_collect_func (face,
100 table_tag,
101 nullptr,
102 nullptr,
103 nullptr,
104 lookup_indices);
105 return;
106 }
107
108 if (hb_set_is_empty (layout_features_to_retain)) return;
109 unsigned num = layout_features_to_retain->get_population () + 1;
110 hb_tag_t *features = (hb_tag_t *) malloc (num * sizeof (hb_tag_t));
111 if (!features) return;
112
113 unsigned i = 0;
114 for (hb_tag_t f : layout_features_to_retain->iter ())
115 features[i++] = f;
116
117 features[i] = 0;
Garret Rieger26c80ad2021-06-18 14:14:20 -0700118
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700119 layout_collect_func (face,
120 table_tag,
121 nullptr,
122 nullptr,
123 features,
124 lookup_indices);
125
126 free (features);
127}
128
129template <typename T>
130static inline void
131_closure_glyphs_lookups_features (hb_face_t *face,
132 hb_set_t *gids_to_retain,
133 const hb_set_t *layout_features_to_retain,
134 bool retain_all_features,
135 hb_map_t *lookups,
136 hb_map_t *features,
137 script_langsys_map *langsys_map)
138{
139 hb_blob_ptr_t<T> table = hb_sanitize_context_t ().reference_table<T> (face);
140 hb_tag_t table_tag = table->tableTag;
Behdad Esfahbod3a4e5dd2018-10-29 18:05:25 -0700141 hb_set_t lookup_indices;
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700142 _collect_subset_layout (face,
143 table_tag,
144 layout_features_to_retain,
145 retain_all_features,
146 hb_ot_layout_collect_lookups,
147 &lookup_indices);
148
149 if (table_tag == HB_OT_TAG_GSUB)
150 hb_ot_layout_lookups_substitute_closure (face,
151 &lookup_indices,
152 gids_to_retain);
153 table->closure_lookups (face,
154 gids_to_retain,
Qunxin Liu973c47f2020-06-11 11:27:57 -0700155 &lookup_indices);
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700156 _remap_indexes (&lookup_indices, lookups);
Qunxin Liu8ffc9ad2019-10-31 15:59:02 -0700157
Garret Rieger718bf5a2020-09-29 13:16:01 -0700158 // Collect and prune features
Qunxin Liu8ffc9ad2019-10-31 15:59:02 -0700159 hb_set_t feature_indices;
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700160 _collect_subset_layout (face,
161 table_tag,
162 layout_features_to_retain,
163 retain_all_features,
164 hb_ot_layout_collect_features,
165 &feature_indices);
Qunxin Liu56ca4352021-01-28 15:21:26 -0800166
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700167 table->prune_features (lookups, &feature_indices);
Qunxin Liu56ca4352021-01-28 15:21:26 -0800168 hb_map_t duplicate_feature_map;
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700169 table->find_duplicate_features (lookups, &feature_indices, &duplicate_feature_map);
Qunxin Liu56ca4352021-01-28 15:21:26 -0800170
171 feature_indices.clear ();
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700172 table->prune_langsys (&duplicate_feature_map, langsys_map, &feature_indices);
173 _remap_indexes (&feature_indices, features);
Garret Rieger718bf5a2020-09-29 13:16:01 -0700174
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700175 table.destroy ();
Qunxin Liu0b39c482019-10-22 16:00:43 -0700176}
177
Dominik Röttschesc73d7ba2019-05-14 13:26:18 +0300178#endif
Garret Riegerfeb23892018-06-07 14:32:34 -0700179
Qunxin Liu8200e482020-02-26 13:11:42 -0800180#ifndef HB_NO_VAR
181static inline void
182 _collect_layout_variation_indices (hb_face_t *face,
183 const hb_set_t *glyphset,
184 const hb_map_t *gpos_lookups,
185 hb_set_t *layout_variation_indices,
186 hb_map_t *layout_variation_idx_map)
187{
Qunxin Liud7c012a2020-02-26 13:11:42 -0800188 hb_blob_ptr_t<OT::GDEF> gdef = hb_sanitize_context_t ().reference_table<OT::GDEF> (face);
189 hb_blob_ptr_t<OT::GPOS> gpos = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
190
191 if (!gdef->has_data ())
192 {
193 gdef.destroy ();
194 gpos.destroy ();
195 return;
196 }
197 OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups);
198 gdef->collect_variation_indices (&c);
199
200 if (hb_ot_layout_has_positioning (face))
201 gpos->collect_variation_indices (&c);
202
203 gdef->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map);
Ebrahim Byagowi5a7cc7f2020-07-29 08:33:32 +0430204
Qunxin Liud7c012a2020-02-26 13:11:42 -0800205 gdef.destroy ();
206 gpos.destroy ();
Qunxin Liu8200e482020-02-26 13:11:42 -0800207}
208#endif
209
Behdad Esfahbodd43af332019-05-10 23:46:22 -0700210static inline void
Qunxin Liu078ddbd2019-08-07 13:17:26 -0700211_cmap_closure (hb_face_t *face,
Ebrahim Byagowid8af4e72019-09-21 14:19:14 +0430212 const hb_set_t *unicodes,
213 hb_set_t *glyphset)
Qunxin Liu078ddbd2019-08-07 13:17:26 -0700214{
Behdad Esfahbod7152ac32019-10-28 17:12:55 -0700215 OT::cmap::accelerator_t cmap;
216 cmap.init (face);
217 cmap.table->closure_glyphs (unicodes, glyphset);
218 cmap.fini ();
Qunxin Liu078ddbd2019-08-07 13:17:26 -0700219}
220
221static inline void
Behdad Esfahbod9e9f16c2018-11-16 01:48:26 -0500222_remove_invalid_gids (hb_set_t *glyphs,
223 unsigned int num_glyphs)
224{
225 hb_codepoint_t gid = HB_SET_VALUE_INVALID;
226 while (glyphs->next (&gid))
227 {
228 if (gid >= num_glyphs)
229 glyphs->del (gid);
230 }
231}
Garret Riegerfeb23892018-06-07 14:32:34 -0700232
Garret Rieger0af9de12019-05-20 15:04:20 -0700233static void
234_populate_gids_to_retain (hb_subset_plan_t* plan,
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330235 const hb_set_t *unicodes,
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430236 const hb_set_t *input_glyphs_to_retain,
Qunxin Liu0b39c482019-10-22 16:00:43 -0700237 bool close_over_gsub,
Qunxin Liu8200e482020-02-26 13:11:42 -0800238 bool close_over_gpos,
Ebrahim Byagowi58a59612020-07-29 08:44:23 +0430239 bool close_over_gdef)
Garret Rieger25e91732018-02-05 17:26:25 -0800240{
Behdad Esfahbodaf028122018-02-07 13:07:46 -0500241 OT::cmap::accelerator_t cmap;
Garret Riegerdcac9fe2018-02-16 11:27:03 -0700242 OT::glyf::accelerator_t glyf;
blueshade7ab525ac2019-11-19 20:36:56 -0800243#ifndef HB_NO_SUBSET_CFF
Michiharu Ariza3787c072018-11-14 13:38:03 -0800244 OT::cff1::accelerator_t cff;
blueshade7ab525ac2019-11-19 20:36:56 -0800245#endif
ckitagawaed857c42020-01-24 08:52:23 -0500246 OT::COLR::accelerator_t colr;
Garret Rieger0af9de12019-05-20 15:04:20 -0700247 cmap.init (plan->source);
248 glyf.init (plan->source);
blueshade7ab525ac2019-11-19 20:36:56 -0800249#ifndef HB_NO_SUBSET_CFF
Garret Rieger0af9de12019-05-20 15:04:20 -0700250 cff.init (plan->source);
blueshade7ab525ac2019-11-19 20:36:56 -0800251#endif
ckitagawaed857c42020-01-24 08:52:23 -0500252 colr.init (plan->source);
Rod Sheeter59c658c2018-02-08 19:22:47 -0800253
Garret Rieger0af9de12019-05-20 15:04:20 -0700254 plan->_glyphset_gsub->add (0); // Not-def
255 hb_set_union (plan->_glyphset_gsub, input_glyphs_to_retain);
Rod Sheeter59c658c2018-02-08 19:22:47 -0800256
Garret Rieger251cc972018-05-30 12:23:51 -0700257 hb_codepoint_t cp = HB_SET_VALUE_INVALID;
258 while (unicodes->next (&cp))
Behdad Esfahbode5ab34f2018-02-16 16:58:17 -0800259 {
Rod Sheeterd0ce3c62018-02-06 16:58:35 -0800260 hb_codepoint_t gid;
Garret Rieger251cc972018-05-30 12:23:51 -0700261 if (!cmap.get_nominal_glyph (cp, &gid))
Behdad Esfahbode5ab34f2018-02-16 16:58:17 -0800262 {
Garret Rieger251cc972018-05-30 12:23:51 -0700263 DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
264 continue;
Rod Sheeterd0ce3c62018-02-06 16:58:35 -0800265 }
Garret Rieger0af9de12019-05-20 15:04:20 -0700266 plan->unicodes->add (cp);
267 plan->codepoint_to_glyph->set (cp, gid);
268 plan->_glyphset_gsub->add (gid);
Rod Sheeter59c658c2018-02-08 19:22:47 -0800269 }
Ebrahim Byagowid8af4e72019-09-21 14:19:14 +0430270
Qunxin Liu078ddbd2019-08-07 13:17:26 -0700271 _cmap_closure (plan->source, plan->unicodes, plan->_glyphset_gsub);
Rod Sheeter59c658c2018-02-08 19:22:47 -0800272
Behdad Esfahbodd43af332019-05-10 23:46:22 -0700273#ifndef HB_NO_SUBSET_LAYOUT
Garret Riegerfeb23892018-06-07 14:32:34 -0700274 if (close_over_gsub)
Qunxin Liu8ffc9ad2019-10-31 15:59:02 -0700275 // closure all glyphs/lookups/features needed for GSUB substitutions.
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700276 _closure_glyphs_lookups_features<OT::GSUB> (plan->source, plan->_glyphset_gsub, plan->layout_features, plan->retain_all_layout_features, plan->gsub_lookups, plan->gsub_features, plan->gsub_langsys);
Qunxin Liu0b39c482019-10-22 16:00:43 -0700277
278 if (close_over_gpos)
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700279 _closure_glyphs_lookups_features<OT::GPOS> (plan->source, plan->_glyphset_gsub, plan->layout_features, plan->retain_all_layout_features, plan->gpos_lookups, plan->gpos_features, plan->gpos_langsys);
Behdad Esfahbodd43af332019-05-10 23:46:22 -0700280#endif
Garret Rieger0af9de12019-05-20 15:04:20 -0700281 _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
Garret Riegerfeb23892018-06-07 14:32:34 -0700282
Garret Riegera08900b2021-05-04 16:48:41 -0700283 // Collect all glyphs referenced by COLRv0
284 hb_set_t* cur_glyphset = plan->_glyphset_gsub;
285 hb_set_t glyphset_colrv0;
286 if (colr.is_valid ())
287 {
Behdad Esfahbodbc33b872021-06-09 11:51:32 -0600288 glyphset_colrv0.union_ (*cur_glyphset);
Garret Riegera08900b2021-05-04 16:48:41 -0700289 for (hb_codepoint_t gid : cur_glyphset->iter ())
290 colr.closure_glyphs (gid, &glyphset_colrv0);
291 cur_glyphset = &glyphset_colrv0;
292 }
293
Garret Rieger26c80ad2021-06-18 14:14:20 -0700294 hb_set_t palette_indices;
295 colr.closure_V0palette_indices (cur_glyphset, &palette_indices);
296
297 hb_set_t layer_indices;
298 colr.closure_forV1 (cur_glyphset, &layer_indices, &palette_indices);
299 _remap_indexes (&layer_indices, plan->colrv1_layers);
300 _remap_palette_indexes (&palette_indices, plan->colr_palettes);
301 colr.fini ();
302 _remove_invalid_gids (cur_glyphset, plan->source->get_num_glyphs ());
303
Garret Riegerdcac9fe2018-02-16 11:27:03 -0700304 // Populate a full set of glyphs to retain by adding all referenced
305 // composite glyphs.
Garret Riegera08900b2021-05-04 16:48:41 -0700306 for (hb_codepoint_t gid : cur_glyphset->iter ())
Garret Rieger251cc972018-05-30 12:23:51 -0700307 {
Ebrahim Byagowibe0eddd2019-10-08 13:46:55 +0330308 glyf.add_gid_and_children (gid, plan->_glyphset);
Behdad Esfahbodd43af332019-05-10 23:46:22 -0700309#ifndef HB_NO_SUBSET_CFF
Michiharu Ariza3787c072018-11-14 13:38:03 -0800310 if (cff.is_valid ())
Garret Rieger0af9de12019-05-20 15:04:20 -0700311 _add_cff_seac_components (cff, gid, plan->_glyphset);
Behdad Esfahbodd43af332019-05-10 23:46:22 -0700312#endif
Garret Rieger251cc972018-05-30 12:23:51 -0700313 }
Garret Rieger251cc972018-05-30 12:23:51 -0700314
Garret Rieger0af9de12019-05-20 15:04:20 -0700315 _remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
Qunxin Liuf739e1d2021-05-11 11:44:32 -0700316
Behdad Esfahbod9e9f16c2018-11-16 01:48:26 -0500317
Qunxin Liu8200e482020-02-26 13:11:42 -0800318#ifndef HB_NO_VAR
319 if (close_over_gdef)
Garret Riegeraace09a2020-10-06 10:26:17 -0700320 _collect_layout_variation_indices (plan->source,
321 plan->_glyphset_gsub,
322 plan->gpos_lookups,
323 plan->layout_variation_indices,
324 plan->layout_variation_idx_map);
Qunxin Liu8200e482020-02-26 13:11:42 -0800325#endif
326
blueshade7ab525ac2019-11-19 20:36:56 -0800327#ifndef HB_NO_SUBSET_CFF
Michiharu Ariza3787c072018-11-14 13:38:03 -0800328 cff.fini ();
blueshade7ab525ac2019-11-19 20:36:56 -0800329#endif
Garret Riegerdcac9fe2018-02-16 11:27:03 -0700330 glyf.fini ();
Behdad Esfahbodaf028122018-02-07 13:07:46 -0500331 cmap.fini ();
Garret Rieger25e91732018-02-05 17:26:25 -0800332}
Garret Rieger1cfe6502018-02-05 15:22:30 -0800333
Garret Rieger251cc972018-05-30 12:23:51 -0700334static void
Garret Rieger5e3cbed2019-05-08 16:33:03 -0700335_create_old_gid_to_new_gid_map (const hb_face_t *face,
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430336 bool retain_gids,
Garret Rieger5e3cbed2019-05-08 16:33:03 -0700337 const hb_set_t *all_gids_to_retain,
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430338 hb_map_t *glyph_map, /* OUT */
339 hb_map_t *reverse_glyph_map, /* OUT */
340 unsigned int *num_glyphs /* OUT */)
Garret Rieger251cc972018-05-30 12:23:51 -0700341{
Garret Rieger5e3cbed2019-05-08 16:33:03 -0700342 if (!retain_gids)
Garret Rieger2da16542019-01-18 17:49:35 -0800343 {
Garret Rieger5e3cbed2019-05-08 16:33:03 -0700344 + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0)
345 | hb_sink (reverse_glyph_map)
346 ;
347 *num_glyphs = reverse_glyph_map->get_population ();
348 } else {
349 + hb_iter (all_gids_to_retain)
Behdad Esfahbod78d35f02019-05-15 18:15:05 -0700350 | hb_map ([] (hb_codepoint_t _) {
Garret Rieger5e3cbed2019-05-08 16:33:03 -0700351 return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, _);
352 })
Behdad Esfahbod70fe9e72019-05-13 17:35:02 -0700353 | hb_sink (reverse_glyph_map)
Garret Rieger5e3cbed2019-05-08 16:33:03 -0700354 ;
355
Garret Rieger6555f202019-05-15 09:42:38 -0700356 unsigned max_glyph =
357 + hb_iter (all_gids_to_retain)
Behdad Esfahbod6157bbe2019-07-17 11:20:08 -0700358 | hb_reduce (hb_max, 0u)
Garret Rieger6555f202019-05-15 09:42:38 -0700359 ;
360 *num_glyphs = max_glyph + 1;
Garret Rieger2da16542019-01-18 17:49:35 -0800361 }
Garret Rieger5e3cbed2019-05-08 16:33:03 -0700362
363 + reverse_glyph_map->iter ()
364 | hb_map (&hb_pair_t<hb_codepoint_t, hb_codepoint_t>::reverse)
365 | hb_sink (glyph_map)
366 ;
Garret Rieger251cc972018-05-30 12:23:51 -0700367}
368
Qunxin Liu02e5e5d2019-05-13 09:38:42 -0700369static void
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430370_nameid_closure (hb_face_t *face,
371 hb_set_t *nameids)
Qunxin Liu02e5e5d2019-05-13 09:38:42 -0700372{
Ebrahim Byagowi22037492019-08-04 11:31:31 +0430373#ifndef HB_NO_STYLE
Behdad Esfahbodb0debc32019-06-19 18:42:39 -0700374 face->table.STAT->collect_name_ids (nameids);
Behdad Esfahboda5897462019-06-19 18:36:35 -0700375#endif
Behdad Esfahboda8498732019-06-19 19:26:22 -0700376#ifndef HB_NO_VAR
Behdad Esfahbodb0debc32019-06-19 18:42:39 -0700377 face->table.fvar->collect_name_ids (nameids);
Behdad Esfahboda8498732019-06-19 19:26:22 -0700378#endif
Qunxin Liu02e5e5d2019-05-13 09:38:42 -0700379}
380
Garret Rieger1cfe6502018-02-05 15:22:30 -0800381/**
382 * hb_subset_plan_create:
383 * Computes a plan for subsetting the supplied face according
Behdad Esfahbodf39166f2018-08-29 18:09:55 -0700384 * to a provided input. The plan describes
Garret Rieger1cfe6502018-02-05 15:22:30 -0800385 * which tables and glyphs should be retained.
386 *
Garret Riegeraf46a4d2018-02-05 17:14:46 -0800387 * Return value: New subset plan.
Garret Rieger1cfe6502018-02-05 15:22:30 -0800388 *
389 * Since: 1.7.5
390 **/
391hb_subset_plan_t *
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430392hb_subset_plan_create (hb_face_t *face,
393 hb_subset_input_t *input)
Garret Rieger1cfe6502018-02-05 15:22:30 -0800394{
Garret Riegerdae32b42020-07-28 18:31:46 -0700395 hb_subset_plan_t *plan;
Ebrahim Byagowi5a7cc7f2020-07-29 08:33:32 +0430396 if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> ())))
Garret Riegerdae32b42020-07-28 18:31:46 -0700397 return const_cast<hb_subset_plan_t *> (&Null (hb_subset_plan_t));
Behdad Esfahbodc31fcf42018-02-10 14:20:10 -0600398
Garret Riegerdae32b42020-07-28 18:31:46 -0700399 plan->successful = true;
Garret Rieger251cc972018-05-30 12:23:51 -0700400 plan->drop_hints = input->drop_hints;
Michiharu Arizad56e3382018-10-31 22:30:34 -0700401 plan->desubroutinize = input->desubroutinize;
Michiharu Ariza474f3582019-04-26 10:12:38 -0700402 plan->retain_gids = input->retain_gids;
Qunxin Liu36a5c042020-01-21 13:37:28 -0800403 plan->name_legacy = input->name_legacy;
Garret Rieger73ff04a2021-05-18 16:54:01 -0700404 plan->overlaps_flag = input->overlaps_flag;
Qunxin Liud07f7892021-06-09 15:36:40 -0700405 plan->notdef_outline = input->notdef_outline;
Qunxin Liueee7b452021-06-24 10:17:46 -0700406 plan->prune_unicode_ranges = !input->no_prune_unicode_ranges;
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700407 plan->retain_all_layout_features = input->retain_all_layout_features;
Qunxin Liue501ea12019-04-05 10:05:55 -0700408 plan->unicodes = hb_set_create ();
409 plan->name_ids = hb_set_reference (input->name_ids);
Qunxin Liu02e5e5d2019-05-13 09:38:42 -0700410 _nameid_closure (face, plan->name_ids);
Qunxin Liu36a5c042020-01-21 13:37:28 -0800411 plan->name_languages = hb_set_reference (input->name_languages);
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700412 plan->layout_features = hb_set_reference (input->layout_features);
Qunxin Liub2a965d2020-04-22 15:58:41 -0700413 plan->glyphs_requested = hb_set_reference (input->glyphs);
Qunxin Liu993d81b2019-05-14 13:55:11 -0700414 plan->drop_tables = hb_set_reference (input->drop_tables);
Garret Riegerb56c9382018-02-14 16:05:39 -0800415 plan->source = hb_face_reference (face);
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700416 plan->dest = hb_face_builder_create ();
Garret Rieger0af9de12019-05-20 15:04:20 -0700417
418 plan->_glyphset = hb_set_create ();
419 plan->_glyphset_gsub = hb_set_create ();
Qunxin Liue501ea12019-04-05 10:05:55 -0700420 plan->codepoint_to_glyph = hb_map_create ();
421 plan->glyph_map = hb_map_create ();
422 plan->reverse_glyph_map = hb_map_create ();
Qunxin Liu0b39c482019-10-22 16:00:43 -0700423 plan->gsub_lookups = hb_map_create ();
424 plan->gpos_lookups = hb_map_create ();
Qunxin Liu56ca4352021-01-28 15:21:26 -0800425
Garret Rieger3c8273a2021-03-25 11:39:57 -0700426 if (plan->check_success (plan->gsub_langsys = hb_object_create<script_langsys_map> ()))
427 plan->gsub_langsys->init_shallow ();
428 if (plan->check_success (plan->gpos_langsys = hb_object_create<script_langsys_map> ()))
429 plan->gpos_langsys->init_shallow ();
430
Qunxin Liu8ffc9ad2019-10-31 15:59:02 -0700431 plan->gsub_features = hb_map_create ();
432 plan->gpos_features = hb_map_create ();
Qunxin Liue59ffe52021-04-01 12:01:19 -0700433 plan->colrv1_layers = hb_map_create ();
Qunxin Liuf739e1d2021-05-11 11:44:32 -0700434 plan->colr_palettes = hb_map_create ();
Qunxin Liu8200e482020-02-26 13:11:42 -0800435 plan->layout_variation_indices = hb_set_create ();
436 plan->layout_variation_idx_map = hb_map_create ();
Garret Rieger0af9de12019-05-20 15:04:20 -0700437
Garret Rieger3c8273a2021-03-25 11:39:57 -0700438 if (plan->in_error ()) {
439 return plan;
440 }
441
Garret Rieger0af9de12019-05-20 15:04:20 -0700442 _populate_gids_to_retain (plan,
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430443 input->unicodes,
444 input->glyphs,
Qunxin Liu0b39c482019-10-22 16:00:43 -0700445 !input->drop_tables->has (HB_OT_TAG_GSUB),
Qunxin Liu8200e482020-02-26 13:11:42 -0800446 !input->drop_tables->has (HB_OT_TAG_GPOS),
Ebrahim Byagowi58a59612020-07-29 08:44:23 +0430447 !input->drop_tables->has (HB_OT_TAG_GDEF));
Garret Riegerb7f97182019-01-17 18:55:56 -0800448
Garret Rieger198859b2019-01-28 18:10:56 -0800449 _create_old_gid_to_new_gid_map (face,
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430450 input->retain_gids,
Qunxin Liu31471332019-03-26 09:15:56 -0700451 plan->_glyphset,
Garret Rieger2da16542019-01-18 17:49:35 -0800452 plan->glyph_map,
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430453 plan->reverse_glyph_map,
454 &plan->_num_output_glyphs);
Rod Sheeterfa877702018-02-14 14:16:25 -0800455
Garret Rieger25e91732018-02-05 17:26:25 -0800456 return plan;
Garret Rieger1cfe6502018-02-05 15:22:30 -0800457}
458
Garret Rieger1cfe6502018-02-05 15:22:30 -0800459/**
460 * hb_subset_plan_destroy:
461 *
462 * Since: 1.7.5
463 **/
464void
465hb_subset_plan_destroy (hb_subset_plan_t *plan)
466{
467 if (!hb_object_destroy (plan)) return;
468
Garret Rieger251cc972018-05-30 12:23:51 -0700469 hb_set_destroy (plan->unicodes);
Qunxin Liue501ea12019-04-05 10:05:55 -0700470 hb_set_destroy (plan->name_ids);
Qunxin Liu36a5c042020-01-21 13:37:28 -0800471 hb_set_destroy (plan->name_languages);
Qunxin Liucb5a6b52021-05-19 17:33:46 -0700472 hb_set_destroy (plan->layout_features);
Qunxin Liub2a965d2020-04-22 15:58:41 -0700473 hb_set_destroy (plan->glyphs_requested);
Garret Rieger3be0ffe2019-05-16 11:29:15 -0700474 hb_set_destroy (plan->drop_tables);
Garret Riegerb56c9382018-02-14 16:05:39 -0800475 hb_face_destroy (plan->source);
476 hb_face_destroy (plan->dest);
Garret Rieger251cc972018-05-30 12:23:51 -0700477 hb_map_destroy (plan->codepoint_to_glyph);
478 hb_map_destroy (plan->glyph_map);
Garret Rieger23f36442019-01-18 18:33:21 -0800479 hb_map_destroy (plan->reverse_glyph_map);
Garret Riegerbdbe0472019-01-28 16:59:15 -0800480 hb_set_destroy (plan->_glyphset);
Garret Rieger0af9de12019-05-20 15:04:20 -0700481 hb_set_destroy (plan->_glyphset_gsub);
Qunxin Liu0b39c482019-10-22 16:00:43 -0700482 hb_map_destroy (plan->gsub_lookups);
483 hb_map_destroy (plan->gpos_lookups);
Qunxin Liu8ffc9ad2019-10-31 15:59:02 -0700484 hb_map_destroy (plan->gsub_features);
485 hb_map_destroy (plan->gpos_features);
Qunxin Liue59ffe52021-04-01 12:01:19 -0700486 hb_map_destroy (plan->colrv1_layers);
Qunxin Liuf739e1d2021-05-11 11:44:32 -0700487 hb_map_destroy (plan->colr_palettes);
Qunxin Liu8200e482020-02-26 13:11:42 -0800488 hb_set_destroy (plan->layout_variation_indices);
489 hb_map_destroy (plan->layout_variation_idx_map);
Qunxin Liu8ffc9ad2019-10-31 15:59:02 -0700490
Garret Rieger3c8273a2021-03-25 11:39:57 -0700491 if (plan->gsub_langsys)
492 {
493 for (auto _ : plan->gsub_langsys->iter ())
494 hb_set_destroy (_.second);
Qunxin Liu56ca4352021-01-28 15:21:26 -0800495
Garret Rieger3c8273a2021-03-25 11:39:57 -0700496 hb_object_destroy (plan->gsub_langsys);
497 plan->gsub_langsys->fini_shallow ();
498 free (plan->gsub_langsys);
499 }
500
501 if (plan->gpos_langsys)
502 {
503 for (auto _ : plan->gpos_langsys->iter ())
504 hb_set_destroy (_.second);
505
506 hb_object_destroy (plan->gpos_langsys);
507 plan->gpos_langsys->fini_shallow ();
508 free (plan->gpos_langsys);
509 }
Garret Riegerb56c9382018-02-14 16:05:39 -0800510
Garret Rieger1cfe6502018-02-05 15:22:30 -0800511 free (plan);
512}