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 * Font face is objects represent a single face in a font family.
45 * More exactly, a font face represents a single face in a binary font file.
46 * Font faces are typically built from a binary blob and a face index.
47 * Font faces are used to create fonts.
48 **/
49
50
51 /**
52 * hb_face_count:
53 * @blob: a blob.
54 *
55 * Get number of faces in a blob.
56 *
57 * Return value: Number of faces in @blob
58 *
59 * Since: 1.7.7
60 **/
61 unsigned int
hb_face_count(hb_blob_t * blob)62 hb_face_count (hb_blob_t *blob)
63 {
64 if (unlikely (!blob))
65 return 0;
66
67 /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
68 /* Make API signature const after. */
69 hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
70 const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
71 unsigned int ret = ot.get_face_count ();
72 hb_blob_destroy (sanitized);
73
74 return ret;
75 }
76
77 /*
78 * hb_face_t
79 */
80
81 DEFINE_NULL_INSTANCE (hb_face_t) =
82 {
83 HB_OBJECT_HEADER_STATIC,
84
85 nullptr, /* reference_table_func */
86 nullptr, /* user_data */
87 nullptr, /* destroy */
88
89 0, /* index */
90 HB_ATOMIC_INT_INIT (1000), /* upem */
91 HB_ATOMIC_INT_INIT (0), /* num_glyphs */
92
93 /* Zero for the rest is fine. */
94 };
95
96
97 /**
98 * hb_face_create_for_tables:
99 * @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
100 * @user_data:
101 * @destroy:
102 *
103 *
104 *
105 * Return value: (transfer full)
106 *
107 * Since: 0.9.2
108 **/
109 hb_face_t *
hb_face_create_for_tables(hb_reference_table_func_t reference_table_func,void * user_data,hb_destroy_func_t destroy)110 hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
111 void *user_data,
112 hb_destroy_func_t destroy)
113 {
114 hb_face_t *face;
115
116 if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
117 if (destroy)
118 destroy (user_data);
119 return hb_face_get_empty ();
120 }
121
122 face->reference_table_func = reference_table_func;
123 face->user_data = user_data;
124 face->destroy = destroy;
125
126 face->num_glyphs.set_relaxed (-1);
127
128 face->data.init0 (face);
129 face->table.init0 (face);
130
131 return face;
132 }
133
134
135 typedef struct hb_face_for_data_closure_t {
136 hb_blob_t *blob;
137 unsigned int index;
138 } hb_face_for_data_closure_t;
139
140 static hb_face_for_data_closure_t *
_hb_face_for_data_closure_create(hb_blob_t * blob,unsigned int index)141 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
142 {
143 hb_face_for_data_closure_t *closure;
144
145 closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
146 if (unlikely (!closure))
147 return nullptr;
148
149 closure->blob = blob;
150 closure->index = index;
151
152 return closure;
153 }
154
155 static void
_hb_face_for_data_closure_destroy(void * data)156 _hb_face_for_data_closure_destroy (void *data)
157 {
158 hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
159
160 hb_blob_destroy (closure->blob);
161 free (closure);
162 }
163
164 static hb_blob_t *
_hb_face_for_data_reference_table(hb_face_t * face HB_UNUSED,hb_tag_t tag,void * user_data)165 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
166 {
167 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
168
169 if (tag == HB_TAG_NONE)
170 return hb_blob_reference (data->blob);
171
172 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
173 unsigned int base_offset;
174 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
175
176 const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
177
178 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
179
180 return blob;
181 }
182
183 /**
184 * hb_face_create: (Xconstructor)
185 * @blob:
186 * @index:
187 *
188 *
189 *
190 * Return value: (transfer full):
191 *
192 * Since: 0.9.2
193 **/
194 hb_face_t *
hb_face_create(hb_blob_t * blob,unsigned int index)195 hb_face_create (hb_blob_t *blob,
196 unsigned int index)
197 {
198 hb_face_t *face;
199
200 if (unlikely (!blob))
201 blob = hb_blob_get_empty ();
202
203 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
204
205 if (unlikely (!closure))
206 return hb_face_get_empty ();
207
208 face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
209 closure,
210 _hb_face_for_data_closure_destroy);
211
212 face->index = index;
213
214 return face;
215 }
216
217 /**
218 * hb_face_get_empty:
219 *
220 *
221 *
222 * Return value: (transfer full)
223 *
224 * Since: 0.9.2
225 **/
226 hb_face_t *
hb_face_get_empty()227 hb_face_get_empty ()
228 {
229 return const_cast<hb_face_t *> (&Null(hb_face_t));
230 }
231
232
233 /**
234 * hb_face_reference: (skip)
235 * @face: a face.
236 *
237 *
238 *
239 * Return value:
240 *
241 * Since: 0.9.2
242 **/
243 hb_face_t *
hb_face_reference(hb_face_t * face)244 hb_face_reference (hb_face_t *face)
245 {
246 return hb_object_reference (face);
247 }
248
249 /**
250 * hb_face_destroy: (skip)
251 * @face: a face.
252 *
253 *
254 *
255 * Since: 0.9.2
256 **/
257 void
hb_face_destroy(hb_face_t * face)258 hb_face_destroy (hb_face_t *face)
259 {
260 if (!hb_object_destroy (face)) return;
261
262 for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
263 {
264 hb_face_t::plan_node_t *next = node->next;
265 hb_shape_plan_destroy (node->shape_plan);
266 free (node);
267 node = next;
268 }
269
270 face->data.fini ();
271 face->table.fini ();
272
273 if (face->destroy)
274 face->destroy (face->user_data);
275
276 free (face);
277 }
278
279 /**
280 * hb_face_set_user_data: (skip)
281 * @face: a face.
282 * @key:
283 * @data:
284 * @destroy:
285 * @replace:
286 *
287 *
288 *
289 * Return value:
290 *
291 * Since: 0.9.2
292 **/
293 hb_bool_t
hb_face_set_user_data(hb_face_t * face,hb_user_data_key_t * key,void * data,hb_destroy_func_t destroy,hb_bool_t replace)294 hb_face_set_user_data (hb_face_t *face,
295 hb_user_data_key_t *key,
296 void * data,
297 hb_destroy_func_t destroy,
298 hb_bool_t replace)
299 {
300 return hb_object_set_user_data (face, key, data, destroy, replace);
301 }
302
303 /**
304 * hb_face_get_user_data: (skip)
305 * @face: a face.
306 * @key:
307 *
308 *
309 *
310 * Return value: (transfer none):
311 *
312 * Since: 0.9.2
313 **/
314 void *
hb_face_get_user_data(const hb_face_t * face,hb_user_data_key_t * key)315 hb_face_get_user_data (const hb_face_t *face,
316 hb_user_data_key_t *key)
317 {
318 return hb_object_get_user_data (face, key);
319 }
320
321 /**
322 * hb_face_make_immutable:
323 * @face: a face.
324 *
325 *
326 *
327 * Since: 0.9.2
328 **/
329 void
hb_face_make_immutable(hb_face_t * face)330 hb_face_make_immutable (hb_face_t *face)
331 {
332 if (hb_object_is_immutable (face))
333 return;
334
335 hb_object_make_immutable (face);
336 }
337
338 /**
339 * hb_face_is_immutable:
340 * @face: a face.
341 *
342 *
343 *
344 * Return value:
345 *
346 * Since: 0.9.2
347 **/
348 hb_bool_t
hb_face_is_immutable(const hb_face_t * face)349 hb_face_is_immutable (const hb_face_t *face)
350 {
351 return hb_object_is_immutable (face);
352 }
353
354
355 /**
356 * hb_face_reference_table:
357 * @face: a face.
358 * @tag:
359 *
360 *
361 *
362 * Return value: (transfer full):
363 *
364 * Since: 0.9.2
365 **/
366 hb_blob_t *
hb_face_reference_table(const hb_face_t * face,hb_tag_t tag)367 hb_face_reference_table (const hb_face_t *face,
368 hb_tag_t tag)
369 {
370 if (unlikely (tag == HB_TAG_NONE))
371 return hb_blob_get_empty ();
372
373 return face->reference_table (tag);
374 }
375
376 /**
377 * hb_face_reference_blob:
378 * @face: a face.
379 *
380 *
381 *
382 * Return value: (transfer full):
383 *
384 * Since: 0.9.2
385 **/
386 hb_blob_t *
hb_face_reference_blob(hb_face_t * face)387 hb_face_reference_blob (hb_face_t *face)
388 {
389 return face->reference_table (HB_TAG_NONE);
390 }
391
392 /**
393 * hb_face_set_index:
394 * @face: a face.
395 * @index:
396 *
397 *
398 *
399 * Since: 0.9.2
400 **/
401 void
hb_face_set_index(hb_face_t * face,unsigned int index)402 hb_face_set_index (hb_face_t *face,
403 unsigned int index)
404 {
405 if (hb_object_is_immutable (face))
406 return;
407
408 face->index = index;
409 }
410
411 /**
412 * hb_face_get_index:
413 * @face: a face.
414 *
415 *
416 *
417 * Return value:
418 *
419 * Since: 0.9.2
420 **/
421 unsigned int
hb_face_get_index(const hb_face_t * face)422 hb_face_get_index (const hb_face_t *face)
423 {
424 return face->index;
425 }
426
427 /**
428 * hb_face_set_upem:
429 * @face: a face.
430 * @upem:
431 *
432 *
433 *
434 * Since: 0.9.2
435 **/
436 void
hb_face_set_upem(hb_face_t * face,unsigned int upem)437 hb_face_set_upem (hb_face_t *face,
438 unsigned int upem)
439 {
440 if (hb_object_is_immutable (face))
441 return;
442
443 face->upem.set_relaxed (upem);
444 }
445
446 /**
447 * hb_face_get_upem:
448 * @face: a face.
449 *
450 *
451 *
452 * Return value:
453 *
454 * Since: 0.9.2
455 **/
456 unsigned int
hb_face_get_upem(const hb_face_t * face)457 hb_face_get_upem (const hb_face_t *face)
458 {
459 return face->get_upem ();
460 }
461
462 /**
463 * hb_face_set_glyph_count:
464 * @face: a face.
465 * @glyph_count:
466 *
467 *
468 *
469 * Since: 0.9.7
470 **/
471 void
hb_face_set_glyph_count(hb_face_t * face,unsigned int glyph_count)472 hb_face_set_glyph_count (hb_face_t *face,
473 unsigned int glyph_count)
474 {
475 if (hb_object_is_immutable (face))
476 return;
477
478 face->num_glyphs.set_relaxed (glyph_count);
479 }
480
481 /**
482 * hb_face_get_glyph_count:
483 * @face: a face.
484 *
485 *
486 *
487 * Return value:
488 *
489 * Since: 0.9.7
490 **/
491 unsigned int
hb_face_get_glyph_count(const hb_face_t * face)492 hb_face_get_glyph_count (const hb_face_t *face)
493 {
494 return face->get_num_glyphs ();
495 }
496
497 /**
498 * hb_face_get_table_tags:
499 * @face: a face.
500 * @start_offset: index of first tag to return.
501 * @table_count: input length of @table_tags array, output number of items written.
502 * @table_tags: array to write tags into.
503 *
504 * Retrieves table tags for a face, if possible.
505 *
506 * Return value: total number of tables, or 0 if not possible to list.
507 *
508 * Since: 1.6.0
509 **/
510 unsigned int
hb_face_get_table_tags(const hb_face_t * face,unsigned int start_offset,unsigned int * table_count,hb_tag_t * table_tags)511 hb_face_get_table_tags (const hb_face_t *face,
512 unsigned int start_offset,
513 unsigned int *table_count, /* IN/OUT */
514 hb_tag_t *table_tags /* OUT */)
515 {
516 if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
517 {
518 if (table_count)
519 *table_count = 0;
520 return 0;
521 }
522
523 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
524
525 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
526 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
527
528 return ot_face.get_table_tags (start_offset, table_count, table_tags);
529 }
530
531
532 /*
533 * Character set.
534 */
535
536
537 #ifndef HB_NO_FACE_COLLECT_UNICODES
538 /**
539 * hb_face_collect_unicodes:
540 * @face: font face.
541 * @out: set to add Unicode characters covered by @face to.
542 *
543 * Since: 1.9.0
544 */
545 void
hb_face_collect_unicodes(hb_face_t * face,hb_set_t * out)546 hb_face_collect_unicodes (hb_face_t *face,
547 hb_set_t *out)
548 {
549 face->table.cmap->collect_unicodes (out);
550 }
551 /**
552 * hb_face_collect_variation_selectors:
553 * @face: font face.
554 * @out: set to add Variation Selector characters covered by @face to.
555 *
556 *
557 *
558 * Since: 1.9.0
559 */
560 void
hb_face_collect_variation_selectors(hb_face_t * face,hb_set_t * out)561 hb_face_collect_variation_selectors (hb_face_t *face,
562 hb_set_t *out)
563 {
564 face->table.cmap->collect_variation_selectors (out);
565 }
566 /**
567 * hb_face_collect_variation_unicodes:
568 * @face: font face.
569 * @out: set to add Unicode characters for @variation_selector covered by @face to.
570 *
571 *
572 *
573 * Since: 1.9.0
574 */
575 void
hb_face_collect_variation_unicodes(hb_face_t * face,hb_codepoint_t variation_selector,hb_set_t * out)576 hb_face_collect_variation_unicodes (hb_face_t *face,
577 hb_codepoint_t variation_selector,
578 hb_set_t *out)
579 {
580 face->table.cmap->collect_variation_unicodes (variation_selector, out);
581 }
582 #endif
583
584
585 /*
586 * face-builder: A face that has add_table().
587 */
588
589 struct hb_face_builder_data_t
590 {
591 struct table_entry_t
592 {
cmphb_face_builder_data_t::table_entry_t593 int cmp (hb_tag_t t) const
594 {
595 if (t < tag) return -1;
596 if (t > tag) return -1;
597 return 0;
598 }
599
600 hb_tag_t tag;
601 hb_blob_t *blob;
602 };
603
604 hb_vector_t<table_entry_t> tables;
605 };
606
607 static hb_face_builder_data_t *
_hb_face_builder_data_create()608 _hb_face_builder_data_create ()
609 {
610 hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
611 if (unlikely (!data))
612 return nullptr;
613
614 data->tables.init ();
615
616 return data;
617 }
618
619 static void
_hb_face_builder_data_destroy(void * user_data)620 _hb_face_builder_data_destroy (void *user_data)
621 {
622 hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
623
624 for (unsigned int i = 0; i < data->tables.length; i++)
625 hb_blob_destroy (data->tables[i].blob);
626
627 data->tables.fini ();
628
629 free (data);
630 }
631
632 static hb_blob_t *
_hb_face_builder_data_reference_blob(hb_face_builder_data_t * data)633 _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
634 {
635
636 unsigned int table_count = data->tables.length;
637 unsigned int face_length = table_count * 16 + 12;
638
639 for (unsigned int i = 0; i < table_count; i++)
640 face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob));
641
642 char *buf = (char *) malloc (face_length);
643 if (unlikely (!buf))
644 return nullptr;
645
646 hb_serialize_context_t c (buf, face_length);
647 c.propagate_error (data->tables);
648 OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
649
650 bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
651 hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
652
653 bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ());
654
655 c.end_serialize ();
656
657 if (unlikely (!ret))
658 {
659 free (buf);
660 return nullptr;
661 }
662
663 return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
664 }
665
666 static hb_blob_t *
_hb_face_builder_reference_table(hb_face_t * face HB_UNUSED,hb_tag_t tag,void * user_data)667 _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
668 {
669 hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
670
671 if (!tag)
672 return _hb_face_builder_data_reference_blob (data);
673
674 hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
675 if (entry)
676 return hb_blob_reference (entry->blob);
677
678 return nullptr;
679 }
680
681
682 /**
683 * hb_face_builder_create:
684 *
685 * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
686 * After tables are added to the face, it can be compiled to a binary
687 * font file by calling hb_face_reference_blob().
688 *
689 * Return value: (transfer full): New face.
690 *
691 * Since: 1.9.0
692 **/
693 hb_face_t *
hb_face_builder_create()694 hb_face_builder_create ()
695 {
696 hb_face_builder_data_t *data = _hb_face_builder_data_create ();
697 if (unlikely (!data)) return hb_face_get_empty ();
698
699 return hb_face_create_for_tables (_hb_face_builder_reference_table,
700 data,
701 _hb_face_builder_data_destroy);
702 }
703
704 /**
705 * hb_face_builder_add_table:
706 *
707 * Add table for @tag with data provided by @blob to the face. @face must
708 * be created using hb_face_builder_create().
709 *
710 * Since: 1.9.0
711 **/
712 hb_bool_t
hb_face_builder_add_table(hb_face_t * face,hb_tag_t tag,hb_blob_t * blob)713 hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
714 {
715 if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
716 return false;
717
718 hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
719 hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
720
721 entry->tag = tag;
722 entry->blob = hb_blob_reference (blob);
723
724 return true;
725 }
726