/src/harfbuzz/src/hb-face.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright © 2009 Red Hat, Inc. |
3 | | * Copyright © 2012 Google, Inc. |
4 | | * |
5 | | * This is part of HarfBuzz, a text shaping library. |
6 | | * |
7 | | * Permission is hereby granted, without written agreement and without |
8 | | * license or royalty fees, to use, copy, modify, and distribute this |
9 | | * software and its documentation for any purpose, provided that the |
10 | | * above copyright notice and the following two paragraphs appear in |
11 | | * all copies of this software. |
12 | | * |
13 | | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
14 | | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
15 | | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
16 | | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
17 | | * DAMAGE. |
18 | | * |
19 | | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
20 | | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
21 | | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
22 | | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
23 | | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
24 | | * |
25 | | * Red Hat Author(s): Behdad Esfahbod |
26 | | * Google Author(s): Behdad Esfahbod |
27 | | */ |
28 | | |
29 | | #include "hb.hh" |
30 | | |
31 | | #include "hb-face.hh" |
32 | | #include "hb-blob.hh" |
33 | | #include "hb-open-file.hh" |
34 | | #include "hb-ot-face.hh" |
35 | | #include "hb-ot-cmap-table.hh" |
36 | | |
37 | | |
38 | | /** |
39 | | * SECTION:hb-face |
40 | | * @title: hb-face |
41 | | * @short_description: Font face objects |
42 | | * @include: hb.h |
43 | | * |
44 | | * A font face is an object that represents a single face from within a |
45 | | * font family. |
46 | | * |
47 | | * More precisely, a font face represents a single face in a binary font file. |
48 | | * Font faces are typically built from a binary blob and a face index. |
49 | | * Font faces are used to create fonts. |
50 | | **/ |
51 | | |
52 | | |
53 | | /** |
54 | | * hb_face_count: |
55 | | * @blob: a blob. |
56 | | * |
57 | | * Fetches the number of faces in a blob. |
58 | | * |
59 | | * Return value: Number of faces in @blob |
60 | | * |
61 | | * Since: 1.7.7 |
62 | | **/ |
63 | | unsigned int |
64 | | hb_face_count (hb_blob_t *blob) |
65 | 0 | { |
66 | 0 | if (unlikely (!blob)) |
67 | 0 | return 0; |
68 | | |
69 | | /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */ |
70 | | /* Make API signature const after. */ |
71 | 0 | hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)); |
72 | 0 | const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> (); |
73 | 0 | unsigned int ret = ot.get_face_count (); |
74 | 0 | hb_blob_destroy (sanitized); |
75 | |
|
76 | 0 | return ret; |
77 | 0 | } |
78 | | |
79 | | /* |
80 | | * hb_face_t |
81 | | */ |
82 | | |
83 | | DEFINE_NULL_INSTANCE (hb_face_t) = |
84 | | { |
85 | | HB_OBJECT_HEADER_STATIC, |
86 | | |
87 | | nullptr, /* reference_table_func */ |
88 | | nullptr, /* user_data */ |
89 | | nullptr, /* destroy */ |
90 | | |
91 | | 0, /* index */ |
92 | | 1000, /* upem */ |
93 | | 0, /* num_glyphs */ |
94 | | |
95 | | /* Zero for the rest is fine. */ |
96 | | }; |
97 | | |
98 | | |
99 | | /** |
100 | | * hb_face_create_for_tables: |
101 | | * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): Table-referencing function |
102 | | * @user_data: A pointer to the user data |
103 | | * @destroy: (nullable): A callback to call when @data is not needed anymore |
104 | | * |
105 | | * Variant of hb_face_create(), built for those cases where it is more |
106 | | * convenient to provide data for individual tables instead of the whole font |
107 | | * data. With the caveat that hb_face_get_table_tags() does not currently work |
108 | | * with faces created this way. |
109 | | * |
110 | | * Creates a new face object from the specified @user_data and @reference_table_func, |
111 | | * with the @destroy callback. |
112 | | * |
113 | | * Return value: (transfer full): The new face object |
114 | | * |
115 | | * Since: 0.9.2 |
116 | | **/ |
117 | | hb_face_t * |
118 | | hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, |
119 | | void *user_data, |
120 | | hb_destroy_func_t destroy) |
121 | 331k | { |
122 | 331k | hb_face_t *face; |
123 | | |
124 | 331k | if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) { |
125 | 226 | if (destroy) |
126 | 226 | destroy (user_data); |
127 | 226 | return hb_face_get_empty (); |
128 | 226 | } |
129 | | |
130 | 331k | face->reference_table_func = reference_table_func; |
131 | 331k | face->user_data = user_data; |
132 | 331k | face->destroy = destroy; |
133 | | |
134 | 331k | face->num_glyphs = -1; |
135 | | |
136 | 331k | face->data.init0 (face); |
137 | 331k | face->table.init0 (face); |
138 | | |
139 | 331k | return face; |
140 | 331k | } |
141 | | |
142 | | |
143 | | typedef struct hb_face_for_data_closure_t { |
144 | | hb_blob_t *blob; |
145 | | uint16_t index; |
146 | | } hb_face_for_data_closure_t; |
147 | | |
148 | | static hb_face_for_data_closure_t * |
149 | | _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) |
150 | 332k | { |
151 | 332k | hb_face_for_data_closure_t *closure; |
152 | | |
153 | 332k | closure = (hb_face_for_data_closure_t *) hb_calloc (1, sizeof (hb_face_for_data_closure_t)); |
154 | 332k | if (unlikely (!closure)) |
155 | 323 | return nullptr; |
156 | | |
157 | 331k | closure->blob = blob; |
158 | 331k | closure->index = (uint16_t) (index & 0xFFFFu); |
159 | | |
160 | 331k | return closure; |
161 | 332k | } |
162 | | |
163 | | static void |
164 | | _hb_face_for_data_closure_destroy (void *data) |
165 | 331k | { |
166 | 331k | hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data; |
167 | | |
168 | 331k | hb_blob_destroy (closure->blob); |
169 | 331k | hb_free (closure); |
170 | 331k | } |
171 | | |
172 | | static hb_blob_t * |
173 | | _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) |
174 | 12.6M | { |
175 | 12.6M | hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data; |
176 | | |
177 | 12.6M | if (tag == HB_TAG_NONE) |
178 | 0 | return hb_blob_reference (data->blob); |
179 | | |
180 | 12.6M | const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> (); |
181 | 12.6M | unsigned int base_offset; |
182 | 12.6M | const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset); |
183 | | |
184 | 12.6M | const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag); |
185 | | |
186 | 12.6M | hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length); |
187 | | |
188 | 12.6M | return blob; |
189 | 12.6M | } |
190 | | |
191 | | /** |
192 | | * hb_face_create: |
193 | | * @blob: #hb_blob_t to work upon |
194 | | * @index: The index of the face within @blob |
195 | | * |
196 | | * Constructs a new face object from the specified blob and |
197 | | * a face index into that blob. |
198 | | * |
199 | | * The face index is used for blobs of file formats such as TTC and |
200 | | * and DFont that can contain more than one face. Face indices within |
201 | | * such collections are zero-based. |
202 | | * |
203 | | * <note>Note: If the blob font format is not a collection, @index |
204 | | * is ignored. Otherwise, only the lower 16-bits of @index are used. |
205 | | * The unmodified @index can be accessed via hb_face_get_index().</note> |
206 | | * |
207 | | * <note>Note: The high 16-bits of @index, if non-zero, are used by |
208 | | * hb_font_create() to load named-instances in variable fonts. See |
209 | | * hb_font_create() for details.</note> |
210 | | * |
211 | | * Return value: (transfer full): The new face object |
212 | | * |
213 | | * Since: 0.9.2 |
214 | | **/ |
215 | | hb_face_t * |
216 | | hb_face_create (hb_blob_t *blob, |
217 | | unsigned int index) |
218 | 332k | { |
219 | 332k | hb_face_t *face; |
220 | | |
221 | 332k | if (unlikely (!blob)) |
222 | 0 | blob = hb_blob_get_empty (); |
223 | | |
224 | 332k | blob = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)); |
225 | | |
226 | 332k | hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (blob, index); |
227 | | |
228 | 332k | if (unlikely (!closure)) |
229 | 323 | { |
230 | 323 | hb_blob_destroy (blob); |
231 | 323 | return hb_face_get_empty (); |
232 | 323 | } |
233 | | |
234 | 331k | face = hb_face_create_for_tables (_hb_face_for_data_reference_table, |
235 | 331k | closure, |
236 | 331k | _hb_face_for_data_closure_destroy); |
237 | | |
238 | 331k | face->index = index; |
239 | | |
240 | 331k | return face; |
241 | 332k | } |
242 | | |
243 | | /** |
244 | | * hb_face_get_empty: |
245 | | * |
246 | | * Fetches the singleton empty face object. |
247 | | * |
248 | | * Return value: (transfer full): The empty face object |
249 | | * |
250 | | * Since: 0.9.2 |
251 | | **/ |
252 | | hb_face_t * |
253 | | hb_face_get_empty () |
254 | 549 | { |
255 | 549 | return const_cast<hb_face_t *> (&Null (hb_face_t)); |
256 | 549 | } |
257 | | |
258 | | |
259 | | /** |
260 | | * hb_face_reference: (skip) |
261 | | * @face: A face object |
262 | | * |
263 | | * Increases the reference count on a face object. |
264 | | * |
265 | | * Return value: The @face object |
266 | | * |
267 | | * Since: 0.9.2 |
268 | | **/ |
269 | | hb_face_t * |
270 | | hb_face_reference (hb_face_t *face) |
271 | 331k | { |
272 | 331k | return hb_object_reference (face); |
273 | 331k | } |
274 | | |
275 | | /** |
276 | | * hb_face_destroy: (skip) |
277 | | * @face: A face object |
278 | | * |
279 | | * Decreases the reference count on a face object. When the |
280 | | * reference count reaches zero, the face is destroyed, |
281 | | * freeing all memory. |
282 | | * |
283 | | * Since: 0.9.2 |
284 | | **/ |
285 | | void |
286 | | hb_face_destroy (hb_face_t *face) |
287 | 663k | { |
288 | 663k | if (!hb_object_destroy (face)) return; |
289 | | |
290 | 331k | #ifndef HB_NO_SHAPER |
291 | 811k | for (hb_face_t::plan_node_t *node = face->shape_plans; node; ) |
292 | 479k | { |
293 | 479k | hb_face_t::plan_node_t *next = node->next; |
294 | 479k | hb_shape_plan_destroy (node->shape_plan); |
295 | 479k | hb_free (node); |
296 | 479k | node = next; |
297 | 479k | } |
298 | 331k | #endif |
299 | | |
300 | 331k | face->data.fini (); |
301 | 331k | face->table.fini (); |
302 | | |
303 | 331k | if (face->destroy) |
304 | 331k | face->destroy (face->user_data); |
305 | | |
306 | 331k | hb_free (face); |
307 | 331k | } |
308 | | |
309 | | /** |
310 | | * hb_face_set_user_data: (skip) |
311 | | * @face: A face object |
312 | | * @key: The user-data key to set |
313 | | * @data: A pointer to the user data |
314 | | * @destroy: (nullable): A callback to call when @data is not needed anymore |
315 | | * @replace: Whether to replace an existing data with the same key |
316 | | * |
317 | | * Attaches a user-data key/data pair to the given face object. |
318 | | * |
319 | | * Return value: `true` if success, `false` otherwise |
320 | | * |
321 | | * Since: 0.9.2 |
322 | | **/ |
323 | | hb_bool_t |
324 | | hb_face_set_user_data (hb_face_t *face, |
325 | | hb_user_data_key_t *key, |
326 | | void * data, |
327 | | hb_destroy_func_t destroy, |
328 | | hb_bool_t replace) |
329 | 349k | { |
330 | 349k | return hb_object_set_user_data (face, key, data, destroy, replace); |
331 | 349k | } |
332 | | |
333 | | /** |
334 | | * hb_face_get_user_data: (skip) |
335 | | * @face: A face object |
336 | | * @key: The user-data key to query |
337 | | * |
338 | | * Fetches the user data associated with the specified key, |
339 | | * attached to the specified face object. |
340 | | * |
341 | | * Return value: (transfer none): A pointer to the user data |
342 | | * |
343 | | * Since: 0.9.2 |
344 | | **/ |
345 | | void * |
346 | | hb_face_get_user_data (const hb_face_t *face, |
347 | | hb_user_data_key_t *key) |
348 | 976k | { |
349 | 976k | return hb_object_get_user_data (face, key); |
350 | 976k | } |
351 | | |
352 | | /** |
353 | | * hb_face_make_immutable: |
354 | | * @face: A face object |
355 | | * |
356 | | * Makes the given face object immutable. |
357 | | * |
358 | | * Since: 0.9.2 |
359 | | **/ |
360 | | void |
361 | | hb_face_make_immutable (hb_face_t *face) |
362 | 821k | { |
363 | 821k | if (hb_object_is_immutable (face)) |
364 | 490k | return; |
365 | | |
366 | 331k | hb_object_make_immutable (face); |
367 | 331k | } |
368 | | |
369 | | /** |
370 | | * hb_face_is_immutable: |
371 | | * @face: A face object |
372 | | * |
373 | | * Tests whether the given face object is immutable. |
374 | | * |
375 | | * Return value: `true` is @face is immutable, `false` otherwise |
376 | | * |
377 | | * Since: 0.9.2 |
378 | | **/ |
379 | | hb_bool_t |
380 | | hb_face_is_immutable (const hb_face_t *face) |
381 | 0 | { |
382 | 0 | return hb_object_is_immutable (face); |
383 | 0 | } |
384 | | |
385 | | |
386 | | /** |
387 | | * hb_face_reference_table: |
388 | | * @face: A face object |
389 | | * @tag: The #hb_tag_t of the table to query |
390 | | * |
391 | | * Fetches a reference to the specified table within |
392 | | * the specified face. |
393 | | * |
394 | | * Return value: (transfer full): A pointer to the @tag table within @face |
395 | | * |
396 | | * Since: 0.9.2 |
397 | | **/ |
398 | | hb_blob_t * |
399 | | hb_face_reference_table (const hb_face_t *face, |
400 | | hb_tag_t tag) |
401 | 12.6M | { |
402 | 12.6M | if (unlikely (tag == HB_TAG_NONE)) |
403 | 0 | return hb_blob_get_empty (); |
404 | | |
405 | 12.6M | return face->reference_table (tag); |
406 | 12.6M | } |
407 | | |
408 | | /** |
409 | | * hb_face_reference_blob: |
410 | | * @face: A face object |
411 | | * |
412 | | * Fetches a pointer to the binary blob that contains the |
413 | | * specified face. Returns an empty blob if referencing face data is not |
414 | | * possible. |
415 | | * |
416 | | * Return value: (transfer full): A pointer to the blob for @face |
417 | | * |
418 | | * Since: 0.9.2 |
419 | | **/ |
420 | | hb_blob_t * |
421 | | hb_face_reference_blob (hb_face_t *face) |
422 | 0 | { |
423 | 0 | return face->reference_table (HB_TAG_NONE); |
424 | 0 | } |
425 | | |
426 | | /** |
427 | | * hb_face_set_index: |
428 | | * @face: A face object |
429 | | * @index: The index to assign |
430 | | * |
431 | | * Assigns the specified face-index to @face. Fails if the |
432 | | * face is immutable. |
433 | | * |
434 | | * <note>Note: changing the index has no effect on the face itself |
435 | | * This only changes the value returned by hb_face_get_index().</note> |
436 | | * |
437 | | * Since: 0.9.2 |
438 | | **/ |
439 | | void |
440 | | hb_face_set_index (hb_face_t *face, |
441 | | unsigned int index) |
442 | 0 | { |
443 | 0 | if (hb_object_is_immutable (face)) |
444 | 0 | return; |
445 | | |
446 | 0 | face->index = index; |
447 | 0 | } |
448 | | |
449 | | /** |
450 | | * hb_face_get_index: |
451 | | * @face: A face object |
452 | | * |
453 | | * Fetches the face-index corresponding to the given face. |
454 | | * |
455 | | * <note>Note: face indices within a collection are zero-based.</note> |
456 | | * |
457 | | * Return value: The index of @face. |
458 | | * |
459 | | * Since: 0.9.2 |
460 | | **/ |
461 | | unsigned int |
462 | | hb_face_get_index (const hb_face_t *face) |
463 | 0 | { |
464 | 0 | return face->index; |
465 | 0 | } |
466 | | |
467 | | /** |
468 | | * hb_face_set_upem: |
469 | | * @face: A face object |
470 | | * @upem: The units-per-em value to assign |
471 | | * |
472 | | * Sets the units-per-em (upem) for a face object to the specified value. |
473 | | * |
474 | | * This API is used in rare circumstances. |
475 | | * |
476 | | * Since: 0.9.2 |
477 | | **/ |
478 | | void |
479 | | hb_face_set_upem (hb_face_t *face, |
480 | | unsigned int upem) |
481 | 0 | { |
482 | 0 | if (hb_object_is_immutable (face)) |
483 | 0 | return; |
484 | | |
485 | 0 | face->upem = upem; |
486 | 0 | } |
487 | | |
488 | | /** |
489 | | * hb_face_get_upem: |
490 | | * @face: A face object |
491 | | * |
492 | | * Fetches the units-per-em (UPEM) value of the specified face object. |
493 | | * |
494 | | * Typical UPEM values for fonts are 1000, or 2048, but any value |
495 | | * in between 16 and 16,384 is allowed for OpenType fonts. |
496 | | * |
497 | | * Return value: The upem value of @face |
498 | | * |
499 | | * Since: 0.9.2 |
500 | | **/ |
501 | | unsigned int |
502 | | hb_face_get_upem (const hb_face_t *face) |
503 | 972k | { |
504 | 972k | return face->get_upem (); |
505 | 972k | } |
506 | | |
507 | | /** |
508 | | * hb_face_set_glyph_count: |
509 | | * @face: A face object |
510 | | * @glyph_count: The glyph-count value to assign |
511 | | * |
512 | | * Sets the glyph count for a face object to the specified value. |
513 | | * |
514 | | * This API is used in rare circumstances. |
515 | | * |
516 | | * Since: 0.9.7 |
517 | | **/ |
518 | | void |
519 | | hb_face_set_glyph_count (hb_face_t *face, |
520 | | unsigned int glyph_count) |
521 | 0 | { |
522 | 0 | if (hb_object_is_immutable (face)) |
523 | 0 | return; |
524 | | |
525 | 0 | face->num_glyphs = glyph_count; |
526 | 0 | } |
527 | | |
528 | | /** |
529 | | * hb_face_get_glyph_count: |
530 | | * @face: A face object |
531 | | * |
532 | | * Fetches the glyph-count value of the specified face object. |
533 | | * |
534 | | * Return value: The glyph-count value of @face |
535 | | * |
536 | | * Since: 0.9.7 |
537 | | **/ |
538 | | unsigned int |
539 | | hb_face_get_glyph_count (const hb_face_t *face) |
540 | 7.76M | { |
541 | 7.76M | return face->get_num_glyphs (); |
542 | 7.76M | } |
543 | | |
544 | | /** |
545 | | * hb_face_get_table_tags: |
546 | | * @face: A face object |
547 | | * @start_offset: The index of first table tag to retrieve |
548 | | * @table_count: (inout): Input = the maximum number of table tags to return; |
549 | | * Output = the actual number of table tags returned (may be zero) |
550 | | * @table_tags: (out) (array length=table_count): The array of table tags found |
551 | | * |
552 | | * Fetches a list of all table tags for a face, if possible. The list returned will |
553 | | * begin at the offset provided |
554 | | * |
555 | | * Return value: Total number of tables, or zero if it is not possible to list |
556 | | * |
557 | | * Since: 1.6.0 |
558 | | **/ |
559 | | unsigned int |
560 | | hb_face_get_table_tags (const hb_face_t *face, |
561 | | unsigned int start_offset, |
562 | | unsigned int *table_count, /* IN/OUT */ |
563 | | hb_tag_t *table_tags /* OUT */) |
564 | 0 | { |
565 | 0 | if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy) |
566 | 0 | { |
567 | 0 | if (table_count) |
568 | 0 | *table_count = 0; |
569 | 0 | return 0; |
570 | 0 | } |
571 | | |
572 | 0 | hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data; |
573 | |
|
574 | 0 | const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> (); |
575 | 0 | const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); |
576 | |
|
577 | 0 | return ot_face.get_table_tags (start_offset, table_count, table_tags); |
578 | 0 | } |
579 | | |
580 | | |
581 | | /* |
582 | | * Character set. |
583 | | */ |
584 | | |
585 | | |
586 | | #ifndef HB_NO_FACE_COLLECT_UNICODES |
587 | | /** |
588 | | * hb_face_collect_unicodes: |
589 | | * @face: A face object |
590 | | * @out: (out): The set to add Unicode characters to |
591 | | * |
592 | | * Collects all of the Unicode characters covered by @face and adds |
593 | | * them to the #hb_set_t set @out. |
594 | | * |
595 | | * Since: 1.9.0 |
596 | | */ |
597 | | void |
598 | | hb_face_collect_unicodes (hb_face_t *face, |
599 | | hb_set_t *out) |
600 | 332k | { |
601 | 332k | face->table.cmap->collect_unicodes (out, face->get_num_glyphs ()); |
602 | 332k | } |
603 | | /** |
604 | | * hb_face_collect_nominal_glyph_mapping: |
605 | | * @face: A face object |
606 | | * @mapping: (out): The map to add Unicode-to-glyph mapping to |
607 | | * @unicodes: (nullable) (out): The set to add Unicode characters to, or `NULL` |
608 | | * |
609 | | * Collects the mapping from Unicode characters to nominal glyphs of the @face, |
610 | | * and optionally all of the Unicode characters covered by @face. |
611 | | * |
612 | | * Since: REPLACEME |
613 | | */ |
614 | | void |
615 | | hb_face_collect_nominal_glyph_mapping (hb_face_t *face, |
616 | | hb_map_t *mapping, |
617 | | hb_set_t *unicodes) |
618 | 0 | { |
619 | 0 | hb_set_t stack_unicodes; |
620 | 0 | if (!unicodes) |
621 | 0 | unicodes = &stack_unicodes; |
622 | 0 | face->table.cmap->collect_mapping (unicodes, mapping, face->get_num_glyphs ()); |
623 | 0 | } |
624 | | /** |
625 | | * hb_face_collect_variation_selectors: |
626 | | * @face: A face object |
627 | | * @out: (out): The set to add Variation Selector characters to |
628 | | * |
629 | | * Collects all Unicode "Variation Selector" characters covered by @face and adds |
630 | | * them to the #hb_set_t set @out. |
631 | | * |
632 | | * Since: 1.9.0 |
633 | | */ |
634 | | void |
635 | | hb_face_collect_variation_selectors (hb_face_t *face, |
636 | | hb_set_t *out) |
637 | 332k | { |
638 | 332k | face->table.cmap->collect_variation_selectors (out); |
639 | 332k | } |
640 | | /** |
641 | | * hb_face_collect_variation_unicodes: |
642 | | * @face: A face object |
643 | | * @variation_selector: The Variation Selector to query |
644 | | * @out: (out): The set to add Unicode characters to |
645 | | * |
646 | | * Collects all Unicode characters for @variation_selector covered by @face and adds |
647 | | * them to the #hb_set_t set @out. |
648 | | * |
649 | | * Since: 1.9.0 |
650 | | */ |
651 | | void |
652 | | hb_face_collect_variation_unicodes (hb_face_t *face, |
653 | | hb_codepoint_t variation_selector, |
654 | | hb_set_t *out) |
655 | 332k | { |
656 | 332k | face->table.cmap->collect_variation_unicodes (variation_selector, out); |
657 | 332k | } |
658 | | #endif |