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.hh" |
28 | #include "hb-set.hh" |
29 | #include "hb-utf.hh" |
30 | |
31 | |
32 | hb_subset_input_t::hb_subset_input_t () |
33 | { |
34 | for (auto& set : sets_iter ()) |
35 | set = hb::shared_ptr<hb_set_t> (hb_set_create ()); |
36 | |
37 | if (in_error ()) |
38 | return; |
39 | |
40 | flags = HB_SUBSET_FLAGS_DEFAULT; |
41 | |
42 | hb_set_add_range (sets.name_ids, 0, 6); |
43 | hb_set_add (sets.name_languages, 0x0409); |
44 | |
45 | hb_tag_t default_drop_tables[] = { |
46 | // Layout disabled by default |
47 | HB_TAG ('m', 'o', 'r', 'x'), |
48 | HB_TAG ('m', 'o', 'r', 't'), |
49 | HB_TAG ('k', 'e', 'r', 'x'), |
50 | HB_TAG ('k', 'e', 'r', 'n'), |
51 | |
52 | // Copied from fontTools: |
53 | HB_TAG ('B', 'A', 'S', 'E'), |
54 | HB_TAG ('J', 'S', 'T', 'F'), |
55 | HB_TAG ('D', 'S', 'I', 'G'), |
56 | HB_TAG ('E', 'B', 'D', 'T'), |
57 | HB_TAG ('E', 'B', 'L', 'C'), |
58 | HB_TAG ('E', 'B', 'S', 'C'), |
59 | HB_TAG ('S', 'V', 'G', ' '), |
60 | HB_TAG ('P', 'C', 'L', 'T'), |
61 | HB_TAG ('L', 'T', 'S', 'H'), |
62 | // Graphite tables |
63 | HB_TAG ('F', 'e', 'a', 't'), |
64 | HB_TAG ('G', 'l', 'a', 't'), |
65 | HB_TAG ('G', 'l', 'o', 'c'), |
66 | HB_TAG ('S', 'i', 'l', 'f'), |
67 | HB_TAG ('S', 'i', 'l', 'l'), |
68 | }; |
69 | sets.drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables)); |
70 | |
71 | hb_tag_t default_no_subset_tables[] = { |
72 | HB_TAG ('g', 'a', 's', 'p'), |
73 | HB_TAG ('f', 'p', 'g', 'm'), |
74 | HB_TAG ('p', 'r', 'e', 'p'), |
75 | HB_TAG ('V', 'D', 'M', 'X'), |
76 | HB_TAG ('D', 'S', 'I', 'G'), |
77 | HB_TAG ('M', 'V', 'A', 'R'), |
78 | HB_TAG ('c', 'v', 'a', 'r'), |
79 | }; |
80 | sets.no_subset_tables->add_array (default_no_subset_tables, |
81 | ARRAY_LENGTH (default_no_subset_tables)); |
82 | |
83 | //copied from _layout_features_groups in fonttools |
84 | hb_tag_t default_layout_features[] = { |
85 | // default shaper |
86 | // common |
87 | HB_TAG ('r', 'v', 'r', 'n'), |
88 | HB_TAG ('c', 'c', 'm', 'p'), |
89 | HB_TAG ('l', 'i', 'g', 'a'), |
90 | HB_TAG ('l', 'o', 'c', 'l'), |
91 | HB_TAG ('m', 'a', 'r', 'k'), |
92 | HB_TAG ('m', 'k', 'm', 'k'), |
93 | HB_TAG ('r', 'l', 'i', 'g'), |
94 | |
95 | //fractions |
96 | HB_TAG ('f', 'r', 'a', 'c'), |
97 | HB_TAG ('n', 'u', 'm', 'r'), |
98 | HB_TAG ('d', 'n', 'o', 'm'), |
99 | |
100 | //horizontal |
101 | HB_TAG ('c', 'a', 'l', 't'), |
102 | HB_TAG ('c', 'l', 'i', 'g'), |
103 | HB_TAG ('c', 'u', 'r', 's'), |
104 | HB_TAG ('k', 'e', 'r', 'n'), |
105 | HB_TAG ('r', 'c', 'l', 't'), |
106 | |
107 | //vertical |
108 | HB_TAG ('v', 'a', 'l', 't'), |
109 | HB_TAG ('v', 'e', 'r', 't'), |
110 | HB_TAG ('v', 'k', 'r', 'n'), |
111 | HB_TAG ('v', 'p', 'a', 'l'), |
112 | HB_TAG ('v', 'r', 't', '2'), |
113 | |
114 | //ltr |
115 | HB_TAG ('l', 't', 'r', 'a'), |
116 | HB_TAG ('l', 't', 'r', 'm'), |
117 | |
118 | //rtl |
119 | HB_TAG ('r', 't', 'l', 'a'), |
120 | HB_TAG ('r', 't', 'l', 'm'), |
121 | |
122 | //random |
123 | HB_TAG ('r', 'a', 'n', 'd'), |
124 | |
125 | //justify |
126 | HB_TAG ('j', 'a', 'l', 't'), // HarfBuzz doesn't use; others might |
127 | |
128 | //private |
129 | HB_TAG ('H', 'a', 'r', 'f'), |
130 | HB_TAG ('H', 'A', 'R', 'F'), |
131 | HB_TAG ('B', 'u', 'z', 'z'), |
132 | HB_TAG ('B', 'U', 'Z', 'Z'), |
133 | |
134 | //shapers |
135 | |
136 | //arabic |
137 | HB_TAG ('i', 'n', 'i', 't'), |
138 | HB_TAG ('m', 'e', 'd', 'i'), |
139 | HB_TAG ('f', 'i', 'n', 'a'), |
140 | HB_TAG ('i', 's', 'o', 'l'), |
141 | HB_TAG ('m', 'e', 'd', '2'), |
142 | HB_TAG ('f', 'i', 'n', '2'), |
143 | HB_TAG ('f', 'i', 'n', '3'), |
144 | HB_TAG ('c', 's', 'w', 'h'), |
145 | HB_TAG ('m', 's', 'e', 't'), |
146 | HB_TAG ('s', 't', 'c', 'h'), |
147 | |
148 | //hangul |
149 | HB_TAG ('l', 'j', 'm', 'o'), |
150 | HB_TAG ('v', 'j', 'm', 'o'), |
151 | HB_TAG ('t', 'j', 'm', 'o'), |
152 | |
153 | //tibetan |
154 | HB_TAG ('a', 'b', 'v', 's'), |
155 | HB_TAG ('b', 'l', 'w', 's'), |
156 | HB_TAG ('a', 'b', 'v', 'm'), |
157 | HB_TAG ('b', 'l', 'w', 'm'), |
158 | |
159 | //indic |
160 | HB_TAG ('n', 'u', 'k', 't'), |
161 | HB_TAG ('a', 'k', 'h', 'n'), |
162 | HB_TAG ('r', 'p', 'h', 'f'), |
163 | HB_TAG ('r', 'k', 'r', 'f'), |
164 | HB_TAG ('p', 'r', 'e', 'f'), |
165 | HB_TAG ('b', 'l', 'w', 'f'), |
166 | HB_TAG ('h', 'a', 'l', 'f'), |
167 | HB_TAG ('a', 'b', 'v', 'f'), |
168 | HB_TAG ('p', 's', 't', 'f'), |
169 | HB_TAG ('c', 'f', 'a', 'r'), |
170 | HB_TAG ('v', 'a', 't', 'u'), |
171 | HB_TAG ('c', 'j', 'c', 't'), |
172 | HB_TAG ('i', 'n', 'i', 't'), |
173 | HB_TAG ('p', 'r', 'e', 's'), |
174 | HB_TAG ('a', 'b', 'v', 's'), |
175 | HB_TAG ('b', 'l', 'w', 's'), |
176 | HB_TAG ('p', 's', 't', 's'), |
177 | HB_TAG ('h', 'a', 'l', 'n'), |
178 | HB_TAG ('d', 'i', 's', 't'), |
179 | HB_TAG ('a', 'b', 'v', 'm'), |
180 | HB_TAG ('b', 'l', 'w', 'm'), |
181 | }; |
182 | |
183 | sets.layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features)); |
184 | |
185 | sets.layout_scripts->invert (); // Default to all scripts. |
186 | } |
187 | |
188 | /** |
189 | * hb_subset_input_create_or_fail: |
190 | * |
191 | * Creates a new subset input object. |
192 | * |
193 | * Return value: (transfer full): New subset input, or `NULL` if failed. Destroy |
194 | * with hb_subset_input_destroy(). |
195 | * |
196 | * Since: 1.8.0 |
197 | **/ |
198 | hb_subset_input_t * |
199 | hb_subset_input_create_or_fail (void) |
200 | { |
201 | hb_subset_input_t *input = hb_object_create<hb_subset_input_t>(); |
202 | |
203 | if (unlikely (!input)) |
204 | return nullptr; |
205 | |
206 | if (input->in_error ()) |
207 | { |
208 | hb_subset_input_destroy (input); |
209 | return nullptr; |
210 | } |
211 | |
212 | return input; |
213 | } |
214 | |
215 | /** |
216 | * hb_subset_input_reference: (skip) |
217 | * @input: a #hb_subset_input_t object. |
218 | * |
219 | * Increases the reference count on @input. |
220 | * |
221 | * Return value: @input. |
222 | * |
223 | * Since: 1.8.0 |
224 | **/ |
225 | hb_subset_input_t * |
226 | hb_subset_input_reference (hb_subset_input_t *input) |
227 | { |
228 | return hb_object_reference (input); |
229 | } |
230 | |
231 | /** |
232 | * hb_subset_input_destroy: |
233 | * @input: a #hb_subset_input_t object. |
234 | * |
235 | * Decreases the reference count on @input, and if it reaches zero, destroys |
236 | * @input, freeing all memory. |
237 | * |
238 | * Since: 1.8.0 |
239 | **/ |
240 | void |
241 | hb_subset_input_destroy (hb_subset_input_t *input) |
242 | { |
243 | if (!hb_object_destroy (input)) return; |
244 | |
245 | hb_free (input); |
246 | } |
247 | |
248 | /** |
249 | * hb_subset_input_unicode_set: |
250 | * @input: a #hb_subset_input_t object. |
251 | * |
252 | * Gets the set of Unicode code points to retain, the caller should modify the |
253 | * set as needed. |
254 | * |
255 | * Return value: (transfer none): pointer to the #hb_set_t of Unicode code |
256 | * points. |
257 | * |
258 | * Since: 1.8.0 |
259 | **/ |
260 | HB_EXTERN hb_set_t * |
261 | hb_subset_input_unicode_set (hb_subset_input_t *input) |
262 | { |
263 | return input->sets.unicodes; |
264 | } |
265 | |
266 | /** |
267 | * hb_subset_input_glyph_set: |
268 | * @input: a #hb_subset_input_t object. |
269 | * |
270 | * Gets the set of glyph IDs to retain, the caller should modify the set as |
271 | * needed. |
272 | * |
273 | * Return value: (transfer none): pointer to the #hb_set_t of glyph IDs. |
274 | * |
275 | * Since: 1.8.0 |
276 | **/ |
277 | HB_EXTERN hb_set_t * |
278 | hb_subset_input_glyph_set (hb_subset_input_t *input) |
279 | { |
280 | return input->sets.glyphs; |
281 | } |
282 | |
283 | /** |
284 | * hb_subset_input_set: |
285 | * @input: a #hb_subset_input_t object. |
286 | * @set_type: a #hb_subset_sets_t set type. |
287 | * |
288 | * Gets the set of the specified type. |
289 | * |
290 | * Return value: (transfer none): pointer to the #hb_set_t of the specified type. |
291 | * |
292 | * Since: 2.9.1 |
293 | **/ |
294 | HB_EXTERN hb_set_t * |
295 | hb_subset_input_set (hb_subset_input_t *input, hb_subset_sets_t set_type) |
296 | { |
297 | return input->sets_iter () [set_type]; |
298 | } |
299 | |
300 | /** |
301 | * hb_subset_input_get_flags: |
302 | * @input: a #hb_subset_input_t object. |
303 | * |
304 | * Gets all of the subsetting flags in the input object. |
305 | * |
306 | * Return value: the subsetting flags bit field. |
307 | * |
308 | * Since: 2.9.0 |
309 | **/ |
310 | HB_EXTERN hb_subset_flags_t |
311 | hb_subset_input_get_flags (hb_subset_input_t *input) |
312 | { |
313 | return (hb_subset_flags_t) input->flags; |
314 | } |
315 | |
316 | /** |
317 | * hb_subset_input_set_flags: |
318 | * @input: a #hb_subset_input_t object. |
319 | * @value: bit field of flags |
320 | * |
321 | * Sets all of the flags in the input object to the values specified by the bit |
322 | * field. |
323 | * |
324 | * Since: 2.9.0 |
325 | **/ |
326 | HB_EXTERN void |
327 | hb_subset_input_set_flags (hb_subset_input_t *input, |
328 | unsigned value) |
329 | { |
330 | input->flags = (hb_subset_flags_t) value; |
331 | } |
332 | |
333 | /** |
334 | * hb_subset_input_set_user_data: (skip) |
335 | * @input: a #hb_subset_input_t object. |
336 | * @key: The user-data key to set |
337 | * @data: A pointer to the user data |
338 | * @destroy: (nullable): A callback to call when @data is not needed anymore |
339 | * @replace: Whether to replace an existing data with the same key |
340 | * |
341 | * Attaches a user-data key/data pair to the given subset input object. |
342 | * |
343 | * Return value: `true` if success, `false` otherwise |
344 | * |
345 | * Since: 2.9.0 |
346 | **/ |
347 | hb_bool_t |
348 | hb_subset_input_set_user_data (hb_subset_input_t *input, |
349 | hb_user_data_key_t *key, |
350 | void * data, |
351 | hb_destroy_func_t destroy, |
352 | hb_bool_t replace) |
353 | { |
354 | return hb_object_set_user_data (input, key, data, destroy, replace); |
355 | } |
356 | |
357 | /** |
358 | * hb_subset_input_get_user_data: (skip) |
359 | * @input: a #hb_subset_input_t object. |
360 | * @key: The user-data key to query |
361 | * |
362 | * Fetches the user data associated with the specified key, |
363 | * attached to the specified subset input object. |
364 | * |
365 | * Return value: (transfer none): A pointer to the user data |
366 | * |
367 | * Since: 2.9.0 |
368 | **/ |
369 | void * |
370 | hb_subset_input_get_user_data (const hb_subset_input_t *input, |
371 | hb_user_data_key_t *key) |
372 | { |
373 | return hb_object_get_user_data (input, key); |
374 | } |
375 | |
376 | /** |
377 | * hb_subset_input_keep_everything: |
378 | * @input: a #hb_subset_input_t object |
379 | * |
380 | * Configure input object to keep everything in the font face. |
381 | * That is, all Unicodes, glyphs, names, layout items, |
382 | * glyph names, etc. |
383 | * |
384 | * The input can be tailored afterwards by the caller. |
385 | * |
386 | * Since: 7.0.0 |
387 | */ |
388 | void |
389 | hb_subset_input_keep_everything (hb_subset_input_t *input) |
390 | { |
391 | const hb_subset_sets_t indices[] = {HB_SUBSET_SETS_UNICODE, |
392 | HB_SUBSET_SETS_GLYPH_INDEX, |
393 | HB_SUBSET_SETS_NAME_ID, |
394 | HB_SUBSET_SETS_NAME_LANG_ID, |
395 | HB_SUBSET_SETS_LAYOUT_FEATURE_TAG, |
396 | HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG}; |
397 | |
398 | for (auto idx : hb_iter (indices)) |
399 | { |
400 | hb_set_t *set = hb_subset_input_set (input, idx); |
401 | hb_set_clear (set); |
402 | hb_set_invert (set); |
403 | } |
404 | |
405 | // Don't drop any tables |
406 | hb_set_clear (hb_subset_input_set (input, HB_SUBSET_SETS_DROP_TABLE_TAG)); |
407 | |
408 | hb_subset_input_set_flags (input, |
409 | HB_SUBSET_FLAGS_NOTDEF_OUTLINE | |
410 | HB_SUBSET_FLAGS_GLYPH_NAMES | |
411 | HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES | |
412 | HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED); |
413 | } |
414 | |
415 | #ifndef HB_NO_VAR |
416 | /** |
417 | * hb_subset_input_pin_axis_to_default: (skip) |
418 | * @input: a #hb_subset_input_t object. |
419 | * @face: a #hb_face_t object. |
420 | * @axis_tag: Tag of the axis to be pinned |
421 | * |
422 | * Pin an axis to its default location in the given subset input object. |
423 | * |
424 | * All axes in a font must be pinned. Additionally, `CFF2` table, if present, |
425 | * will be de-subroutinized. |
426 | * |
427 | * Return value: `true` if success, `false` otherwise |
428 | * |
429 | * Since: 6.0.0 |
430 | **/ |
431 | HB_EXTERN hb_bool_t |
432 | hb_subset_input_pin_axis_to_default (hb_subset_input_t *input, |
433 | hb_face_t *face, |
434 | hb_tag_t axis_tag) |
435 | { |
436 | hb_ot_var_axis_info_t axis_info; |
437 | if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) |
438 | return false; |
439 | |
440 | float default_val = axis_info.default_value; |
441 | return input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val)); |
442 | } |
443 | |
444 | /** |
445 | * hb_subset_input_pin_axis_location: (skip) |
446 | * @input: a #hb_subset_input_t object. |
447 | * @face: a #hb_face_t object. |
448 | * @axis_tag: Tag of the axis to be pinned |
449 | * @axis_value: Location on the axis to be pinned at |
450 | * |
451 | * Pin an axis to a fixed location in the given subset input object. |
452 | * |
453 | * All axes in a font must be pinned. Additionally, `CFF2` table, if present, |
454 | * will be de-subroutinized. |
455 | * |
456 | * Return value: `true` if success, `false` otherwise |
457 | * |
458 | * Since: 6.0.0 |
459 | **/ |
460 | HB_EXTERN hb_bool_t |
461 | hb_subset_input_pin_axis_location (hb_subset_input_t *input, |
462 | hb_face_t *face, |
463 | hb_tag_t axis_tag, |
464 | float axis_value) |
465 | { |
466 | hb_ot_var_axis_info_t axis_info; |
467 | if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) |
468 | return false; |
469 | |
470 | float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value); |
471 | return input->axes_location.set (axis_tag, Triple (val, val, val)); |
472 | } |
473 | |
474 | #ifdef HB_EXPERIMENTAL_API |
475 | /** |
476 | * hb_subset_input_set_axis_range: (skip) |
477 | * @input: a #hb_subset_input_t object. |
478 | * @face: a #hb_face_t object. |
479 | * @axis_tag: Tag of the axis |
480 | * @axis_min_value: Minimum value of the axis variation range to set |
481 | * @axis_max_value: Maximum value of the axis variation range to set |
482 | * |
483 | * Restricting the range of variation on an axis in the given subset input object. |
484 | * New min/max values will be clamped if they're not within the fvar axis range. |
485 | * If the fvar axis default value is not within the new range, the new default |
486 | * value will be changed to the new min or max value, whichever is closer to the fvar |
487 | * axis default. |
488 | * |
489 | * Note: input min value can not be bigger than input max value |
490 | * Note: currently this API does not support changing axis limits yet.It'd be only |
491 | * used internally for setting axis limits in the internal data structures |
492 | * |
493 | * Return value: `true` if success, `false` otherwise |
494 | * |
495 | * XSince: EXPERIMENTAL |
496 | **/ |
497 | HB_EXTERN hb_bool_t |
498 | hb_subset_input_set_axis_range (hb_subset_input_t *input, |
499 | hb_face_t *face, |
500 | hb_tag_t axis_tag, |
501 | float axis_min_value, |
502 | float axis_max_value) |
503 | { |
504 | if (axis_min_value > axis_max_value) |
505 | return false; |
506 | |
507 | hb_ot_var_axis_info_t axis_info; |
508 | if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) |
509 | return false; |
510 | |
511 | float new_min_val = hb_clamp(axis_min_value, axis_info.min_value, axis_info.max_value); |
512 | float new_max_val = hb_clamp(axis_max_value, axis_info.min_value, axis_info.max_value); |
513 | float new_default_val = hb_clamp(axis_info.default_value, new_min_val, new_max_val); |
514 | return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val)); |
515 | } |
516 | #endif |
517 | #endif |
518 | |
519 | /** |
520 | * hb_subset_preprocess: |
521 | * @source: a #hb_face_t object. |
522 | * |
523 | * Preprocesses the face and attaches data that will be needed by the |
524 | * subsetter. Future subsetting operations can then use the precomputed data |
525 | * to speed up the subsetting operation. |
526 | * |
527 | * See [subset-preprocessing](https://github.com/harfbuzz/harfbuzz/blob/main/docs/subset-preprocessing.md) |
528 | * for more information. |
529 | * |
530 | * Note: the preprocessed face may contain sub-blobs that reference the memory |
531 | * backing the source #hb_face_t. Therefore in the case that this memory is not |
532 | * owned by the source face you will need to ensure that memory lives |
533 | * as long as the returned #hb_face_t. |
534 | * |
535 | * Returns: a new #hb_face_t. |
536 | * |
537 | * Since: 6.0.0 |
538 | **/ |
539 | |
540 | HB_EXTERN hb_face_t * |
541 | hb_subset_preprocess (hb_face_t *source) |
542 | { |
543 | hb_subset_input_t* input = hb_subset_input_create_or_fail (); |
544 | if (!input) |
545 | return hb_face_reference (source); |
546 | |
547 | hb_subset_input_keep_everything (input); |
548 | |
549 | input->attach_accelerator_data = true; |
550 | |
551 | // Always use long loca in the preprocessed version. This allows |
552 | // us to store the glyph bytes unpadded which allows the future subset |
553 | // operation to run faster by skipping the trim padding step. |
554 | input->force_long_loca = true; |
555 | |
556 | hb_face_t* new_source = hb_subset_or_fail (source, input); |
557 | hb_subset_input_destroy (input); |
558 | |
559 | if (!new_source) { |
560 | DEBUG_MSG (SUBSET, nullptr, "Preprocessing failed due to subset failure." ); |
561 | return hb_face_reference (source); |
562 | } |
563 | |
564 | return new_source; |
565 | } |
566 | |
567 | /** |
568 | * hb_subset_input_old_to_new_glyph_mapping: |
569 | * @input: a #hb_subset_input_t object. |
570 | * |
571 | * Returns a map which can be used to provide an explicit mapping from old to new glyph |
572 | * id's in the produced subset. The caller should populate the map as desired. |
573 | * If this map is left empty then glyph ids will be automatically mapped to new |
574 | * values by the subsetter. If populated, the mapping must be unique. That |
575 | * is no two original glyph ids can be mapped to the same new id. |
576 | * Additionally, if a mapping is provided then the retain gids option cannot |
577 | * be enabled. |
578 | * |
579 | * Any glyphs that are retained in the subset which are not specified |
580 | * in this mapping will be assigned glyph ids after the highest glyph |
581 | * id in the mapping. |
582 | * |
583 | * Note: this will accept and apply non-monotonic mappings, however this |
584 | * may result in unsorted Coverage tables. Such fonts may not work for all |
585 | * use cases (for example ots will reject unsorted coverage tables). So it's |
586 | * recommended, if possible, to supply a monotonic mapping. |
587 | * |
588 | * Return value: (transfer none): pointer to the #hb_map_t of the custom glyphs ID map. |
589 | * |
590 | * Since: 7.3.0 |
591 | **/ |
592 | HB_EXTERN hb_map_t* |
593 | hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input) |
594 | { |
595 | return &input->glyph_map; |
596 | } |
597 | |
598 | #ifdef HB_EXPERIMENTAL_API |
599 | /** |
600 | * hb_subset_input_override_name_table: |
601 | * @input: a #hb_subset_input_t object. |
602 | * @name_id: name_id of a nameRecord |
603 | * @platform_id: platform ID of a nameRecord |
604 | * @encoding_id: encoding ID of a nameRecord |
605 | * @language_id: language ID of a nameRecord |
606 | * @name_str: pointer to name string new value or null to indicate should remove |
607 | * @str_len: the size of @name_str, or -1 if it is `NULL`-terminated |
608 | * |
609 | * Override the name string of the NameRecord identified by name_id, |
610 | * platform_id, encoding_id and language_id. If a record with that name_id |
611 | * doesn't exist, create it and insert to the name table. |
612 | * |
613 | * Note: for mac platform, we only support name_str with all ascii characters, |
614 | * name_str with non-ascii characters will be ignored. |
615 | * |
616 | * XSince: EXPERIMENTAL |
617 | **/ |
618 | HB_EXTERN hb_bool_t |
619 | hb_subset_input_override_name_table (hb_subset_input_t *input, |
620 | hb_ot_name_id_t name_id, |
621 | unsigned platform_id, |
622 | unsigned encoding_id, |
623 | unsigned language_id, |
624 | const char *name_str, |
625 | int str_len /* -1 means nul-terminated */) |
626 | { |
627 | if (!name_str) |
628 | { |
629 | str_len = 0; |
630 | } |
631 | else if (str_len == -1) |
632 | { |
633 | str_len = strlen (name_str); |
634 | } |
635 | |
636 | hb_bytes_t name_bytes (nullptr, 0); |
637 | if (str_len) |
638 | { |
639 | if (platform_id == 1) |
640 | { |
641 | const uint8_t *src = reinterpret_cast<const uint8_t*> (name_str); |
642 | const uint8_t *src_end = src + str_len; |
643 | |
644 | hb_codepoint_t unicode; |
645 | const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; |
646 | while (src < src_end) |
647 | { |
648 | src = hb_utf8_t::next (src, src_end, &unicode, replacement); |
649 | if (unicode >= 0x0080u) |
650 | { |
651 | printf ("Non-ascii character detected, ignored...This API supports acsii characters only for mac platform\n" ); |
652 | return false; |
653 | } |
654 | } |
655 | } |
656 | char *override_name = (char *) hb_malloc (str_len); |
657 | if (unlikely (!override_name)) return false; |
658 | |
659 | hb_memcpy (override_name, name_str, str_len); |
660 | name_bytes = hb_bytes_t (override_name, str_len); |
661 | } |
662 | input->name_table_overrides.set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes); |
663 | return true; |
664 | } |
665 | |
666 | #endif |
667 | |