comparison mupdf-source/thirdparty/harfbuzz/src/hb-subset-plan.hh @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /*
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 *
24 * Google Author(s): Garret Rieger, Roderick Sheeter
25 */
26
27 #ifndef HB_SUBSET_PLAN_HH
28 #define HB_SUBSET_PLAN_HH
29
30 #include "hb.hh"
31
32 #include "hb-subset.h"
33 #include "hb-subset-input.hh"
34 #include "hb-subset-accelerator.hh"
35
36 #include "hb-map.hh"
37 #include "hb-bimap.hh"
38 #include "hb-set.hh"
39
40 namespace OT {
41 struct Feature;
42 }
43
44 struct hb_subset_plan_t
45 {
46 hb_subset_plan_t ()
47 {}
48
49 ~hb_subset_plan_t()
50 {
51 hb_set_destroy (unicodes);
52 hb_set_destroy (name_ids);
53 hb_set_destroy (name_languages);
54 hb_set_destroy (layout_features);
55 hb_set_destroy (layout_scripts);
56 hb_set_destroy (glyphs_requested);
57 hb_set_destroy (drop_tables);
58 hb_set_destroy (no_subset_tables);
59 hb_face_destroy (source);
60 hb_face_destroy (dest);
61 hb_map_destroy (codepoint_to_glyph);
62 hb_map_destroy (glyph_map);
63 hb_map_destroy (reverse_glyph_map);
64 hb_map_destroy (glyph_map_gsub);
65 hb_set_destroy (_glyphset);
66 hb_set_destroy (_glyphset_gsub);
67 hb_set_destroy (_glyphset_mathed);
68 hb_set_destroy (_glyphset_colred);
69 hb_map_destroy (gsub_lookups);
70 hb_map_destroy (gpos_lookups);
71 hb_map_destroy (gsub_features);
72 hb_map_destroy (gpos_features);
73 hb_map_destroy (colrv1_layers);
74 hb_map_destroy (colr_palettes);
75 hb_map_destroy (axes_index_map);
76 hb_map_destroy (axes_old_index_tag_map);
77
78 hb_hashmap_destroy (gsub_langsys);
79 hb_hashmap_destroy (gpos_langsys);
80 hb_hashmap_destroy (gsub_feature_record_cond_idx_map);
81 hb_hashmap_destroy (gpos_feature_record_cond_idx_map);
82 hb_hashmap_destroy (gsub_feature_substitutes_map);
83 hb_hashmap_destroy (gpos_feature_substitutes_map);
84 hb_hashmap_destroy (axes_location);
85 hb_hashmap_destroy (sanitized_table_cache);
86 hb_hashmap_destroy (hmtx_map);
87 hb_hashmap_destroy (vmtx_map);
88 hb_hashmap_destroy (layout_variation_idx_delta_map);
89
90 #ifdef HB_EXPERIMENTAL_API
91 if (name_table_overrides)
92 {
93 for (auto _ : *name_table_overrides)
94 _.second.fini ();
95 }
96 hb_hashmap_destroy (name_table_overrides);
97 #endif
98
99 if (inprogress_accelerator)
100 hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
101
102 if (user_axes_location)
103 {
104 hb_object_destroy (user_axes_location);
105 hb_free (user_axes_location);
106 }
107 }
108
109 hb_object_header_t header;
110
111 bool successful;
112 unsigned flags;
113 bool attach_accelerator_data = false;
114 bool force_long_loca = false;
115
116 // For each cp that we'd like to retain maps to the corresponding gid.
117 hb_set_t *unicodes;
118 hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list;
119
120 // name_ids we would like to retain
121 hb_set_t *name_ids;
122
123 // name_languages we would like to retain
124 hb_set_t *name_languages;
125
126 //layout features which will be preserved
127 hb_set_t *layout_features;
128
129 // layout scripts which will be preserved.
130 hb_set_t *layout_scripts;
131
132 //glyph ids requested to retain
133 hb_set_t *glyphs_requested;
134
135 // Tables which should not be processed, just pass them through.
136 hb_set_t *no_subset_tables;
137
138 // Tables which should be dropped.
139 hb_set_t *drop_tables;
140
141 // The glyph subset
142 hb_map_t *codepoint_to_glyph;
143
144 // Old -> New glyph id mapping
145 hb_map_t *glyph_map;
146 hb_map_t *reverse_glyph_map;
147 hb_map_t *glyph_map_gsub;
148
149 // Plan is only good for a specific source/dest so keep them with it
150 hb_face_t *source;
151 hb_face_t *dest;
152
153 unsigned int _num_output_glyphs;
154 hb_set_t *_glyphset;
155 hb_set_t *_glyphset_gsub;
156 hb_set_t *_glyphset_mathed;
157 hb_set_t *_glyphset_colred;
158
159 //active lookups we'd like to retain
160 hb_map_t *gsub_lookups;
161 hb_map_t *gpos_lookups;
162
163 //active langsys we'd like to retain
164 hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gsub_langsys;
165 hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gpos_langsys;
166
167 //active features after removing redundant langsys and prune_features
168 hb_map_t *gsub_features;
169 hb_map_t *gpos_features;
170
171 //active feature variation records/condition index with variations
172 hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gsub_feature_record_cond_idx_map;
173 hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gpos_feature_record_cond_idx_map;
174
175 //feature index-> address of substituation feature table mapping with
176 //variations
177 hb_hashmap_t<unsigned, const OT::Feature*> *gsub_feature_substitutes_map;
178 hb_hashmap_t<unsigned, const OT::Feature*> *gpos_feature_substitutes_map;
179
180 //active layers/palettes we'd like to retain
181 hb_map_t *colrv1_layers;
182 hb_map_t *colr_palettes;
183
184 //Old layout item variation index -> (New varidx, delta) mapping
185 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map;
186
187 //gdef varstore retained varidx mapping
188 hb_vector_t<hb_inc_bimap_t> gdef_varstore_inner_maps;
189
190 hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache;
191 //normalized axes location map
192 hb_hashmap_t<hb_tag_t, int> *axes_location;
193 //user specified axes location map
194 hb_hashmap_t<hb_tag_t, float> *user_axes_location;
195 //retained old axis index -> new axis index mapping in fvar axis array
196 hb_map_t *axes_index_map;
197 //axis_index->axis_tag mapping in fvar axis array
198 hb_map_t *axes_old_index_tag_map;
199 bool all_axes_pinned;
200 bool pinned_at_default;
201 bool has_seac;
202
203 //hmtx metrics map: new gid->(advance, lsb)
204 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *hmtx_map;
205 //vmtx metrics map: new gid->(advance, lsb)
206 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *vmtx_map;
207
208 #ifdef HB_EXPERIMENTAL_API
209 // name table overrides map: hb_ot_name_record_ids_t-> name string new value or
210 // None to indicate should remove
211 hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides;
212 #endif
213
214 const hb_subset_accelerator_t* accelerator;
215 hb_subset_accelerator_t* inprogress_accelerator;
216
217 public:
218
219 template<typename T>
220 hb_blob_ptr_t<T> source_table()
221 {
222 hb_lock_t (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
223
224 auto *cache = accelerator ? &accelerator->sanitized_table_cache : sanitized_table_cache;
225 if (cache
226 && !cache->in_error ()
227 && cache->has (+T::tableTag)) {
228 return hb_blob_reference (cache->get (+T::tableTag).get ());
229 }
230
231 hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)};
232 hb_blob_t* ret = hb_blob_reference (table_blob.get ());
233
234 if (likely (cache))
235 cache->set (+T::tableTag, std::move (table_blob));
236
237 return ret;
238 }
239
240 bool in_error () const { return !successful; }
241
242 bool check_success(bool success)
243 {
244 successful = (successful && success);
245 return successful;
246 }
247
248 /*
249 * The set of input glyph ids which will be retained in the subset.
250 * Does NOT include ids kept due to retain_gids. You probably want to use
251 * glyph_map/reverse_glyph_map.
252 */
253 inline const hb_set_t *
254 glyphset () const
255 {
256 return _glyphset;
257 }
258
259 /*
260 * The set of input glyph ids which will be retained in the subset.
261 */
262 inline const hb_set_t *
263 glyphset_gsub () const
264 {
265 return _glyphset_gsub;
266 }
267
268 /*
269 * The total number of output glyphs in the final subset.
270 */
271 inline unsigned int
272 num_output_glyphs () const
273 {
274 return _num_output_glyphs;
275 }
276
277 /*
278 * Given an output gid , returns true if that glyph id is an empty
279 * glyph (ie. it's a gid that we are dropping all data for).
280 */
281 inline bool is_empty_glyph (hb_codepoint_t gid) const
282 {
283 return !_glyphset->has (gid);
284 }
285
286 inline bool new_gid_for_codepoint (hb_codepoint_t codepoint,
287 hb_codepoint_t *new_gid) const
288 {
289 hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint);
290 if (old_gid == HB_MAP_VALUE_INVALID)
291 return false;
292
293 return new_gid_for_old_gid (old_gid, new_gid);
294 }
295
296 inline bool new_gid_for_old_gid (hb_codepoint_t old_gid,
297 hb_codepoint_t *new_gid) const
298 {
299 hb_codepoint_t gid = glyph_map->get (old_gid);
300 if (gid == HB_MAP_VALUE_INVALID)
301 return false;
302
303 *new_gid = gid;
304 return true;
305 }
306
307 inline bool old_gid_for_new_gid (hb_codepoint_t new_gid,
308 hb_codepoint_t *old_gid) const
309 {
310 hb_codepoint_t gid = reverse_glyph_map->get (new_gid);
311 if (gid == HB_MAP_VALUE_INVALID)
312 return false;
313
314 *old_gid = gid;
315 return true;
316 }
317
318 inline bool
319 add_table (hb_tag_t tag,
320 hb_blob_t *contents)
321 {
322 if (HB_DEBUG_SUBSET)
323 {
324 hb_blob_t *source_blob = source->reference_table (tag);
325 DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes",
326 HB_UNTAG(tag),
327 hb_blob_get_length (contents),
328 hb_blob_get_length (source_blob));
329 hb_blob_destroy (source_blob);
330 }
331 return hb_face_builder_add_table (dest, tag, contents);
332 }
333 };
334
335 #endif /* HB_SUBSET_PLAN_HH */