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