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-open-file-private.hh"
35#include "hb-ot-head-table.hh"
36#include "hb-ot-maxp-table.hh"
37
38#include "hb-cache-private.hh"
39
40#include <string.h>
41
42
43/*
44 * hb_font_funcs_t
45 */
46
47static hb_bool_t
48hb_font_get_glyph_nil (hb_font_t *font,
49		       void *font_data HB_UNUSED,
50		       hb_codepoint_t unicode,
51		       hb_codepoint_t variation_selector,
52		       hb_codepoint_t *glyph,
53		       void *user_data HB_UNUSED)
54{
55  if (font->parent)
56    return font->parent->get_glyph (unicode, variation_selector, glyph);
57
58  *glyph = 0;
59  return false;
60}
61
62static hb_position_t
63hb_font_get_glyph_h_advance_nil (hb_font_t *font,
64				 void *font_data HB_UNUSED,
65				 hb_codepoint_t glyph,
66				 void *user_data HB_UNUSED)
67{
68  if (font->parent)
69    return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
70
71  return font->x_scale;
72}
73
74static hb_position_t
75hb_font_get_glyph_v_advance_nil (hb_font_t *font,
76				 void *font_data HB_UNUSED,
77				 hb_codepoint_t glyph,
78				 void *user_data HB_UNUSED)
79{
80  if (font->parent)
81    return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
82
83  return font->y_scale;
84}
85
86static hb_bool_t
87hb_font_get_glyph_h_origin_nil (hb_font_t *font,
88				void *font_data HB_UNUSED,
89				hb_codepoint_t glyph,
90				hb_position_t *x,
91				hb_position_t *y,
92				void *user_data HB_UNUSED)
93{
94  if (font->parent) {
95    hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
96    if (ret)
97      font->parent_scale_position (x, y);
98    return ret;
99  }
100
101  *x = *y = 0;
102  return false;
103}
104
105static hb_bool_t
106hb_font_get_glyph_v_origin_nil (hb_font_t *font,
107				void *font_data HB_UNUSED,
108				hb_codepoint_t glyph,
109				hb_position_t *x,
110				hb_position_t *y,
111				void *user_data HB_UNUSED)
112{
113  if (font->parent) {
114    hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
115    if (ret)
116      font->parent_scale_position (x, y);
117    return ret;
118  }
119
120  *x = *y = 0;
121  return false;
122}
123
124static hb_position_t
125hb_font_get_glyph_h_kerning_nil (hb_font_t *font,
126				 void *font_data HB_UNUSED,
127				 hb_codepoint_t left_glyph,
128				 hb_codepoint_t right_glyph,
129				 void *user_data HB_UNUSED)
130{
131  if (font->parent)
132    return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
133
134  return 0;
135}
136
137static hb_position_t
138hb_font_get_glyph_v_kerning_nil (hb_font_t *font,
139				 void *font_data HB_UNUSED,
140				 hb_codepoint_t top_glyph,
141				 hb_codepoint_t bottom_glyph,
142				 void *user_data HB_UNUSED)
143{
144  if (font->parent)
145    return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
146
147  return 0;
148}
149
150static hb_bool_t
151hb_font_get_glyph_extents_nil (hb_font_t *font,
152			       void *font_data HB_UNUSED,
153			       hb_codepoint_t glyph,
154			       hb_glyph_extents_t *extents,
155			       void *user_data HB_UNUSED)
156{
157  if (font->parent) {
158    hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
159    if (ret) {
160      font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
161      font->parent_scale_distance (&extents->width, &extents->height);
162    }
163    return ret;
164  }
165
166  memset (extents, 0, sizeof (*extents));
167  return false;
168}
169
170static hb_bool_t
171hb_font_get_glyph_contour_point_nil (hb_font_t *font,
172				     void *font_data HB_UNUSED,
173				     hb_codepoint_t glyph,
174				     unsigned int point_index,
175				     hb_position_t *x,
176				     hb_position_t *y,
177				     void *user_data HB_UNUSED)
178{
179  if (font->parent) {
180    hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
181    if (ret)
182      font->parent_scale_position (x, y);
183    return ret;
184  }
185
186  *x = *y = 0;
187  return false;
188}
189
190static hb_bool_t
191hb_font_get_glyph_name_nil (hb_font_t *font,
192			    void *font_data HB_UNUSED,
193			    hb_codepoint_t glyph,
194			    char *name, unsigned int size,
195			    void *user_data HB_UNUSED)
196{
197  if (font->parent)
198    return font->parent->get_glyph_name (glyph, name, size);
199
200  if (size) *name = '\0';
201  return false;
202}
203
204static hb_bool_t
205hb_font_get_glyph_from_name_nil (hb_font_t *font,
206				 void *font_data HB_UNUSED,
207				 const char *name, int len, /* -1 means nul-terminated */
208				 hb_codepoint_t *glyph,
209				 void *user_data HB_UNUSED)
210{
211  if (font->parent)
212    return font->parent->get_glyph_from_name (name, len, glyph);
213
214  *glyph = 0;
215  return false;
216}
217
218
219static const hb_font_funcs_t _hb_font_funcs_nil = {
220  HB_OBJECT_HEADER_STATIC,
221
222  true, /* immutable */
223
224  {
225#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
226    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
227#undef HB_FONT_FUNC_IMPLEMENT
228  }
229};
230
231
232/**
233 * hb_font_funcs_create: (Xconstructor)
234 *
235 *
236 *
237 * Return value: (transfer full):
238 *
239 * Since: 1.0
240 **/
241hb_font_funcs_t *
242hb_font_funcs_create (void)
243{
244  hb_font_funcs_t *ffuncs;
245
246  if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
247    return hb_font_funcs_get_empty ();
248
249  ffuncs->get = _hb_font_funcs_nil.get;
250
251  return ffuncs;
252}
253
254/**
255 * hb_font_funcs_get_empty:
256 *
257 *
258 *
259 * Return value: (transfer full):
260 *
261 * Since: 1.0
262 **/
263hb_font_funcs_t *
264hb_font_funcs_get_empty (void)
265{
266  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil);
267}
268
269/**
270 * hb_font_funcs_reference: (skip)
271 * @ffuncs: font functions.
272 *
273 *
274 *
275 * Return value:
276 *
277 * Since: 1.0
278 **/
279hb_font_funcs_t *
280hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
281{
282  return hb_object_reference (ffuncs);
283}
284
285/**
286 * hb_font_funcs_destroy: (skip)
287 * @ffuncs: font functions.
288 *
289 *
290 *
291 * Since: 1.0
292 **/
293void
294hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
295{
296  if (!hb_object_destroy (ffuncs)) return;
297
298#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
299  ffuncs->destroy.name (ffuncs->user_data.name);
300  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
301#undef HB_FONT_FUNC_IMPLEMENT
302
303  free (ffuncs);
304}
305
306/**
307 * hb_font_funcs_set_user_data: (skip)
308 * @ffuncs: font functions.
309 * @key:
310 * @data:
311 * @destroy:
312 * @replace:
313 *
314 *
315 *
316 * Return value:
317 *
318 * Since: 1.0
319 **/
320hb_bool_t
321hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
322			     hb_user_data_key_t *key,
323			     void *              data,
324			     hb_destroy_func_t   destroy,
325			     hb_bool_t           replace)
326{
327  return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
328}
329
330/**
331 * hb_font_funcs_get_user_data: (skip)
332 * @ffuncs: font functions.
333 * @key:
334 *
335 *
336 *
337 * Return value: (transfer none):
338 *
339 * Since: 1.0
340 **/
341void *
342hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
343			     hb_user_data_key_t *key)
344{
345  return hb_object_get_user_data (ffuncs, key);
346}
347
348
349/**
350 * hb_font_funcs_make_immutable:
351 * @ffuncs: font functions.
352 *
353 *
354 *
355 * Since: 1.0
356 **/
357void
358hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
359{
360  if (unlikely (hb_object_is_inert (ffuncs)))
361    return;
362
363  ffuncs->immutable = true;
364}
365
366/**
367 * hb_font_funcs_is_immutable:
368 * @ffuncs: font functions.
369 *
370 *
371 *
372 * Return value:
373 *
374 * Since: 1.0
375 **/
376hb_bool_t
377hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
378{
379  return ffuncs->immutable;
380}
381
382
383#define HB_FONT_FUNC_IMPLEMENT(name) \
384                                                                         \
385void                                                                     \
386hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
387                                 hb_font_get_##name##_func_t  func,      \
388                                 void                        *user_data, \
389                                 hb_destroy_func_t            destroy)   \
390{                                                                        \
391  if (ffuncs->immutable) {                                               \
392    if (destroy)                                                         \
393      destroy (user_data);                                               \
394    return;                                                              \
395  }                                                                      \
396                                                                         \
397  if (ffuncs->destroy.name)                                              \
398    ffuncs->destroy.name (ffuncs->user_data.name);                       \
399                                                                         \
400  if (func) {                                                            \
401    ffuncs->get.name = func;                                             \
402    ffuncs->user_data.name = user_data;                                  \
403    ffuncs->destroy.name = destroy;                                      \
404  } else {                                                               \
405    ffuncs->get.name = hb_font_get_##name##_nil;                         \
406    ffuncs->user_data.name = NULL;                                       \
407    ffuncs->destroy.name = NULL;                                         \
408  }                                                                      \
409}
410
411HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
412#undef HB_FONT_FUNC_IMPLEMENT
413
414
415/* Public getters */
416
417/**
418 * hb_font_get_glyph:
419 * @font: a font.
420 * @unicode:
421 * @variation_selector:
422 * @glyph: (out):
423 *
424 *
425 *
426 * Return value:
427 *
428 * Since: 1.0
429 **/
430hb_bool_t
431hb_font_get_glyph (hb_font_t *font,
432		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
433		   hb_codepoint_t *glyph)
434{
435  return font->get_glyph (unicode, variation_selector, glyph);
436}
437
438/**
439 * hb_font_get_glyph_h_advance:
440 * @font: a font.
441 * @glyph:
442 *
443 *
444 *
445 * Return value:
446 *
447 * Since: 1.0
448 **/
449hb_position_t
450hb_font_get_glyph_h_advance (hb_font_t *font,
451			     hb_codepoint_t glyph)
452{
453  return font->get_glyph_h_advance (glyph);
454}
455
456/**
457 * hb_font_get_glyph_v_advance:
458 * @font: a font.
459 * @glyph:
460 *
461 *
462 *
463 * Return value:
464 *
465 * Since: 1.0
466 **/
467hb_position_t
468hb_font_get_glyph_v_advance (hb_font_t *font,
469			     hb_codepoint_t glyph)
470{
471  return font->get_glyph_v_advance (glyph);
472}
473
474/**
475 * hb_font_get_glyph_h_origin:
476 * @font: a font.
477 * @glyph:
478 * @x: (out):
479 * @y: (out):
480 *
481 *
482 *
483 * Return value:
484 *
485 * Since: 1.0
486 **/
487hb_bool_t
488hb_font_get_glyph_h_origin (hb_font_t *font,
489			    hb_codepoint_t glyph,
490			    hb_position_t *x, hb_position_t *y)
491{
492  return font->get_glyph_h_origin (glyph, x, y);
493}
494
495/**
496 * hb_font_get_glyph_v_origin:
497 * @font: a font.
498 * @glyph:
499 * @x: (out):
500 * @y: (out):
501 *
502 *
503 *
504 * Return value:
505 *
506 * Since: 1.0
507 **/
508hb_bool_t
509hb_font_get_glyph_v_origin (hb_font_t *font,
510			    hb_codepoint_t glyph,
511			    hb_position_t *x, hb_position_t *y)
512{
513  return font->get_glyph_v_origin (glyph, x, y);
514}
515
516/**
517 * hb_font_get_glyph_h_kerning:
518 * @font: a font.
519 * @left_glyph:
520 * @right_glyph:
521 *
522 *
523 *
524 * Return value:
525 *
526 * Since: 1.0
527 **/
528hb_position_t
529hb_font_get_glyph_h_kerning (hb_font_t *font,
530			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
531{
532  return font->get_glyph_h_kerning (left_glyph, right_glyph);
533}
534
535/**
536 * hb_font_get_glyph_v_kerning:
537 * @font: a font.
538 * @top_glyph:
539 * @bottom_glyph:
540 *
541 *
542 *
543 * Return value:
544 *
545 * Since: 1.0
546 **/
547hb_position_t
548hb_font_get_glyph_v_kerning (hb_font_t *font,
549			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
550{
551  return font->get_glyph_v_kerning (top_glyph, bottom_glyph);
552}
553
554/**
555 * hb_font_get_glyph_extents:
556 * @font: a font.
557 * @glyph:
558 * @extents: (out):
559 *
560 *
561 *
562 * Return value:
563 *
564 * Since: 1.0
565 **/
566hb_bool_t
567hb_font_get_glyph_extents (hb_font_t *font,
568			   hb_codepoint_t glyph,
569			   hb_glyph_extents_t *extents)
570{
571  return font->get_glyph_extents (glyph, extents);
572}
573
574/**
575 * hb_font_get_glyph_contour_point:
576 * @font: a font.
577 * @glyph:
578 * @point_index:
579 * @x: (out):
580 * @y: (out):
581 *
582 *
583 *
584 * Return value:
585 *
586 * Since: 1.0
587 **/
588hb_bool_t
589hb_font_get_glyph_contour_point (hb_font_t *font,
590				 hb_codepoint_t glyph, unsigned int point_index,
591				 hb_position_t *x, hb_position_t *y)
592{
593  return font->get_glyph_contour_point (glyph, point_index, x, y);
594}
595
596/**
597 * hb_font_get_glyph_name:
598 * @font: a font.
599 * @glyph:
600 * @name: (array length=size):
601 * @size:
602 *
603 *
604 *
605 * Return value:
606 *
607 * Since: 1.0
608 **/
609hb_bool_t
610hb_font_get_glyph_name (hb_font_t *font,
611			hb_codepoint_t glyph,
612			char *name, unsigned int size)
613{
614  return font->get_glyph_name (glyph, name, size);
615}
616
617/**
618 * hb_font_get_glyph_from_name:
619 * @font: a font.
620 * @name: (array length=len):
621 * @len:
622 * @glyph: (out):
623 *
624 *
625 *
626 * Return value:
627 *
628 * Since: 1.0
629 **/
630hb_bool_t
631hb_font_get_glyph_from_name (hb_font_t *font,
632			     const char *name, int len, /* -1 means nul-terminated */
633			     hb_codepoint_t *glyph)
634{
635  return font->get_glyph_from_name (name, len, glyph);
636}
637
638
639/* A bit higher-level, and with fallback */
640
641/**
642 * hb_font_get_glyph_advance_for_direction:
643 * @font: a font.
644 * @glyph:
645 * @direction:
646 * @x: (out):
647 * @y: (out):
648 *
649 *
650 *
651 * Since: 1.0
652 **/
653void
654hb_font_get_glyph_advance_for_direction (hb_font_t *font,
655					 hb_codepoint_t glyph,
656					 hb_direction_t direction,
657					 hb_position_t *x, hb_position_t *y)
658{
659  return font->get_glyph_advance_for_direction (glyph, direction, x, y);
660}
661
662/**
663 * hb_font_get_glyph_origin_for_direction:
664 * @font: a font.
665 * @glyph:
666 * @direction:
667 * @x: (out):
668 * @y: (out):
669 *
670 *
671 *
672 * Since: 1.0
673 **/
674void
675hb_font_get_glyph_origin_for_direction (hb_font_t *font,
676					hb_codepoint_t glyph,
677					hb_direction_t direction,
678					hb_position_t *x, hb_position_t *y)
679{
680  return font->get_glyph_origin_for_direction (glyph, direction, x, y);
681}
682
683/**
684 * hb_font_add_glyph_origin_for_direction:
685 * @font: a font.
686 * @glyph:
687 * @direction:
688 * @x: (out):
689 * @y: (out):
690 *
691 *
692 *
693 * Since: 1.0
694 **/
695void
696hb_font_add_glyph_origin_for_direction (hb_font_t *font,
697					hb_codepoint_t glyph,
698					hb_direction_t direction,
699					hb_position_t *x, hb_position_t *y)
700{
701  return font->add_glyph_origin_for_direction (glyph, direction, x, y);
702}
703
704/**
705 * hb_font_subtract_glyph_origin_for_direction:
706 * @font: a font.
707 * @glyph:
708 * @direction:
709 * @x: (out):
710 * @y: (out):
711 *
712 *
713 *
714 * Since: 1.0
715 **/
716void
717hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
718					     hb_codepoint_t glyph,
719					     hb_direction_t direction,
720					     hb_position_t *x, hb_position_t *y)
721{
722  return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
723}
724
725/**
726 * hb_font_get_glyph_kerning_for_direction:
727 * @font: a font.
728 * @first_glyph:
729 * @second_glyph:
730 * @direction:
731 * @x: (out):
732 * @y: (out):
733 *
734 *
735 *
736 * Since: 1.0
737 **/
738void
739hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
740					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
741					 hb_direction_t direction,
742					 hb_position_t *x, hb_position_t *y)
743{
744  return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
745}
746
747/**
748 * hb_font_get_glyph_extents_for_origin:
749 * @font: a font.
750 * @glyph:
751 * @direction:
752 * @extents: (out):
753 *
754 *
755 *
756 * Return value:
757 *
758 * Since: 1.0
759 **/
760hb_bool_t
761hb_font_get_glyph_extents_for_origin (hb_font_t *font,
762				      hb_codepoint_t glyph,
763				      hb_direction_t direction,
764				      hb_glyph_extents_t *extents)
765{
766  return font->get_glyph_extents_for_origin (glyph, direction, extents);
767}
768
769/**
770 * hb_font_get_glyph_contour_point_for_origin:
771 * @font: a font.
772 * @glyph:
773 * @point_index:
774 * @direction:
775 * @x: (out):
776 * @y: (out):
777 *
778 *
779 *
780 * Return value:
781 *
782 * Since: 1.0
783 **/
784hb_bool_t
785hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
786					    hb_codepoint_t glyph, unsigned int point_index,
787					    hb_direction_t direction,
788					    hb_position_t *x, hb_position_t *y)
789{
790  return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
791}
792
793/* Generates gidDDD if glyph has no name. */
794/**
795 * hb_font_glyph_to_string:
796 * @font: a font.
797 * @glyph:
798 * @s: (array length=size):
799 * @size:
800 *
801 *
802 *
803 * Since: 1.0
804 **/
805void
806hb_font_glyph_to_string (hb_font_t *font,
807			 hb_codepoint_t glyph,
808			 char *s, unsigned int size)
809{
810  font->glyph_to_string (glyph, s, size);
811}
812
813/* Parses gidDDD and uniUUUU strings automatically. */
814/**
815 * hb_font_glyph_from_string:
816 * @font: a font.
817 * @s: (array length=len):
818 * @len:
819 * @glyph: (out):
820 *
821 *
822 *
823 * Return value:
824 *
825 * Since: 1.0
826 **/
827hb_bool_t
828hb_font_glyph_from_string (hb_font_t *font,
829			   const char *s, int len, /* -1 means nul-terminated */
830			   hb_codepoint_t *glyph)
831{
832  return font->glyph_from_string (s, len, glyph);
833}
834
835
836/*
837 * hb_font_t
838 */
839
840/**
841 * hb_font_create: (Xconstructor)
842 * @face: a face.
843 *
844 *
845 *
846 * Return value: (transfer full):
847 *
848 * Since: 1.0
849 **/
850hb_font_t *
851hb_font_create (hb_face_t *face)
852{
853  hb_font_t *font;
854
855  if (unlikely (!face))
856    face = hb_face_get_empty ();
857  if (unlikely (hb_object_is_inert (face)))
858    return hb_font_get_empty ();
859  if (!(font = hb_object_create<hb_font_t> ()))
860    return hb_font_get_empty ();
861
862  hb_face_make_immutable (face);
863  font->face = hb_face_reference (face);
864  font->klass = hb_font_funcs_get_empty ();
865
866  return font;
867}
868
869/**
870 * hb_font_create_sub_font:
871 * @parent: parent font.
872 *
873 *
874 *
875 * Return value: (transfer full):
876 *
877 * Since: 1.0
878 **/
879hb_font_t *
880hb_font_create_sub_font (hb_font_t *parent)
881{
882  if (unlikely (!parent))
883    return hb_font_get_empty ();
884
885  hb_font_t *font = hb_font_create (parent->face);
886
887  if (unlikely (hb_object_is_inert (font)))
888    return font;
889
890  hb_font_make_immutable (parent);
891  font->parent = hb_font_reference (parent);
892
893  font->x_scale = parent->x_scale;
894  font->y_scale = parent->y_scale;
895  font->x_ppem = parent->x_ppem;
896  font->y_ppem = parent->y_ppem;
897
898  return font;
899}
900
901/**
902 * hb_font_get_empty:
903 *
904 *
905 *
906 * Return value: (transfer full)
907 *
908 * Since: 1.0
909 **/
910hb_font_t *
911hb_font_get_empty (void)
912{
913  static const hb_font_t _hb_font_nil = {
914    HB_OBJECT_HEADER_STATIC,
915
916    true, /* immutable */
917
918    NULL, /* parent */
919    const_cast<hb_face_t *> (&_hb_face_nil),
920
921    0, /* x_scale */
922    0, /* y_scale */
923
924    0, /* x_ppem */
925    0, /* y_ppem */
926
927    const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
928    NULL, /* user_data */
929    NULL, /* destroy */
930
931    {
932#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
933#include "hb-shaper-list.hh"
934#undef HB_SHAPER_IMPLEMENT
935    }
936  };
937
938  return const_cast<hb_font_t *> (&_hb_font_nil);
939}
940
941/**
942 * hb_font_reference: (skip)
943 * @font: a font.
944 *
945 *
946 *
947 * Return value: (transfer full):
948 *
949 * Since: 1.0
950 **/
951hb_font_t *
952hb_font_reference (hb_font_t *font)
953{
954  return hb_object_reference (font);
955}
956
957/**
958 * hb_font_destroy: (skip)
959 * @font: a font.
960 *
961 *
962 *
963 * Since: 1.0
964 **/
965void
966hb_font_destroy (hb_font_t *font)
967{
968  if (!hb_object_destroy (font)) return;
969
970#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
971#include "hb-shaper-list.hh"
972#undef HB_SHAPER_IMPLEMENT
973
974  if (font->destroy)
975    font->destroy (font->user_data);
976
977  hb_font_destroy (font->parent);
978  hb_face_destroy (font->face);
979  hb_font_funcs_destroy (font->klass);
980
981  free (font);
982}
983
984/**
985 * hb_font_set_user_data: (skip)
986 * @font: a font.
987 * @key:
988 * @data:
989 * @destroy:
990 * @replace:
991 *
992 *
993 *
994 * Return value:
995 *
996 * Since: 1.0
997 **/
998hb_bool_t
999hb_font_set_user_data (hb_font_t          *font,
1000		       hb_user_data_key_t *key,
1001		       void *              data,
1002		       hb_destroy_func_t   destroy,
1003		       hb_bool_t           replace)
1004{
1005  return hb_object_set_user_data (font, key, data, destroy, replace);
1006}
1007
1008/**
1009 * hb_font_get_user_data: (skip)
1010 * @font: a font.
1011 * @key:
1012 *
1013 *
1014 *
1015 * Return value: (transfer none):
1016 *
1017 * Since: 1.0
1018 **/
1019void *
1020hb_font_get_user_data (hb_font_t          *font,
1021		       hb_user_data_key_t *key)
1022{
1023  return hb_object_get_user_data (font, key);
1024}
1025
1026/**
1027 * hb_font_make_immutable:
1028 * @font: a font.
1029 *
1030 *
1031 *
1032 * Since: 1.0
1033 **/
1034void
1035hb_font_make_immutable (hb_font_t *font)
1036{
1037  if (unlikely (hb_object_is_inert (font)))
1038    return;
1039
1040  font->immutable = true;
1041}
1042
1043/**
1044 * hb_font_is_immutable:
1045 * @font: a font.
1046 *
1047 *
1048 *
1049 * Return value:
1050 *
1051 * Since: 1.0
1052 **/
1053hb_bool_t
1054hb_font_is_immutable (hb_font_t *font)
1055{
1056  return font->immutable;
1057}
1058
1059/**
1060 * hb_font_get_parent:
1061 * @font: a font.
1062 *
1063 *
1064 *
1065 * Return value: (transfer none):
1066 *
1067 * Since: 1.0
1068 **/
1069hb_font_t *
1070hb_font_get_parent (hb_font_t *font)
1071{
1072  return font->parent;
1073}
1074
1075/**
1076 * hb_font_get_face:
1077 * @font: a font.
1078 *
1079 *
1080 *
1081 * Return value: (transfer none):
1082 *
1083 * Since: 1.0
1084 **/
1085hb_face_t *
1086hb_font_get_face (hb_font_t *font)
1087{
1088  return font->face;
1089}
1090
1091
1092/**
1093 * hb_font_set_funcs:
1094 * @font: a font.
1095 * @klass: (closure font_data) (destroy destroy) (scope notified):
1096 * @font_data:
1097 * @destroy:
1098 *
1099 *
1100 *
1101 * Since: 1.0
1102 **/
1103void
1104hb_font_set_funcs (hb_font_t         *font,
1105		   hb_font_funcs_t   *klass,
1106		   void              *font_data,
1107		   hb_destroy_func_t  destroy)
1108{
1109  if (font->immutable) {
1110    if (destroy)
1111      destroy (font_data);
1112    return;
1113  }
1114
1115  if (font->destroy)
1116    font->destroy (font->user_data);
1117
1118  if (!klass)
1119    klass = hb_font_funcs_get_empty ();
1120
1121  hb_font_funcs_reference (klass);
1122  hb_font_funcs_destroy (font->klass);
1123  font->klass = klass;
1124  font->user_data = font_data;
1125  font->destroy = destroy;
1126}
1127
1128/**
1129 * hb_font_set_funcs_data:
1130 * @font: a font.
1131 * @font_data: (destroy destroy) (scope notified):
1132 * @destroy:
1133 *
1134 *
1135 *
1136 * Since: 1.0
1137 **/
1138void
1139hb_font_set_funcs_data (hb_font_t         *font,
1140		        void              *font_data,
1141		        hb_destroy_func_t  destroy)
1142{
1143  /* Destroy user_data? */
1144  if (font->immutable) {
1145    if (destroy)
1146      destroy (font_data);
1147    return;
1148  }
1149
1150  if (font->destroy)
1151    font->destroy (font->user_data);
1152
1153  font->user_data = font_data;
1154  font->destroy = destroy;
1155}
1156
1157
1158/**
1159 * hb_font_set_scale:
1160 * @font: a font.
1161 * @x_scale:
1162 * @y_scale:
1163 *
1164 *
1165 *
1166 * Since: 1.0
1167 **/
1168void
1169hb_font_set_scale (hb_font_t *font,
1170		   int x_scale,
1171		   int y_scale)
1172{
1173  if (font->immutable)
1174    return;
1175
1176  font->x_scale = x_scale;
1177  font->y_scale = y_scale;
1178}
1179
1180/**
1181 * hb_font_get_scale:
1182 * @font: a font.
1183 * @x_scale: (out):
1184 * @y_scale: (out):
1185 *
1186 *
1187 *
1188 * Since: 1.0
1189 **/
1190void
1191hb_font_get_scale (hb_font_t *font,
1192		   int *x_scale,
1193		   int *y_scale)
1194{
1195  if (x_scale) *x_scale = font->x_scale;
1196  if (y_scale) *y_scale = font->y_scale;
1197}
1198
1199/**
1200 * hb_font_set_ppem:
1201 * @font: a font.
1202 * @x_ppem:
1203 * @y_ppem:
1204 *
1205 *
1206 *
1207 * Since: 1.0
1208 **/
1209void
1210hb_font_set_ppem (hb_font_t *font,
1211		  unsigned int x_ppem,
1212		  unsigned int y_ppem)
1213{
1214  if (font->immutable)
1215    return;
1216
1217  font->x_ppem = x_ppem;
1218  font->y_ppem = y_ppem;
1219}
1220
1221/**
1222 * hb_font_get_ppem:
1223 * @font: a font.
1224 * @x_ppem: (out):
1225 * @y_ppem: (out):
1226 *
1227 *
1228 *
1229 * Since: 1.0
1230 **/
1231void
1232hb_font_get_ppem (hb_font_t *font,
1233		  unsigned int *x_ppem,
1234		  unsigned int *y_ppem)
1235{
1236  if (x_ppem) *x_ppem = font->x_ppem;
1237  if (y_ppem) *y_ppem = font->y_ppem;
1238}
1239