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