Imported Upstream version 2.3.1
[platform/upstream/harfbuzz.git] / src / hb-face.cc
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
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 *
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 *
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
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 *
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 *
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 *
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 *
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
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
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 *
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
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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   {
591     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> tables;
603 };
604
605 static hb_face_builder_data_t *
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
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.length; 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 *
631 _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
632 {
633
634   unsigned int table_count = data->tables.length;
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 *
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 *
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
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 }