/work/workdir/UnpackedTarball/harfbuzz/src/hb-subset-input.cc
Line | Count | Source |
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, Rod Sheeter, Behdad Esfahbod |
25 | | */ |
26 | | |
27 | | #include "hb-subset-instancer-solver.hh" |
28 | | #include "hb-subset.hh" |
29 | | #include "hb-set.hh" |
30 | | #include "hb-utf.hh" |
31 | | |
32 | | |
33 | | hb_subset_input_t::hb_subset_input_t () |
34 | 6.42k | { |
35 | 6.42k | for (auto& set : sets_iter ()) |
36 | 51.4k | set = hb::shared_ptr<hb_set_t> (hb_set_create ()); |
37 | | |
38 | 6.42k | if (in_error ()) |
39 | 0 | return; |
40 | | |
41 | 6.42k | flags = HB_SUBSET_FLAGS_DEFAULT; |
42 | | |
43 | 6.42k | hb_set_add_range (sets.name_ids, 0, 6); |
44 | 6.42k | hb_set_add (sets.name_languages, 0x0409); |
45 | | |
46 | 6.42k | hb_tag_t default_drop_tables[] = { |
47 | | // Layout disabled by default |
48 | 6.42k | HB_TAG ('m', 'o', 'r', 'x'), |
49 | 6.42k | HB_TAG ('m', 'o', 'r', 't'), |
50 | 6.42k | HB_TAG ('k', 'e', 'r', 'x'), |
51 | 6.42k | HB_TAG ('k', 'e', 'r', 'n'), |
52 | | |
53 | | // Copied from fontTools: |
54 | 6.42k | HB_TAG ('J', 'S', 'T', 'F'), |
55 | 6.42k | HB_TAG ('D', 'S', 'I', 'G'), |
56 | 6.42k | HB_TAG ('E', 'B', 'D', 'T'), |
57 | 6.42k | HB_TAG ('E', 'B', 'L', 'C'), |
58 | 6.42k | HB_TAG ('E', 'B', 'S', 'C'), |
59 | 6.42k | HB_TAG ('S', 'V', 'G', ' '), |
60 | 6.42k | HB_TAG ('P', 'C', 'L', 'T'), |
61 | 6.42k | HB_TAG ('L', 'T', 'S', 'H'), |
62 | | // Graphite tables |
63 | 6.42k | HB_TAG ('F', 'e', 'a', 't'), |
64 | 6.42k | HB_TAG ('G', 'l', 'a', 't'), |
65 | 6.42k | HB_TAG ('G', 'l', 'o', 'c'), |
66 | 6.42k | HB_TAG ('S', 'i', 'l', 'f'), |
67 | 6.42k | HB_TAG ('S', 'i', 'l', 'l'), |
68 | 6.42k | }; |
69 | 6.42k | sets.drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables)); |
70 | | |
71 | 6.42k | hb_tag_t default_no_subset_tables[] = { |
72 | 6.42k | HB_TAG ('g', 'a', 's', 'p'), |
73 | 6.42k | HB_TAG ('f', 'p', 'g', 'm'), |
74 | 6.42k | HB_TAG ('p', 'r', 'e', 'p'), |
75 | 6.42k | HB_TAG ('V', 'D', 'M', 'X'), |
76 | 6.42k | HB_TAG ('D', 'S', 'I', 'G'), |
77 | 6.42k | }; |
78 | 6.42k | sets.no_subset_tables->add_array (default_no_subset_tables, |
79 | 6.42k | ARRAY_LENGTH (default_no_subset_tables)); |
80 | | |
81 | | //copied from _layout_features_groups in fonttools |
82 | 6.42k | hb_tag_t default_layout_features[] = { |
83 | | // default shaper |
84 | | // common |
85 | 6.42k | HB_TAG ('r', 'v', 'r', 'n'), |
86 | 6.42k | HB_TAG ('c', 'c', 'm', 'p'), |
87 | 6.42k | HB_TAG ('l', 'i', 'g', 'a'), |
88 | 6.42k | HB_TAG ('l', 'o', 'c', 'l'), |
89 | 6.42k | HB_TAG ('m', 'a', 'r', 'k'), |
90 | 6.42k | HB_TAG ('m', 'k', 'm', 'k'), |
91 | 6.42k | HB_TAG ('r', 'l', 'i', 'g'), |
92 | | |
93 | | //fractions |
94 | 6.42k | HB_TAG ('f', 'r', 'a', 'c'), |
95 | 6.42k | HB_TAG ('n', 'u', 'm', 'r'), |
96 | 6.42k | HB_TAG ('d', 'n', 'o', 'm'), |
97 | | |
98 | | //horizontal |
99 | 6.42k | HB_TAG ('c', 'a', 'l', 't'), |
100 | 6.42k | HB_TAG ('c', 'l', 'i', 'g'), |
101 | 6.42k | HB_TAG ('c', 'u', 'r', 's'), |
102 | 6.42k | HB_TAG ('k', 'e', 'r', 'n'), |
103 | 6.42k | HB_TAG ('r', 'c', 'l', 't'), |
104 | | |
105 | | //vertical |
106 | 6.42k | HB_TAG ('v', 'a', 'l', 't'), |
107 | 6.42k | HB_TAG ('v', 'e', 'r', 't'), |
108 | 6.42k | HB_TAG ('v', 'k', 'r', 'n'), |
109 | 6.42k | HB_TAG ('v', 'p', 'a', 'l'), |
110 | 6.42k | HB_TAG ('v', 'r', 't', '2'), |
111 | | |
112 | | //ltr |
113 | 6.42k | HB_TAG ('l', 't', 'r', 'a'), |
114 | 6.42k | HB_TAG ('l', 't', 'r', 'm'), |
115 | | |
116 | | //rtl |
117 | 6.42k | HB_TAG ('r', 't', 'l', 'a'), |
118 | 6.42k | HB_TAG ('r', 't', 'l', 'm'), |
119 | | |
120 | | //random |
121 | 6.42k | HB_TAG ('r', 'a', 'n', 'd'), |
122 | | |
123 | | //justify |
124 | 6.42k | HB_TAG ('j', 'a', 'l', 't'), // HarfBuzz doesn't use; others might |
125 | | |
126 | | //East Asian spacing |
127 | 6.42k | HB_TAG ('c', 'h', 'w', 's'), |
128 | 6.42k | HB_TAG ('v', 'c', 'h', 'w'), |
129 | 6.42k | HB_TAG ('h', 'a', 'l', 't'), |
130 | 6.42k | HB_TAG ('v', 'h', 'a', 'l'), |
131 | 6.42k | HB_TAG ('p', 'a', 'l', 't'), |
132 | | |
133 | | //private |
134 | 6.42k | HB_TAG ('H', 'a', 'r', 'f'), |
135 | 6.42k | HB_TAG ('H', 'A', 'R', 'F'), |
136 | 6.42k | HB_TAG ('B', 'u', 'z', 'z'), |
137 | 6.42k | HB_TAG ('B', 'U', 'Z', 'Z'), |
138 | | |
139 | | //shapers |
140 | | |
141 | | //arabic |
142 | 6.42k | HB_TAG ('i', 'n', 'i', 't'), |
143 | 6.42k | HB_TAG ('m', 'e', 'd', 'i'), |
144 | 6.42k | HB_TAG ('f', 'i', 'n', 'a'), |
145 | 6.42k | HB_TAG ('i', 's', 'o', 'l'), |
146 | 6.42k | HB_TAG ('m', 'e', 'd', '2'), |
147 | 6.42k | HB_TAG ('f', 'i', 'n', '2'), |
148 | 6.42k | HB_TAG ('f', 'i', 'n', '3'), |
149 | 6.42k | HB_TAG ('c', 's', 'w', 'h'), |
150 | 6.42k | HB_TAG ('m', 's', 'e', 't'), |
151 | 6.42k | HB_TAG ('s', 't', 'c', 'h'), |
152 | | |
153 | | //hangul |
154 | 6.42k | HB_TAG ('l', 'j', 'm', 'o'), |
155 | 6.42k | HB_TAG ('v', 'j', 'm', 'o'), |
156 | 6.42k | HB_TAG ('t', 'j', 'm', 'o'), |
157 | | |
158 | | //tibetan |
159 | 6.42k | HB_TAG ('a', 'b', 'v', 's'), |
160 | 6.42k | HB_TAG ('b', 'l', 'w', 's'), |
161 | 6.42k | HB_TAG ('a', 'b', 'v', 'm'), |
162 | 6.42k | HB_TAG ('b', 'l', 'w', 'm'), |
163 | | |
164 | | //indic |
165 | 6.42k | HB_TAG ('n', 'u', 'k', 't'), |
166 | 6.42k | HB_TAG ('a', 'k', 'h', 'n'), |
167 | 6.42k | HB_TAG ('r', 'p', 'h', 'f'), |
168 | 6.42k | HB_TAG ('r', 'k', 'r', 'f'), |
169 | 6.42k | HB_TAG ('p', 'r', 'e', 'f'), |
170 | 6.42k | HB_TAG ('b', 'l', 'w', 'f'), |
171 | 6.42k | HB_TAG ('h', 'a', 'l', 'f'), |
172 | 6.42k | HB_TAG ('a', 'b', 'v', 'f'), |
173 | 6.42k | HB_TAG ('p', 's', 't', 'f'), |
174 | 6.42k | HB_TAG ('c', 'f', 'a', 'r'), |
175 | 6.42k | HB_TAG ('v', 'a', 't', 'u'), |
176 | 6.42k | HB_TAG ('c', 'j', 'c', 't'), |
177 | 6.42k | HB_TAG ('i', 'n', 'i', 't'), |
178 | 6.42k | HB_TAG ('p', 'r', 'e', 's'), |
179 | 6.42k | HB_TAG ('a', 'b', 'v', 's'), |
180 | 6.42k | HB_TAG ('b', 'l', 'w', 's'), |
181 | 6.42k | HB_TAG ('p', 's', 't', 's'), |
182 | 6.42k | HB_TAG ('h', 'a', 'l', 'n'), |
183 | 6.42k | HB_TAG ('d', 'i', 's', 't'), |
184 | 6.42k | HB_TAG ('a', 'b', 'v', 'm'), |
185 | 6.42k | HB_TAG ('b', 'l', 'w', 'm'), |
186 | 6.42k | }; |
187 | | |
188 | 6.42k | sets.layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features)); |
189 | | |
190 | 6.42k | sets.layout_scripts->invert (); // Default to all scripts. |
191 | 6.42k | } |
192 | | |
193 | | /** |
194 | | * hb_subset_input_create_or_fail: |
195 | | * |
196 | | * Creates a new subset input object. |
197 | | * |
198 | | * Return value: (transfer full): New subset input, or `NULL` if failed. Destroy |
199 | | * with hb_subset_input_destroy(). |
200 | | * |
201 | | * Since: 1.8.0 |
202 | | **/ |
203 | | hb_subset_input_t * |
204 | | hb_subset_input_create_or_fail (void) |
205 | 6.42k | { |
206 | 6.42k | hb_subset_input_t *input = hb_object_create<hb_subset_input_t>(); |
207 | | |
208 | 6.42k | if (unlikely (!input)) |
209 | 0 | return nullptr; |
210 | | |
211 | 6.42k | if (input->in_error ()) |
212 | 0 | { |
213 | 0 | hb_subset_input_destroy (input); |
214 | 0 | return nullptr; |
215 | 0 | } |
216 | | |
217 | 6.42k | return input; |
218 | 6.42k | } |
219 | | |
220 | | /** |
221 | | * hb_subset_input_reference: (skip) |
222 | | * @input: a #hb_subset_input_t object. |
223 | | * |
224 | | * Increases the reference count on @input. |
225 | | * |
226 | | * Return value: @input. |
227 | | * |
228 | | * Since: 1.8.0 |
229 | | **/ |
230 | | hb_subset_input_t * |
231 | | hb_subset_input_reference (hb_subset_input_t *input) |
232 | 0 | { |
233 | 0 | return hb_object_reference (input); |
234 | 0 | } |
235 | | |
236 | | /** |
237 | | * hb_subset_input_destroy: |
238 | | * @input: a #hb_subset_input_t object. |
239 | | * |
240 | | * Decreases the reference count on @input, and if it reaches zero, destroys |
241 | | * @input, freeing all memory. |
242 | | * |
243 | | * Since: 1.8.0 |
244 | | **/ |
245 | | void |
246 | | hb_subset_input_destroy (hb_subset_input_t *input) |
247 | 6.42k | { |
248 | 6.42k | if (!hb_object_destroy (input)) return; |
249 | | |
250 | 6.42k | hb_free (input); |
251 | 6.42k | } |
252 | | |
253 | | /** |
254 | | * hb_subset_input_unicode_set: |
255 | | * @input: a #hb_subset_input_t object. |
256 | | * |
257 | | * Gets the set of Unicode code points to retain, the caller should modify the |
258 | | * set as needed. |
259 | | * |
260 | | * Return value: (transfer none): pointer to the #hb_set_t of Unicode code |
261 | | * points. |
262 | | * |
263 | | * Since: 1.8.0 |
264 | | **/ |
265 | | HB_EXTERN hb_set_t * |
266 | | hb_subset_input_unicode_set (hb_subset_input_t *input) |
267 | 0 | { |
268 | 0 | return input->sets.unicodes; |
269 | 0 | } |
270 | | |
271 | | /** |
272 | | * hb_subset_input_glyph_set: |
273 | | * @input: a #hb_subset_input_t object. |
274 | | * |
275 | | * Gets the set of glyph IDs to retain, the caller should modify the set as |
276 | | * needed. |
277 | | * |
278 | | * Return value: (transfer none): pointer to the #hb_set_t of glyph IDs. |
279 | | * |
280 | | * Since: 1.8.0 |
281 | | **/ |
282 | | HB_EXTERN hb_set_t * |
283 | | hb_subset_input_glyph_set (hb_subset_input_t *input) |
284 | 6.42k | { |
285 | 6.42k | return input->sets.glyphs; |
286 | 6.42k | } |
287 | | |
288 | | /** |
289 | | * hb_subset_input_set: |
290 | | * @input: a #hb_subset_input_t object. |
291 | | * @set_type: a #hb_subset_sets_t set type. |
292 | | * |
293 | | * Gets the set of the specified type. |
294 | | * |
295 | | * Return value: (transfer none): pointer to the #hb_set_t of the specified type. |
296 | | * |
297 | | * Since: 2.9.1 |
298 | | **/ |
299 | | HB_EXTERN hb_set_t * |
300 | | hb_subset_input_set (hb_subset_input_t *input, hb_subset_sets_t set_type) |
301 | 6.42k | { |
302 | 6.42k | return input->sets_iter () [set_type]; |
303 | 6.42k | } |
304 | | |
305 | | /** |
306 | | * hb_subset_input_get_flags: |
307 | | * @input: a #hb_subset_input_t object. |
308 | | * |
309 | | * Gets all of the subsetting flags in the input object. |
310 | | * |
311 | | * Return value: the subsetting flags bit field. |
312 | | * |
313 | | * Since: 2.9.0 |
314 | | **/ |
315 | | HB_EXTERN hb_subset_flags_t |
316 | | hb_subset_input_get_flags (hb_subset_input_t *input) |
317 | 0 | { |
318 | 0 | return (hb_subset_flags_t) input->flags; |
319 | 0 | } |
320 | | |
321 | | /** |
322 | | * hb_subset_input_set_flags: |
323 | | * @input: a #hb_subset_input_t object. |
324 | | * @value: bit field of flags |
325 | | * |
326 | | * Sets all of the flags in the input object to the values specified by the bit |
327 | | * field. |
328 | | * |
329 | | * Since: 2.9.0 |
330 | | **/ |
331 | | HB_EXTERN void |
332 | | hb_subset_input_set_flags (hb_subset_input_t *input, |
333 | | unsigned value) |
334 | 6.42k | { |
335 | 6.42k | input->flags = (hb_subset_flags_t) value; |
336 | 6.42k | } |
337 | | |
338 | | /** |
339 | | * hb_subset_input_set_user_data: (skip) |
340 | | * @input: a #hb_subset_input_t object. |
341 | | * @key: The user-data key to set |
342 | | * @data: A pointer to the user data |
343 | | * @destroy: (nullable): A callback to call when @data is not needed anymore |
344 | | * @replace: Whether to replace an existing data with the same key |
345 | | * |
346 | | * Attaches a user-data key/data pair to the given subset input object. |
347 | | * |
348 | | * Return value: `true` if success, `false` otherwise |
349 | | * |
350 | | * Since: 2.9.0 |
351 | | **/ |
352 | | hb_bool_t |
353 | | hb_subset_input_set_user_data (hb_subset_input_t *input, |
354 | | hb_user_data_key_t *key, |
355 | | void * data, |
356 | | hb_destroy_func_t destroy, |
357 | | hb_bool_t replace) |
358 | 0 | { |
359 | 0 | return hb_object_set_user_data (input, key, data, destroy, replace); |
360 | 0 | } |
361 | | |
362 | | /** |
363 | | * hb_subset_input_get_user_data: (skip) |
364 | | * @input: a #hb_subset_input_t object. |
365 | | * @key: The user-data key to query |
366 | | * |
367 | | * Fetches the user data associated with the specified key, |
368 | | * attached to the specified subset input object. |
369 | | * |
370 | | * Return value: (transfer none): A pointer to the user data |
371 | | * |
372 | | * Since: 2.9.0 |
373 | | **/ |
374 | | void * |
375 | | hb_subset_input_get_user_data (const hb_subset_input_t *input, |
376 | | hb_user_data_key_t *key) |
377 | 0 | { |
378 | 0 | return hb_object_get_user_data (input, key); |
379 | 0 | } |
380 | | |
381 | | /** |
382 | | * hb_subset_input_keep_everything: |
383 | | * @input: a #hb_subset_input_t object |
384 | | * |
385 | | * Configure input object to keep everything in the font face. |
386 | | * That is, all Unicodes, glyphs, names, layout items, |
387 | | * glyph names, etc. |
388 | | * |
389 | | * The input can be tailored afterwards by the caller. |
390 | | * |
391 | | * Since: 7.0.0 |
392 | | */ |
393 | | void |
394 | | hb_subset_input_keep_everything (hb_subset_input_t *input) |
395 | 0 | { |
396 | 0 | const hb_subset_sets_t indices[] = {HB_SUBSET_SETS_UNICODE, |
397 | 0 | HB_SUBSET_SETS_GLYPH_INDEX, |
398 | 0 | HB_SUBSET_SETS_NAME_ID, |
399 | 0 | HB_SUBSET_SETS_NAME_LANG_ID, |
400 | 0 | HB_SUBSET_SETS_LAYOUT_FEATURE_TAG, |
401 | 0 | HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG}; |
402 | |
|
403 | 0 | for (auto idx : hb_iter (indices)) |
404 | 0 | { |
405 | 0 | hb_set_t *set = hb_subset_input_set (input, idx); |
406 | 0 | hb_set_clear (set); |
407 | 0 | hb_set_invert (set); |
408 | 0 | } |
409 | | |
410 | | // Don't drop any tables |
411 | 0 | hb_set_clear (hb_subset_input_set (input, HB_SUBSET_SETS_DROP_TABLE_TAG)); |
412 | |
|
413 | 0 | hb_subset_input_set_flags (input, |
414 | 0 | HB_SUBSET_FLAGS_NOTDEF_OUTLINE | |
415 | 0 | HB_SUBSET_FLAGS_GLYPH_NAMES | |
416 | 0 | HB_SUBSET_FLAGS_NAME_LEGACY | |
417 | 0 | HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES | |
418 | 0 | HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED); |
419 | 0 | } |
420 | | |
421 | | #ifndef HB_NO_VAR |
422 | | /** |
423 | | * hb_subset_input_pin_all_axes_to_default: (skip) |
424 | | * @input: a #hb_subset_input_t object. |
425 | | * @face: a #hb_face_t object. |
426 | | * |
427 | | * Pin all axes to default locations in the given subset input object. |
428 | | * |
429 | | * All axes in a font must be pinned. Additionally, `CFF2` table, if present, |
430 | | * will be de-subroutinized. |
431 | | * |
432 | | * Return value: `true` if success, `false` otherwise |
433 | | * |
434 | | * Since: 8.3.1 |
435 | | **/ |
436 | | HB_EXTERN hb_bool_t |
437 | | hb_subset_input_pin_all_axes_to_default (hb_subset_input_t *input, |
438 | | hb_face_t *face) |
439 | 0 | { |
440 | 0 | unsigned axis_count = hb_ot_var_get_axis_count (face); |
441 | 0 | if (!axis_count) return false; |
442 | | |
443 | 0 | hb_ot_var_axis_info_t *axis_infos = (hb_ot_var_axis_info_t *) hb_calloc (axis_count, sizeof (hb_ot_var_axis_info_t)); |
444 | 0 | if (unlikely (!axis_infos)) return false; |
445 | | |
446 | 0 | (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axis_infos); |
447 | |
|
448 | 0 | for (unsigned i = 0; i < axis_count; i++) |
449 | 0 | { |
450 | 0 | hb_tag_t axis_tag = axis_infos[i].tag; |
451 | 0 | double default_val = (double) axis_infos[i].default_value; |
452 | 0 | if (!input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val))) |
453 | 0 | { |
454 | 0 | hb_free (axis_infos); |
455 | 0 | return false; |
456 | 0 | } |
457 | 0 | } |
458 | 0 | hb_free (axis_infos); |
459 | 0 | return true; |
460 | 0 | } |
461 | | |
462 | | /** |
463 | | * hb_subset_input_pin_axis_to_default: (skip) |
464 | | * @input: a #hb_subset_input_t object. |
465 | | * @face: a #hb_face_t object. |
466 | | * @axis_tag: Tag of the axis to be pinned |
467 | | * |
468 | | * Pin an axis to its default location in the given subset input object. |
469 | | * |
470 | | * All axes in a font must be pinned. Additionally, `CFF2` table, if present, |
471 | | * will be de-subroutinized. |
472 | | * |
473 | | * Return value: `true` if success, `false` otherwise |
474 | | * |
475 | | * Since: 6.0.0 |
476 | | **/ |
477 | | HB_EXTERN hb_bool_t |
478 | | hb_subset_input_pin_axis_to_default (hb_subset_input_t *input, |
479 | | hb_face_t *face, |
480 | | hb_tag_t axis_tag) |
481 | 0 | { |
482 | 0 | hb_ot_var_axis_info_t axis_info; |
483 | 0 | if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) |
484 | 0 | return false; |
485 | | |
486 | 0 | double default_val = (double) axis_info.default_value; |
487 | 0 | return input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val)); |
488 | 0 | } |
489 | | |
490 | | /** |
491 | | * hb_subset_input_pin_axis_location: (skip) |
492 | | * @input: a #hb_subset_input_t object. |
493 | | * @face: a #hb_face_t object. |
494 | | * @axis_tag: Tag of the axis to be pinned |
495 | | * @axis_value: Location on the axis to be pinned at |
496 | | * |
497 | | * Pin an axis to a fixed location in the given subset input object. |
498 | | * |
499 | | * All axes in a font must be pinned. Additionally, `CFF2` table, if present, |
500 | | * will be de-subroutinized. |
501 | | * |
502 | | * Return value: `true` if success, `false` otherwise |
503 | | * |
504 | | * Since: 6.0.0 |
505 | | **/ |
506 | | HB_EXTERN hb_bool_t |
507 | | hb_subset_input_pin_axis_location (hb_subset_input_t *input, |
508 | | hb_face_t *face, |
509 | | hb_tag_t axis_tag, |
510 | | float axis_value) |
511 | 0 | { |
512 | 0 | hb_ot_var_axis_info_t axis_info; |
513 | 0 | if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) |
514 | 0 | return false; |
515 | | |
516 | 0 | double val = hb_clamp((double) axis_value, (double) axis_info.min_value, (double) axis_info.max_value); |
517 | 0 | return input->axes_location.set (axis_tag, Triple (val, val, val)); |
518 | 0 | } |
519 | | |
520 | | /** |
521 | | * hb_subset_input_set_axis_range: (skip) |
522 | | * @input: a #hb_subset_input_t object. |
523 | | * @face: a #hb_face_t object. |
524 | | * @axis_tag: Tag of the axis |
525 | | * @axis_min_value: Minimum value of the axis variation range to set, if NaN the existing min will be used. |
526 | | * @axis_max_value: Maximum value of the axis variation range to set if NaN the existing max will be used. |
527 | | * @axis_def_value: Default value of the axis variation range to set, if NaN the existing default will be used. |
528 | | * |
529 | | * Restricting the range of variation on an axis in the given subset input object. |
530 | | * New min/default/max values will be clamped if they're not within the fvar axis range. |
531 | | * |
532 | | * If the fvar axis default value is not within the new range, the new default |
533 | | * value will be changed to the new min or max value, whichever is closer to the fvar |
534 | | * axis default. |
535 | | * |
536 | | * Note: input min value can not be bigger than input max value. If the input |
537 | | * default value is not within the new min/max range, it'll be clamped. |
538 | | * |
539 | | * Return value: `true` if success, `false` otherwise |
540 | | * |
541 | | * Since: 8.5.0 |
542 | | **/ |
543 | | HB_EXTERN hb_bool_t |
544 | | hb_subset_input_set_axis_range (hb_subset_input_t *input, |
545 | | hb_face_t *face, |
546 | | hb_tag_t axis_tag, |
547 | | float axis_min_value, |
548 | | float axis_max_value, |
549 | | float axis_def_value) |
550 | 0 | { |
551 | 0 | hb_ot_var_axis_info_t axis_info; |
552 | 0 | if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) |
553 | 0 | return false; |
554 | | |
555 | 0 | float min = !std::isnan(axis_min_value) ? axis_min_value : axis_info.min_value; |
556 | 0 | float max = !std::isnan(axis_max_value) ? axis_max_value : axis_info.max_value; |
557 | 0 | float def = !std::isnan(axis_def_value) ? axis_def_value : axis_info.default_value; |
558 | |
|
559 | 0 | if (min > max) |
560 | 0 | return false; |
561 | | |
562 | 0 | float new_min_val = hb_clamp(min, axis_info.min_value, axis_info.max_value); |
563 | 0 | float new_max_val = hb_clamp(max, axis_info.min_value, axis_info.max_value); |
564 | 0 | float new_default_val = hb_clamp(def, new_min_val, new_max_val); |
565 | 0 | return input->axes_location.set (axis_tag, Triple ((double) new_min_val, (double) new_default_val, (double) new_max_val)); |
566 | 0 | } |
567 | | |
568 | | /** |
569 | | * hb_subset_input_get_axis_range: (skip) |
570 | | * @input: a #hb_subset_input_t object. |
571 | | * @axis_tag: Tag of the axis |
572 | | * @axis_min_value: Set to the previously configured minimum value of the axis variation range. |
573 | | * @axis_max_value: Set to the previously configured maximum value of the axis variation range. |
574 | | * @axis_def_value: Set to the previously configured default value of the axis variation range. |
575 | | * |
576 | | * Gets the axis range assigned by previous calls to hb_subset_input_set_axis_range. |
577 | | * |
578 | | * Return value: `true` if a range has been set for this axis tag, `false` otherwise. |
579 | | * |
580 | | * Since: 8.5.0 |
581 | | **/ |
582 | | HB_EXTERN hb_bool_t |
583 | | hb_subset_input_get_axis_range (hb_subset_input_t *input, |
584 | | hb_tag_t axis_tag, |
585 | | float *axis_min_value, |
586 | | float *axis_max_value, |
587 | | float *axis_def_value) |
588 | | |
589 | 0 | { |
590 | 0 | Triple* triple; |
591 | 0 | if (!input->axes_location.has(axis_tag, &triple)) { |
592 | 0 | return false; |
593 | 0 | } |
594 | | |
595 | 0 | *axis_min_value = triple->minimum; |
596 | 0 | *axis_def_value = triple->middle; |
597 | 0 | *axis_max_value = triple->maximum; |
598 | 0 | return true; |
599 | 0 | } |
600 | | |
601 | | /** |
602 | | * hb_subset_axis_range_from_string: |
603 | | * @str: a string to parse |
604 | | * @len: length of @str, or -1 if str is NULL terminated |
605 | | * @axis_min_value: (out): the axis min value to initialize with the parsed value |
606 | | * @axis_max_value: (out): the axis max value to initialize with the parsed value |
607 | | * @axis_def_value: (out): the axis default value to initialize with the parse |
608 | | * value |
609 | | * |
610 | | * Parses a string into a subset axis range(min, def, max). |
611 | | * Axis positions string is in the format of min:def:max or min:max |
612 | | * When parsing axis positions, empty values as meaning the existing value for that part |
613 | | * E.g: :300:500 |
614 | | * Specifies min = existing, def = 300, max = 500 |
615 | | * In the output axis_range, if a value should be set to it's default value, |
616 | | * then it will be set to NaN |
617 | | * |
618 | | * Return value: |
619 | | * `true` if @str is successfully parsed, `false` otherwise |
620 | | * |
621 | | * Since: 10.2.0 |
622 | | */ |
623 | | HB_EXTERN hb_bool_t |
624 | | hb_subset_axis_range_from_string (const char *str, int len, |
625 | | float *axis_min_value, |
626 | | float *axis_max_value, |
627 | | float *axis_def_value) |
628 | 0 | { |
629 | 0 | if (len < 0) |
630 | 0 | len = strlen (str); |
631 | |
|
632 | 0 | const char *end = str + len; |
633 | 0 | const char* part = strpbrk (str, ":"); |
634 | 0 | if (!part) |
635 | 0 | { |
636 | | // Single value. |
637 | 0 | if (strcmp (str, "drop") == 0) |
638 | 0 | { |
639 | 0 | *axis_min_value = NAN; |
640 | 0 | *axis_def_value = NAN; |
641 | 0 | *axis_max_value = NAN; |
642 | 0 | return true; |
643 | 0 | } |
644 | | |
645 | 0 | double v; |
646 | 0 | if (!hb_parse_double (&str, end, &v)) return false; |
647 | | |
648 | 0 | *axis_min_value = v; |
649 | 0 | *axis_def_value = v; |
650 | 0 | *axis_max_value = v; |
651 | 0 | return true; |
652 | 0 | } |
653 | | |
654 | 0 | float values[3]; |
655 | 0 | int count = 0; |
656 | 0 | for (int i = 0; i < 3; i++) { |
657 | 0 | count++; |
658 | 0 | if (!*str || part == str) |
659 | 0 | { |
660 | 0 | values[i] = NAN; |
661 | |
|
662 | 0 | if (part == NULL) break; |
663 | 0 | str = part + 1; |
664 | 0 | part = strpbrk (str, ":"); |
665 | 0 | continue; |
666 | 0 | } |
667 | | |
668 | 0 | double v; |
669 | 0 | if (!hb_parse_double (&str, part, &v)) return false; |
670 | 0 | values[i] = v; |
671 | |
|
672 | 0 | if (part == NULL) break; |
673 | 0 | str = part + 1; |
674 | 0 | part = strpbrk (str, ":"); |
675 | 0 | } |
676 | | |
677 | 0 | if (count == 2) |
678 | 0 | { |
679 | 0 | *axis_min_value = values[0]; |
680 | 0 | *axis_def_value = NAN; |
681 | 0 | *axis_max_value = values[1]; |
682 | 0 | return true; |
683 | 0 | } |
684 | 0 | else if (count == 3) |
685 | 0 | { |
686 | 0 | *axis_min_value = values[0]; |
687 | 0 | *axis_def_value = values[1]; |
688 | 0 | *axis_max_value = values[2]; |
689 | 0 | return true; |
690 | 0 | } |
691 | 0 | return false; |
692 | 0 | } |
693 | | |
694 | | /** |
695 | | * hb_subset_axis_range_to_string: |
696 | | * @input: a #hb_subset_input_t object. |
697 | | * @axis_tag: an axis to convert |
698 | | * @buf: (array length=size) (out caller-allocates): output string |
699 | | * @size: the allocated size of @buf |
700 | | * |
701 | | * Converts an axis range into a `NULL`-terminated string in the format |
702 | | * understood by hb_subset_axis_range_from_string(). The client in responsible for |
703 | | * allocating big enough size for @buf, 128 bytes is more than enough. |
704 | | * |
705 | | * Since: 10.2.0 |
706 | | */ |
707 | | HB_EXTERN void |
708 | | hb_subset_axis_range_to_string (hb_subset_input_t *input, |
709 | | hb_tag_t axis_tag, |
710 | | char *buf, unsigned size) |
711 | 0 | { |
712 | 0 | if (unlikely (!size)) return; |
713 | 0 | Triple* triple; |
714 | 0 | if (!input->axes_location.has(axis_tag, &triple)) { |
715 | 0 | return; |
716 | 0 | } |
717 | | |
718 | 0 | char s[128]; |
719 | 0 | unsigned len = 0; |
720 | |
|
721 | 0 | hb_locale_t clocale HB_UNUSED; |
722 | 0 | hb_locale_t oldlocale HB_UNUSED; |
723 | 0 | oldlocale = hb_uselocale (clocale = newlocale (LC_ALL_MASK, "C", NULL)); |
724 | 0 | len += hb_max (0, snprintf (s, ARRAY_LENGTH (s) - len, "%g", (double) triple->minimum)); |
725 | 0 | s[len++] = ':'; |
726 | |
|
727 | 0 | len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) triple->middle)); |
728 | 0 | s[len++] = ':'; |
729 | |
|
730 | 0 | len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) triple->maximum)); |
731 | 0 | (void) hb_uselocale (((void) freelocale (clocale), oldlocale)); |
732 | |
|
733 | 0 | assert (len < ARRAY_LENGTH (s)); |
734 | 0 | len = hb_min (len, size - 1); |
735 | 0 | hb_memcpy (buf, s, len); |
736 | 0 | buf[len] = '\0'; |
737 | 0 | } |
738 | | #endif |
739 | | |
740 | | /** |
741 | | * hb_subset_preprocess: |
742 | | * @source: a #hb_face_t object. |
743 | | * |
744 | | * Preprocesses the face and attaches data that will be needed by the |
745 | | * subsetter. Future subsetting operations can then use the precomputed data |
746 | | * to speed up the subsetting operation. |
747 | | * |
748 | | * See [subset-preprocessing](https://github.com/harfbuzz/harfbuzz/blob/main/docs/subset-preprocessing.md) |
749 | | * for more information. |
750 | | * |
751 | | * Note: the preprocessed face may contain sub-blobs that reference the memory |
752 | | * backing the source #hb_face_t. Therefore in the case that this memory is not |
753 | | * owned by the source face you will need to ensure that memory lives |
754 | | * as long as the returned #hb_face_t. |
755 | | * |
756 | | * Returns: a new #hb_face_t. |
757 | | * |
758 | | * Since: 6.0.0 |
759 | | **/ |
760 | | |
761 | | HB_EXTERN hb_face_t * |
762 | | hb_subset_preprocess (hb_face_t *source) |
763 | 0 | { |
764 | 0 | hb_subset_input_t* input = hb_subset_input_create_or_fail (); |
765 | 0 | if (!input) |
766 | 0 | return hb_face_reference (source); |
767 | | |
768 | 0 | hb_subset_input_keep_everything (input); |
769 | |
|
770 | 0 | input->attach_accelerator_data = true; |
771 | | |
772 | | // Always use long loca in the preprocessed version. This allows |
773 | | // us to store the glyph bytes unpadded which allows the future subset |
774 | | // operation to run faster by skipping the trim padding step. |
775 | 0 | input->force_long_loca = true; |
776 | |
|
777 | 0 | hb_face_t* new_source = hb_subset_or_fail (source, input); |
778 | 0 | hb_subset_input_destroy (input); |
779 | |
|
780 | 0 | if (!new_source) { |
781 | 0 | DEBUG_MSG (SUBSET, nullptr, "Preprocessing failed due to subset failure."); |
782 | 0 | return hb_face_reference (source); |
783 | 0 | } |
784 | | |
785 | 0 | return new_source; |
786 | 0 | } |
787 | | |
788 | | /** |
789 | | * hb_subset_input_old_to_new_glyph_mapping: |
790 | | * @input: a #hb_subset_input_t object. |
791 | | * |
792 | | * Returns a map which can be used to provide an explicit mapping from old to new glyph |
793 | | * id's in the produced subset. The caller should populate the map as desired. |
794 | | * If this map is left empty then glyph ids will be automatically mapped to new |
795 | | * values by the subsetter. If populated, the mapping must be unique. That |
796 | | * is no two original glyph ids can be mapped to the same new id. |
797 | | * Additionally, if a mapping is provided then the retain gids option cannot |
798 | | * be enabled. |
799 | | * |
800 | | * Any glyphs that are retained in the subset which are not specified |
801 | | * in this mapping will be assigned glyph ids after the highest glyph |
802 | | * id in the mapping. |
803 | | * |
804 | | * Note: this will accept and apply non-monotonic mappings, however this |
805 | | * may result in unsorted Coverage tables. Such fonts may not work for all |
806 | | * use cases (for example ots will reject unsorted coverage tables). So it's |
807 | | * recommended, if possible, to supply a monotonic mapping. |
808 | | * |
809 | | * Return value: (transfer none): pointer to the #hb_map_t of the custom glyphs ID map. |
810 | | * |
811 | | * Since: 7.3.0 |
812 | | **/ |
813 | | HB_EXTERN hb_map_t* |
814 | | hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input) |
815 | 6.42k | { |
816 | 6.42k | return &input->glyph_map; |
817 | 6.42k | } |
818 | | |
819 | | #ifdef HB_EXPERIMENTAL_API |
820 | | /** |
821 | | * hb_subset_input_override_name_table: |
822 | | * @input: a #hb_subset_input_t object. |
823 | | * @name_id: name_id of a nameRecord |
824 | | * @platform_id: platform ID of a nameRecord |
825 | | * @encoding_id: encoding ID of a nameRecord |
826 | | * @language_id: language ID of a nameRecord |
827 | | * @name_str: pointer to name string new value or null to indicate should remove |
828 | | * @str_len: the size of @name_str, or -1 if it is `NULL`-terminated |
829 | | * |
830 | | * Override the name string of the NameRecord identified by name_id, |
831 | | * platform_id, encoding_id and language_id. If a record with that name_id |
832 | | * doesn't exist, create it and insert to the name table. |
833 | | * |
834 | | * Note: for mac platform, we only support name_str with all ascii characters, |
835 | | * name_str with non-ascii characters will be ignored. |
836 | | * |
837 | | * XSince: EXPERIMENTAL |
838 | | **/ |
839 | | HB_EXTERN hb_bool_t |
840 | | hb_subset_input_override_name_table (hb_subset_input_t *input, |
841 | | hb_ot_name_id_t name_id, |
842 | | unsigned platform_id, |
843 | | unsigned encoding_id, |
844 | | unsigned language_id, |
845 | | const char *name_str, |
846 | | int str_len /* -1 means nul-terminated */) |
847 | | { |
848 | | if (!name_str) |
849 | | { |
850 | | str_len = 0; |
851 | | } |
852 | | else if (str_len == -1) |
853 | | { |
854 | | str_len = strlen (name_str); |
855 | | } |
856 | | |
857 | | hb_bytes_t name_bytes (nullptr, 0); |
858 | | if (str_len) |
859 | | { |
860 | | if (platform_id == 1) |
861 | | { |
862 | | const uint8_t *src = reinterpret_cast<const uint8_t*> (name_str); |
863 | | const uint8_t *src_end = src + str_len; |
864 | | |
865 | | hb_codepoint_t unicode; |
866 | | const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; |
867 | | while (src < src_end) |
868 | | { |
869 | | src = hb_utf8_t::next (src, src_end, &unicode, replacement); |
870 | | if (unicode >= 0x0080u) |
871 | | { |
872 | | // Non-ascii character detected, ignored... |
873 | | return false; |
874 | | } |
875 | | } |
876 | | } |
877 | | char *override_name = (char *) hb_malloc (str_len); |
878 | | if (unlikely (!override_name)) return false; |
879 | | |
880 | | hb_memcpy (override_name, name_str, str_len); |
881 | | name_bytes = hb_bytes_t (override_name, str_len); |
882 | | } |
883 | | input->name_table_overrides.set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes); |
884 | | return true; |
885 | | } |
886 | | #endif |