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