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 return face->reference_table (tag);
371 }
372
373 /**
374 * hb_face_reference_blob:
375 * @face: a face.
376 *
377 *
378 *
379 * Return value: (transfer full):
380 *
381 * Since: 0.9.2
382 **/
383 hb_blob_t *
hb_face_reference_blob(hb_face_t * face)384 hb_face_reference_blob (hb_face_t *face)
385 {
386 return face->reference_table (HB_TAG_NONE);
387 }
388
389 /**
390 * hb_face_set_index:
391 * @face: a face.
392 * @index:
393 *
394 *
395 *
396 * Since: 0.9.2
397 **/
398 void
hb_face_set_index(hb_face_t * face,unsigned int index)399 hb_face_set_index (hb_face_t *face,
400 unsigned int index)
401 {
402 if (hb_object_is_immutable (face))
403 return;
404
405 face->index = index;
406 }
407
408 /**
409 * hb_face_get_index:
410 * @face: a face.
411 *
412 *
413 *
414 * Return value:
415 *
416 * Since: 0.9.2
417 **/
418 unsigned int
hb_face_get_index(const hb_face_t * face)419 hb_face_get_index (const hb_face_t *face)
420 {
421 return face->index;
422 }
423
424 /**
425 * hb_face_set_upem:
426 * @face: a face.
427 * @upem:
428 *
429 *
430 *
431 * Since: 0.9.2
432 **/
433 void
hb_face_set_upem(hb_face_t * face,unsigned int upem)434 hb_face_set_upem (hb_face_t *face,
435 unsigned int upem)
436 {
437 if (hb_object_is_immutable (face))
438 return;
439
440 face->upem.set_relaxed (upem);
441 }
442
443 /**
444 * hb_face_get_upem:
445 * @face: a face.
446 *
447 *
448 *
449 * Return value:
450 *
451 * Since: 0.9.2
452 **/
453 unsigned int
hb_face_get_upem(const hb_face_t * face)454 hb_face_get_upem (const hb_face_t *face)
455 {
456 return face->get_upem ();
457 }
458
459 /**
460 * hb_face_set_glyph_count:
461 * @face: a face.
462 * @glyph_count:
463 *
464 *
465 *
466 * Since: 0.9.7
467 **/
468 void
hb_face_set_glyph_count(hb_face_t * face,unsigned int glyph_count)469 hb_face_set_glyph_count (hb_face_t *face,
470 unsigned int glyph_count)
471 {
472 if (hb_object_is_immutable (face))
473 return;
474
475 face->num_glyphs.set_relaxed (glyph_count);
476 }
477
478 /**
479 * hb_face_get_glyph_count:
480 * @face: a face.
481 *
482 *
483 *
484 * Return value:
485 *
486 * Since: 0.9.7
487 **/
488 unsigned int
hb_face_get_glyph_count(const hb_face_t * face)489 hb_face_get_glyph_count (const hb_face_t *face)
490 {
491 return face->get_num_glyphs ();
492 }
493
494 /**
495 * hb_face_get_table_tags:
496 * @face: a face.
497 * @start_offset: index of first tag to return.
498 * @table_count: input length of @table_tags array, output number of items written.
499 * @table_tags: array to write tags into.
500 *
501 * Retrieves table tags for a face, if possible.
502 *
503 * Return value: total number of tables, or 0 if not possible to list.
504 *
505 * Since: 1.6.0
506 **/
507 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)508 hb_face_get_table_tags (const hb_face_t *face,
509 unsigned int start_offset,
510 unsigned int *table_count, /* IN/OUT */
511 hb_tag_t *table_tags /* OUT */)
512 {
513 if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
514 {
515 if (table_count)
516 *table_count = 0;
517 return 0;
518 }
519
520 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
521
522 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
523 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
524
525 return ot_face.get_table_tags (start_offset, table_count, table_tags);
526 }
527
528
529 /*
530 * Character set.
531 */
532
533
534 /**
535 * hb_face_collect_unicodes:
536 * @face: font face.
537 * @out: set to add Unicode characters covered by @face to.
538 *
539 * Since: 1.9.0
540 */
541 void
hb_face_collect_unicodes(hb_face_t * face,hb_set_t * out)542 hb_face_collect_unicodes (hb_face_t *face,
543 hb_set_t *out)
544 {
545 face->table.cmap->collect_unicodes (out);
546 }
547
548 /**
549 * hb_face_collect_variation_selectors:
550 * @face: font face.
551 * @out: set to add Variation Selector characters covered by @face to.
552 *
553 *
554 *
555 * Since: 1.9.0
556 */
557 void
hb_face_collect_variation_selectors(hb_face_t * face,hb_set_t * out)558 hb_face_collect_variation_selectors (hb_face_t *face,
559 hb_set_t *out)
560 {
561 face->table.cmap->collect_variation_selectors (out);
562 }
563
564 /**
565 * hb_face_collect_variation_unicodes:
566 * @face: font face.
567 * @out: set to add Unicode characters for @variation_selector covered by @face to.
568 *
569 *
570 *
571 * Since: 1.9.0
572 */
573 void
hb_face_collect_variation_unicodes(hb_face_t * face,hb_codepoint_t variation_selector,hb_set_t * out)574 hb_face_collect_variation_unicodes (hb_face_t *face,
575 hb_codepoint_t variation_selector,
576 hb_set_t *out)
577 {
578 face->table.cmap->collect_variation_unicodes (variation_selector, out);
579 }
580
581
582
583 /*
584 * face-builder: A face that has add_table().
585 */
586
587 struct hb_face_builder_data_t
588 {
589 struct table_entry_t
590 {
cmphb_face_builder_data_t::table_entry_t591 int cmp (hb_tag_t t) const
592 {
593 if (t < tag) return -1;
594 if (t > tag) return -1;
595 return 0;
596 }
597
598 hb_tag_t tag;
599 hb_blob_t *blob;
600 };
601
602 hb_vector_t<table_entry_t, 32> tables;
603 };
604
605 static hb_face_builder_data_t *
_hb_face_builder_data_create()606 _hb_face_builder_data_create ()
607 {
608 hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
609 if (unlikely (!data))
610 return nullptr;
611
612 data->tables.init ();
613
614 return data;
615 }
616
617 static void
_hb_face_builder_data_destroy(void * user_data)618 _hb_face_builder_data_destroy (void *user_data)
619 {
620 hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
621
622 for (unsigned int i = 0; i < data->tables.len; i++)
623 hb_blob_destroy (data->tables[i].blob);
624
625 data->tables.fini ();
626
627 free (data);
628 }
629
630 static hb_blob_t *
_hb_face_builder_data_reference_blob(hb_face_builder_data_t * data)631 _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
632 {
633
634 unsigned int table_count = data->tables.len;
635 unsigned int face_length = table_count * 16 + 12;
636
637 for (unsigned int i = 0; i < table_count; i++)
638 face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob));
639
640 char *buf = (char *) malloc (face_length);
641 if (unlikely (!buf))
642 return nullptr;
643
644 hb_serialize_context_t c (buf, face_length);
645 c.propagate_error (data->tables);
646 OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
647
648 bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
649 hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
650
651 bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ());
652
653 c.end_serialize ();
654
655 if (unlikely (!ret))
656 {
657 free (buf);
658 return nullptr;
659 }
660
661 return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
662 }
663
664 static hb_blob_t *
_hb_face_builder_reference_table(hb_face_t * face HB_UNUSED,hb_tag_t tag,void * user_data)665 _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
666 {
667 hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
668
669 if (!tag)
670 return _hb_face_builder_data_reference_blob (data);
671
672 hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
673 if (entry)
674 return hb_blob_reference (entry->blob);
675
676 return nullptr;
677 }
678
679
680 /**
681 * hb_face_builder_create:
682 *
683 * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
684 * After tables are added to the face, it can be compiled to a binary
685 * font file by calling hb_face_reference_blob().
686 *
687 * Return value: (transfer full): New face.
688 *
689 * Since: 1.9.0
690 **/
691 hb_face_t *
hb_face_builder_create()692 hb_face_builder_create ()
693 {
694 hb_face_builder_data_t *data = _hb_face_builder_data_create ();
695 if (unlikely (!data)) return hb_face_get_empty ();
696
697 return hb_face_create_for_tables (_hb_face_builder_reference_table,
698 data,
699 _hb_face_builder_data_destroy);
700 }
701
702 /**
703 * hb_face_builder_add_table:
704 *
705 * Add table for @tag with data provided by @blob to the face. @face must
706 * be created using hb_face_builder_create().
707 *
708 * Since: 1.9.0
709 **/
710 hb_bool_t
hb_face_builder_add_table(hb_face_t * face,hb_tag_t tag,hb_blob_t * blob)711 hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
712 {
713 if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
714 return false;
715
716 hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
717 hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
718
719 entry->tag = tag;
720 entry->blob = hb_blob_reference (blob);
721
722 return true;
723 }
724