922dee33404838e7b79ad58d069ffd4619a3f1cf
[platform/upstream/harfbuzz.git] / src / hb-font.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-private.hh"
30
31 #include "hb-ot-layout-private.hh"
32
33 #include "hb-font-private.hh"
34 #include "hb-blob.h"
35 #include "hb-open-file-private.hh"
36 #include "hb-ot-head-table.hh"
37
38 #include "hb-cache-private.hh"
39
40 #include <string.h>
41
42
43
44 /*
45  * hb_font_funcs_t
46  */
47
48 static hb_bool_t
49 hb_font_get_glyph_nil (hb_font_t *font,
50                        void *font_data HB_UNUSED,
51                        hb_codepoint_t unicode,
52                        hb_codepoint_t variation_selector,
53                        hb_codepoint_t *glyph,
54                        void *user_data HB_UNUSED)
55 {
56   if (font->parent)
57     return font->parent->get_glyph (unicode, variation_selector, glyph);
58
59   *glyph = 0;
60   return false;
61 }
62
63 static hb_position_t
64 hb_font_get_glyph_h_advance_nil (hb_font_t *font,
65                                  void *font_data HB_UNUSED,
66                                  hb_codepoint_t glyph,
67                                  void *user_data HB_UNUSED)
68 {
69   if (font->parent)
70     return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
71
72   return font->x_scale;
73 }
74
75 static hb_position_t
76 hb_font_get_glyph_v_advance_nil (hb_font_t *font,
77                                  void *font_data HB_UNUSED,
78                                  hb_codepoint_t glyph,
79                                  void *user_data HB_UNUSED)
80 {
81   if (font->parent)
82     return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
83
84   return font->y_scale;
85 }
86
87 static hb_bool_t
88 hb_font_get_glyph_h_origin_nil (hb_font_t *font,
89                                 void *font_data HB_UNUSED,
90                                 hb_codepoint_t glyph,
91                                 hb_position_t *x,
92                                 hb_position_t *y,
93                                 void *user_data HB_UNUSED)
94 {
95   if (font->parent) {
96     hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
97     if (ret)
98       font->parent_scale_position (x, y);
99     return ret;
100   }
101
102   *x = *y = 0;
103   return false;
104 }
105
106 static hb_bool_t
107 hb_font_get_glyph_v_origin_nil (hb_font_t *font,
108                                 void *font_data HB_UNUSED,
109                                 hb_codepoint_t glyph,
110                                 hb_position_t *x,
111                                 hb_position_t *y,
112                                 void *user_data HB_UNUSED)
113 {
114   if (font->parent) {
115     hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
116     if (ret)
117       font->parent_scale_position (x, y);
118     return ret;
119   }
120
121   *x = *y = 0;
122   return false;
123 }
124
125 static hb_position_t
126 hb_font_get_glyph_h_kerning_nil (hb_font_t *font,
127                                  void *font_data HB_UNUSED,
128                                  hb_codepoint_t left_glyph,
129                                  hb_codepoint_t right_glyph,
130                                  void *user_data HB_UNUSED)
131 {
132   if (font->parent)
133     return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
134
135   return 0;
136 }
137
138 static hb_position_t
139 hb_font_get_glyph_v_kerning_nil (hb_font_t *font,
140                                  void *font_data HB_UNUSED,
141                                  hb_codepoint_t top_glyph,
142                                  hb_codepoint_t bottom_glyph,
143                                  void *user_data HB_UNUSED)
144 {
145   if (font->parent)
146     return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
147
148   return 0;
149 }
150
151 static hb_bool_t
152 hb_font_get_glyph_extents_nil (hb_font_t *font,
153                                void *font_data HB_UNUSED,
154                                hb_codepoint_t glyph,
155                                hb_glyph_extents_t *extents,
156                                void *user_data HB_UNUSED)
157 {
158   if (font->parent) {
159     hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
160     if (ret) {
161       font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
162       font->parent_scale_distance (&extents->width, &extents->height);
163     }
164     return ret;
165   }
166
167   memset (extents, 0, sizeof (*extents));
168   return false;
169 }
170
171 static hb_bool_t
172 hb_font_get_glyph_contour_point_nil (hb_font_t *font,
173                                      void *font_data HB_UNUSED,
174                                      hb_codepoint_t glyph,
175                                      unsigned int point_index,
176                                      hb_position_t *x,
177                                      hb_position_t *y,
178                                      void *user_data HB_UNUSED)
179 {
180   if (font->parent) {
181     hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
182     if (ret)
183       font->parent_scale_position (x, y);
184     return ret;
185   }
186
187   *x = *y = 0;
188   return false;
189 }
190
191 static hb_bool_t
192 hb_font_get_glyph_name_nil (hb_font_t *font,
193                             void *font_data HB_UNUSED,
194                             hb_codepoint_t glyph,
195                             char *name, unsigned int size,
196                             void *user_data HB_UNUSED)
197 {
198   if (font->parent)
199     return font->parent->get_glyph_name (glyph, name, size);
200
201   if (size) *name = '\0';
202   return false;
203 }
204
205 static hb_bool_t
206 hb_font_get_glyph_from_name_nil (hb_font_t *font,
207                                  void *font_data HB_UNUSED,
208                                  const char *name, int len, /* -1 means nul-terminated */
209                                  hb_codepoint_t *glyph,
210                                  void *user_data HB_UNUSED)
211 {
212   if (font->parent)
213     return font->parent->get_glyph_from_name (name, len, glyph);
214
215   *glyph = 0;
216   return false;
217 }
218
219
220 static const hb_font_funcs_t _hb_font_funcs_nil = {
221   HB_OBJECT_HEADER_STATIC,
222
223   true, /* immutable */
224
225   {
226 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
227     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
228 #undef HB_FONT_FUNC_IMPLEMENT
229   }
230 };
231
232
233 hb_font_funcs_t *
234 hb_font_funcs_create (void)
235 {
236   hb_font_funcs_t *ffuncs;
237
238   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
239     return hb_font_funcs_get_empty ();
240
241   ffuncs->get = _hb_font_funcs_nil.get;
242
243   return ffuncs;
244 }
245
246 hb_font_funcs_t *
247 hb_font_funcs_get_empty (void)
248 {
249   return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil);
250 }
251
252 hb_font_funcs_t *
253 hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
254 {
255   return hb_object_reference (ffuncs);
256 }
257
258 void
259 hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
260 {
261   if (!hb_object_destroy (ffuncs)) return;
262
263 #define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
264   ffuncs->destroy.name (ffuncs->user_data.name);
265   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
266 #undef HB_FONT_FUNC_IMPLEMENT
267
268   free (ffuncs);
269 }
270
271 hb_bool_t
272 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
273                              hb_user_data_key_t *key,
274                              void *              data,
275                              hb_destroy_func_t   destroy,
276                              hb_bool_t           replace)
277 {
278   return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
279 }
280
281 void *
282 hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
283                              hb_user_data_key_t *key)
284 {
285   return hb_object_get_user_data (ffuncs, key);
286 }
287
288
289 void
290 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
291 {
292   if (hb_object_is_inert (ffuncs))
293     return;
294
295   ffuncs->immutable = true;
296 }
297
298 hb_bool_t
299 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
300 {
301   return ffuncs->immutable;
302 }
303
304
305 #define HB_FONT_FUNC_IMPLEMENT(name) \
306                                                                          \
307 void                                                                     \
308 hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
309                                  hb_font_get_##name##_func_t  func,      \
310                                  void                        *user_data, \
311                                  hb_destroy_func_t            destroy)   \
312 {                                                                        \
313   if (ffuncs->immutable) {                                               \
314     if (destroy)                                                         \
315       destroy (user_data);                                               \
316     return;                                                              \
317   }                                                                      \
318                                                                          \
319   if (ffuncs->destroy.name)                                              \
320     ffuncs->destroy.name (ffuncs->user_data.name);                       \
321                                                                          \
322   if (func) {                                                            \
323     ffuncs->get.name = func;                                             \
324     ffuncs->user_data.name = user_data;                                  \
325     ffuncs->destroy.name = destroy;                                      \
326   } else {                                                               \
327     ffuncs->get.name = hb_font_get_##name##_nil;                         \
328     ffuncs->user_data.name = NULL;                                       \
329     ffuncs->destroy.name = NULL;                                         \
330   }                                                                      \
331 }
332
333 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
334 #undef HB_FONT_FUNC_IMPLEMENT
335
336
337 /* Public getters */
338
339 hb_bool_t
340 hb_font_get_glyph (hb_font_t *font,
341                    hb_codepoint_t unicode, hb_codepoint_t variation_selector,
342                    hb_codepoint_t *glyph)
343 {
344   return font->get_glyph (unicode, variation_selector, glyph);
345 }
346
347 hb_position_t
348 hb_font_get_glyph_h_advance (hb_font_t *font,
349                              hb_codepoint_t glyph)
350 {
351   return font->get_glyph_h_advance (glyph);
352 }
353
354 hb_position_t
355 hb_font_get_glyph_v_advance (hb_font_t *font,
356                              hb_codepoint_t glyph)
357 {
358   return font->get_glyph_v_advance (glyph);
359 }
360
361 hb_bool_t
362 hb_font_get_glyph_h_origin (hb_font_t *font,
363                             hb_codepoint_t glyph,
364                             hb_position_t *x, hb_position_t *y)
365 {
366   return font->get_glyph_h_origin (glyph, x, y);
367 }
368
369 hb_bool_t
370 hb_font_get_glyph_v_origin (hb_font_t *font,
371                             hb_codepoint_t glyph,
372                             hb_position_t *x, hb_position_t *y)
373 {
374   return font->get_glyph_v_origin (glyph, x, y);
375 }
376
377 hb_position_t
378 hb_font_get_glyph_h_kerning (hb_font_t *font,
379                              hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
380 {
381   return font->get_glyph_h_kerning (left_glyph, right_glyph);
382 }
383
384 hb_position_t
385 hb_font_get_glyph_v_kerning (hb_font_t *font,
386                              hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
387 {
388   return font->get_glyph_v_kerning (left_glyph, right_glyph);
389 }
390
391 hb_bool_t
392 hb_font_get_glyph_extents (hb_font_t *font,
393                            hb_codepoint_t glyph,
394                            hb_glyph_extents_t *extents)
395 {
396   return font->get_glyph_extents (glyph, extents);
397 }
398
399 hb_bool_t
400 hb_font_get_glyph_contour_point (hb_font_t *font,
401                                  hb_codepoint_t glyph, unsigned int point_index,
402                                  hb_position_t *x, hb_position_t *y)
403 {
404   return font->get_glyph_contour_point (glyph, point_index, x, y);
405 }
406
407 hb_bool_t
408 hb_font_get_glyph_name (hb_font_t *font,
409                         hb_codepoint_t glyph,
410                         char *name, unsigned int size)
411 {
412   return font->get_glyph_name (glyph, name, size);
413 }
414
415 hb_bool_t
416 hb_font_get_glyph_from_name (hb_font_t *font,
417                              const char *name, int len, /* -1 means nul-terminated */
418                              hb_codepoint_t *glyph)
419 {
420   return font->get_glyph_from_name (name, len, glyph);
421 }
422
423
424 /* A bit higher-level, and with fallback */
425
426 void
427 hb_font_get_glyph_advance_for_direction (hb_font_t *font,
428                                          hb_codepoint_t glyph,
429                                          hb_direction_t direction,
430                                          hb_position_t *x, hb_position_t *y)
431 {
432   return font->get_glyph_advance_for_direction (glyph, direction, x, y);
433 }
434
435 void
436 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
437                                         hb_codepoint_t glyph,
438                                         hb_direction_t direction,
439                                         hb_position_t *x, hb_position_t *y)
440 {
441   return font->get_glyph_origin_for_direction (glyph, direction, x, y);
442 }
443
444 void
445 hb_font_add_glyph_origin_for_direction (hb_font_t *font,
446                                         hb_codepoint_t glyph,
447                                         hb_direction_t direction,
448                                         hb_position_t *x, hb_position_t *y)
449 {
450   return font->add_glyph_origin_for_direction (glyph, direction, x, y);
451 }
452
453 void
454 hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
455                                              hb_codepoint_t glyph,
456                                              hb_direction_t direction,
457                                              hb_position_t *x, hb_position_t *y)
458 {
459   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
460 }
461
462 void
463 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
464                                          hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
465                                          hb_direction_t direction,
466                                          hb_position_t *x, hb_position_t *y)
467 {
468   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
469 }
470
471 hb_bool_t
472 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
473                                       hb_codepoint_t glyph,
474                                       hb_direction_t direction,
475                                       hb_glyph_extents_t *extents)
476 {
477   return font->get_glyph_extents_for_origin (glyph, direction, extents);
478 }
479
480 hb_bool_t
481 hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
482                                             hb_codepoint_t glyph, unsigned int point_index,
483                                             hb_direction_t direction,
484                                             hb_position_t *x, hb_position_t *y)
485 {
486   return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
487 }
488
489 /* Generates gidDDD if glyph has no name. */
490 void
491 hb_font_glyph_to_string (hb_font_t *font,
492                          hb_codepoint_t glyph,
493                          char *s, unsigned int size)
494 {
495   font->glyph_to_string (glyph, s, size);
496 }
497
498 /* Parses gidDDD and uniUUUU strings automatically. */
499 hb_bool_t
500 hb_font_glyph_from_string (hb_font_t *font,
501                            const char *s, int len, /* -1 means nul-terminated */
502                            hb_codepoint_t *glyph)
503 {
504   return font->glyph_from_string (s, len, glyph);
505 }
506
507
508 /*
509  * hb_face_t
510  */
511
512 static const hb_face_t _hb_face_nil = {
513   HB_OBJECT_HEADER_STATIC,
514
515   true, /* immutable */
516
517   NULL, /* reference_table_func */
518   NULL, /* user_data */
519   NULL, /* destroy */
520
521   0,    /* index */
522   1000, /* upem */
523
524   {
525 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
526 #include "hb-shaper-list.hh"
527 #undef HB_SHAPER_IMPLEMENT
528   },
529
530   NULL, /* shape_plans */
531 };
532
533
534 hb_face_t *
535 hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
536                            void                      *user_data,
537                            hb_destroy_func_t          destroy)
538 {
539   hb_face_t *face;
540
541   if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
542     if (destroy)
543       destroy (user_data);
544     return hb_face_get_empty ();
545   }
546
547   face->reference_table_func = reference_table_func;
548   face->user_data = user_data;
549   face->destroy = destroy;
550
551   face->upem = 0;
552
553   return face;
554 }
555
556
557 typedef struct hb_face_for_data_closure_t {
558   hb_blob_t *blob;
559   unsigned int  index;
560 } hb_face_for_data_closure_t;
561
562 static hb_face_for_data_closure_t *
563 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
564 {
565   hb_face_for_data_closure_t *closure;
566
567   closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
568   if (unlikely (!closure))
569     return NULL;
570
571   closure->blob = blob;
572   closure->index = index;
573
574   return closure;
575 }
576
577 static void
578 _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
579 {
580   hb_blob_destroy (closure->blob);
581   free (closure);
582 }
583
584 static hb_blob_t *
585 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
586 {
587   hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
588
589   if (tag == HB_TAG_NONE)
590     return hb_blob_reference (data->blob);
591
592   const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
593   const OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
594
595   const OpenTypeTable &table = ot_face.get_table_by_tag (tag);
596
597   hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
598
599   return blob;
600 }
601
602 hb_face_t *
603 hb_face_create (hb_blob_t    *blob,
604                 unsigned int  index)
605 {
606   hb_face_t *face;
607
608   if (unlikely (!blob || !hb_blob_get_length (blob)))
609     return hb_face_get_empty ();
610
611   hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
612
613   if (unlikely (!closure))
614     return hb_face_get_empty ();
615
616   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
617                                     closure,
618                                     (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
619
620   hb_face_set_index (face, index);
621
622   return face;
623 }
624
625 hb_face_t *
626 hb_face_get_empty (void)
627 {
628   return const_cast<hb_face_t *> (&_hb_face_nil);
629 }
630
631
632 hb_face_t *
633 hb_face_reference (hb_face_t *face)
634 {
635   return hb_object_reference (face);
636 }
637
638 void
639 hb_face_destroy (hb_face_t *face)
640 {
641   if (!hb_object_destroy (face)) return;
642
643   for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
644   {
645     hb_face_t::plan_node_t *next = node->next;
646     hb_shape_plan_destroy (node->shape_plan);
647     free (node);
648     node = next;
649   }
650
651 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
652 #include "hb-shaper-list.hh"
653 #undef HB_SHAPER_IMPLEMENT
654
655   if (face->destroy)
656     face->destroy (face->user_data);
657
658   free (face);
659 }
660
661 hb_bool_t
662 hb_face_set_user_data (hb_face_t          *face,
663                        hb_user_data_key_t *key,
664                        void *              data,
665                        hb_destroy_func_t   destroy,
666                        hb_bool_t           replace)
667 {
668   return hb_object_set_user_data (face, key, data, destroy, replace);
669 }
670
671 void *
672 hb_face_get_user_data (hb_face_t          *face,
673                        hb_user_data_key_t *key)
674 {
675   return hb_object_get_user_data (face, key);
676 }
677
678 void
679 hb_face_make_immutable (hb_face_t *face)
680 {
681   if (hb_object_is_inert (face))
682     return;
683
684   face->immutable = true;
685 }
686
687 hb_bool_t
688 hb_face_is_immutable (hb_face_t *face)
689 {
690   return face->immutable;
691 }
692
693
694 hb_blob_t *
695 hb_face_reference_table (hb_face_t *face,
696                          hb_tag_t   tag)
697 {
698   return face->reference_table (tag);
699 }
700
701 hb_blob_t *
702 hb_face_reference_blob (hb_face_t *face)
703 {
704   return face->reference_table (HB_TAG_NONE);
705 }
706
707 void
708 hb_face_set_index (hb_face_t    *face,
709                    unsigned int  index)
710 {
711   if (hb_object_is_inert (face))
712     return;
713
714   face->index = index;
715 }
716
717 unsigned int
718 hb_face_get_index (hb_face_t    *face)
719 {
720   return face->index;
721 }
722
723 void
724 hb_face_set_upem (hb_face_t    *face,
725                   unsigned int  upem)
726 {
727   if (hb_object_is_inert (face))
728     return;
729
730   face->upem = upem;
731 }
732
733 unsigned int
734 hb_face_get_upem (hb_face_t *face)
735 {
736   return face->get_upem ();
737 }
738
739
740 void
741 hb_face_t::load_upem (void) const
742 {
743   hb_blob_t *head_blob = Sanitizer<head>::sanitize (reference_table (HB_OT_TAG_head));
744   const head *head_table = Sanitizer<head>::lock_instance (head_blob);
745   upem = head_table->get_upem ();
746   hb_blob_destroy (head_blob);
747 }
748
749
750 /*
751  * hb_font_t
752  */
753
754 hb_font_t *
755 hb_font_create (hb_face_t *face)
756 {
757   hb_font_t *font;
758
759   if (unlikely (!face))
760     face = hb_face_get_empty ();
761   if (unlikely (hb_object_is_inert (face)))
762     return hb_font_get_empty ();
763   if (!(font = hb_object_create<hb_font_t> ()))
764     return hb_font_get_empty ();
765
766   hb_face_make_immutable (face);
767   font->face = hb_face_reference (face);
768   font->klass = hb_font_funcs_get_empty ();
769
770   return font;
771 }
772
773 hb_font_t *
774 hb_font_create_sub_font (hb_font_t *parent)
775 {
776   if (unlikely (!parent))
777     return hb_font_get_empty ();
778
779   hb_font_t *font = hb_font_create (parent->face);
780
781   if (unlikely (hb_object_is_inert (font)))
782     return font;
783
784   hb_font_make_immutable (parent);
785   font->parent = hb_font_reference (parent);
786
787   font->x_scale = parent->x_scale;
788   font->y_scale = parent->y_scale;
789   font->x_ppem = parent->x_ppem;
790   font->y_ppem = parent->y_ppem;
791
792   return font;
793 }
794
795 hb_font_t *
796 hb_font_get_empty (void)
797 {
798   static const hb_font_t _hb_font_nil = {
799     HB_OBJECT_HEADER_STATIC,
800
801     true, /* immutable */
802
803     NULL, /* parent */
804     const_cast<hb_face_t *> (&_hb_face_nil),
805
806     0, /* x_scale */
807     0, /* y_scale */
808
809     0, /* x_ppem */
810     0, /* y_ppem */
811
812     const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
813     NULL, /* user_data */
814     NULL, /* destroy */
815
816     {
817 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
818 #include "hb-shaper-list.hh"
819 #undef HB_SHAPER_IMPLEMENT
820     }
821   };
822
823   return const_cast<hb_font_t *> (&_hb_font_nil);
824 }
825
826 hb_font_t *
827 hb_font_reference (hb_font_t *font)
828 {
829   return hb_object_reference (font);
830 }
831
832 void
833 hb_font_destroy (hb_font_t *font)
834 {
835   if (!hb_object_destroy (font)) return;
836
837 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
838 #include "hb-shaper-list.hh"
839 #undef HB_SHAPER_IMPLEMENT
840
841   if (font->destroy)
842     font->destroy (font->user_data);
843
844   hb_font_destroy (font->parent);
845   hb_face_destroy (font->face);
846   hb_font_funcs_destroy (font->klass);
847
848   free (font);
849 }
850
851 hb_bool_t
852 hb_font_set_user_data (hb_font_t          *font,
853                        hb_user_data_key_t *key,
854                        void *              data,
855                        hb_destroy_func_t   destroy,
856                        hb_bool_t           replace)
857 {
858   return hb_object_set_user_data (font, key, data, destroy, replace);
859 }
860
861 void *
862 hb_font_get_user_data (hb_font_t          *font,
863                        hb_user_data_key_t *key)
864 {
865   return hb_object_get_user_data (font, key);
866 }
867
868 void
869 hb_font_make_immutable (hb_font_t *font)
870 {
871   if (hb_object_is_inert (font))
872     return;
873
874   font->immutable = true;
875 }
876
877 hb_bool_t
878 hb_font_is_immutable (hb_font_t *font)
879 {
880   return font->immutable;
881 }
882
883 hb_font_t *
884 hb_font_get_parent (hb_font_t *font)
885 {
886   return font->parent;
887 }
888
889 hb_face_t *
890 hb_font_get_face (hb_font_t *font)
891 {
892   return font->face;
893 }
894
895
896 void
897 hb_font_set_funcs (hb_font_t         *font,
898                    hb_font_funcs_t   *klass,
899                    void              *user_data,
900                    hb_destroy_func_t  destroy)
901 {
902   if (font->immutable) {
903     if (destroy)
904       destroy (user_data);
905     return;
906   }
907
908   if (font->destroy)
909     font->destroy (font->user_data);
910
911   if (!klass)
912     klass = hb_font_funcs_get_empty ();
913
914   hb_font_funcs_reference (klass);
915   hb_font_funcs_destroy (font->klass);
916   font->klass = klass;
917   font->user_data = user_data;
918   font->destroy = destroy;
919 }
920
921 void
922 hb_font_set_funcs_data (hb_font_t         *font,
923                         void              *user_data,
924                         hb_destroy_func_t  destroy)
925 {
926   /* Destroy user_data? */
927   if (font->immutable) {
928     if (destroy)
929       destroy (user_data);
930     return;
931   }
932
933   if (font->destroy)
934     font->destroy (font->user_data);
935
936   font->user_data = user_data;
937   font->destroy = destroy;
938 }
939
940
941 void
942 hb_font_set_scale (hb_font_t *font,
943                    int x_scale,
944                    int y_scale)
945 {
946   if (font->immutable)
947     return;
948
949   font->x_scale = x_scale;
950   font->y_scale = y_scale;
951 }
952
953 void
954 hb_font_get_scale (hb_font_t *font,
955                    int *x_scale,
956                    int *y_scale)
957 {
958   if (x_scale) *x_scale = font->x_scale;
959   if (y_scale) *y_scale = font->y_scale;
960 }
961
962 void
963 hb_font_set_ppem (hb_font_t *font,
964                   unsigned int x_ppem,
965                   unsigned int y_ppem)
966 {
967   if (font->immutable)
968     return;
969
970   font->x_ppem = x_ppem;
971   font->y_ppem = y_ppem;
972 }
973
974 void
975 hb_font_get_ppem (hb_font_t *font,
976                   unsigned int *x_ppem,
977                   unsigned int *y_ppem)
978 {
979   if (x_ppem) *x_ppem = font->x_ppem;
980   if (y_ppem) *y_ppem = font->y_ppem;
981 }