Upgrade to latest harfbuzz
[framework/uifw/harfbuzz.git] / src / hb-font.cc
1 /*
2  * Copyright © 2009  Red Hat, Inc.
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
6  * Permission is hereby granted, without written agreement and without
7  * license or royalty fees, to use, copy, modify, and distribute this
8  * software and its documentation for any purpose, provided that the
9  * above copyright notice and the following two paragraphs appear in
10  * all copies of this software.
11  *
12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16  * DAMAGE.
17  *
18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  *
24  * Red Hat Author(s): Behdad Esfahbod
25  */
26
27 #include "hb-private.hh"
28
29 #include "hb-ot-layout-private.hh"
30
31 #include "hb-font-private.hh"
32 #include "hb-blob.h"
33 #include "hb-open-file-private.hh"
34 #include "hb-ot-head-table.hh"
35
36 #include "hb-cache-private.hh"
37
38 #include <string.h>
39
40
41
42 /*
43  * hb_font_funcs_t
44  */
45
46 static hb_bool_t
47 hb_font_get_glyph_nil (hb_font_t *font,
48                        void *font_data HB_UNUSED,
49                        hb_codepoint_t unicode,
50                        hb_codepoint_t variation_selector,
51                        hb_codepoint_t *glyph,
52                        void *user_data HB_UNUSED)
53 {
54   if (font->parent)
55     return hb_font_get_glyph (font->parent, unicode, variation_selector, glyph);
56
57   *glyph = 0;
58   return false;
59 }
60
61 static hb_position_t
62 hb_font_get_glyph_h_advance_nil (hb_font_t *font,
63                                  void *font_data HB_UNUSED,
64                                  hb_codepoint_t glyph,
65                                  void *user_data HB_UNUSED)
66 {
67   if (font->parent)
68     return font->parent_scale_x_distance (hb_font_get_glyph_h_advance (font->parent, glyph));
69
70   return font->x_scale;
71 }
72
73 static hb_position_t
74 hb_font_get_glyph_v_advance_nil (hb_font_t *font,
75                                  void *font_data HB_UNUSED,
76                                  hb_codepoint_t glyph,
77                                  void *user_data HB_UNUSED)
78 {
79   if (font->parent)
80     return font->parent_scale_y_distance (hb_font_get_glyph_v_advance (font->parent, glyph));
81
82   return font->y_scale;
83 }
84
85 static hb_bool_t
86 hb_font_get_glyph_h_origin_nil (hb_font_t *font,
87                                 void *font_data HB_UNUSED,
88                                 hb_codepoint_t glyph,
89                                 hb_position_t *x,
90                                 hb_position_t *y,
91                                 void *user_data HB_UNUSED)
92 {
93   if (font->parent) {
94     hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent, glyph, x, y);
95     if (ret)
96       font->parent_scale_position (x, y);
97     return ret;
98   }
99
100   *x = *y = 0;
101   return false;
102 }
103
104 static hb_bool_t
105 hb_font_get_glyph_v_origin_nil (hb_font_t *font,
106                                 void *font_data HB_UNUSED,
107                                 hb_codepoint_t glyph,
108                                 hb_position_t *x,
109                                 hb_position_t *y,
110                                 void *user_data HB_UNUSED)
111 {
112   if (font->parent) {
113     hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent, glyph, x, y);
114     if (ret)
115       font->parent_scale_position (x, y);
116     return ret;
117   }
118
119   *x = *y = 0;
120   return false;
121 }
122
123 static hb_position_t
124 hb_font_get_glyph_h_kerning_nil (hb_font_t *font,
125                                  void *font_data HB_UNUSED,
126                                  hb_codepoint_t left_glyph,
127                                  hb_codepoint_t right_glyph,
128                                  void *user_data HB_UNUSED)
129 {
130   if (font->parent)
131     return font->parent_scale_x_distance (hb_font_get_glyph_h_kerning (font->parent, left_glyph, right_glyph));
132
133   return 0;
134 }
135
136 static hb_position_t
137 hb_font_get_glyph_v_kerning_nil (hb_font_t *font,
138                                  void *font_data HB_UNUSED,
139                                  hb_codepoint_t top_glyph,
140                                  hb_codepoint_t bottom_glyph,
141                                  void *user_data HB_UNUSED)
142 {
143   if (font->parent)
144     return font->parent_scale_y_distance (hb_font_get_glyph_v_kerning (font->parent, top_glyph, bottom_glyph));
145
146   return 0;
147 }
148
149 static hb_bool_t
150 hb_font_get_glyph_extents_nil (hb_font_t *font,
151                                void *font_data HB_UNUSED,
152                                hb_codepoint_t glyph,
153                                hb_glyph_extents_t *extents,
154                                void *user_data HB_UNUSED)
155 {
156   if (font->parent) {
157     hb_bool_t ret = hb_font_get_glyph_extents (font->parent,
158                                                glyph,
159                                                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 = hb_font_get_glyph_contour_point (font->parent, 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 hb_font_get_glyph_name (font->parent, glyph, name, size);
200
201   snprintf (name, size, "gid%u", glyph);
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 hb_font_get_glyph_from_name (font->parent, 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 hb_bool_t
338 hb_font_get_glyph (hb_font_t *font,
339                    hb_codepoint_t unicode, hb_codepoint_t variation_selector,
340                    hb_codepoint_t *glyph)
341 {
342   *glyph = 0;
343   return font->klass->get.glyph (font, font->user_data,
344                                  unicode, variation_selector, glyph,
345                                  font->klass->user_data.glyph);
346 }
347
348 hb_position_t
349 hb_font_get_glyph_h_advance (hb_font_t *font,
350                              hb_codepoint_t glyph)
351 {
352   return font->klass->get.glyph_h_advance (font, font->user_data,
353                                            glyph,
354                                            font->klass->user_data.glyph_h_advance);
355 }
356
357 hb_position_t
358 hb_font_get_glyph_v_advance (hb_font_t *font,
359                              hb_codepoint_t glyph)
360 {
361   return font->klass->get.glyph_v_advance (font, font->user_data,
362                                            glyph,
363                                            font->klass->user_data.glyph_v_advance);
364 }
365
366 hb_bool_t
367 hb_font_get_glyph_h_origin (hb_font_t *font,
368                             hb_codepoint_t glyph,
369                             hb_position_t *x, hb_position_t *y)
370 {
371   *x = *y = 0;
372   return font->klass->get.glyph_h_origin (font, font->user_data,
373                                            glyph, x, y,
374                                            font->klass->user_data.glyph_h_origin);
375 }
376
377 hb_bool_t
378 hb_font_get_glyph_v_origin (hb_font_t *font,
379                             hb_codepoint_t glyph,
380                             hb_position_t *x, hb_position_t *y)
381 {
382   *x = *y = 0;
383   return font->klass->get.glyph_v_origin (font, font->user_data,
384                                            glyph, x, y,
385                                            font->klass->user_data.glyph_v_origin);
386 }
387
388 hb_position_t
389 hb_font_get_glyph_h_kerning (hb_font_t *font,
390                              hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
391 {
392   return font->klass->get.glyph_h_kerning (font, font->user_data,
393                                            left_glyph, right_glyph,
394                                            font->klass->user_data.glyph_h_kerning);
395 }
396
397 hb_position_t
398 hb_font_get_glyph_v_kerning (hb_font_t *font,
399                              hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
400 {
401   return font->klass->get.glyph_v_kerning (font, font->user_data,
402                                      left_glyph, right_glyph,
403                                      font->klass->user_data.glyph_v_kerning);
404 }
405
406 hb_bool_t
407 hb_font_get_glyph_extents (hb_font_t *font,
408                            hb_codepoint_t glyph,
409                            hb_glyph_extents_t *extents)
410 {
411   memset (extents, 0, sizeof (*extents));
412   return font->klass->get.glyph_extents (font, font->user_data,
413                                          glyph,
414                                          extents,
415                                          font->klass->user_data.glyph_extents);
416 }
417
418 hb_bool_t
419 hb_font_get_glyph_contour_point (hb_font_t *font,
420                                  hb_codepoint_t glyph, unsigned int point_index,
421                                  hb_position_t *x, hb_position_t *y)
422 {
423   *x = *y = 0;
424   return font->klass->get.glyph_contour_point (font, font->user_data,
425                                                glyph, point_index,
426                                                x, y,
427                                                font->klass->user_data.glyph_contour_point);
428 }
429
430 hb_bool_t
431 hb_font_get_glyph_name (hb_font_t *font,
432                         hb_codepoint_t glyph,
433                         char *name, unsigned int size)
434 {
435   return font->klass->get.glyph_name (font, font->user_data,
436                                       glyph,
437                                       name, size,
438                                       font->klass->user_data.glyph_name);
439 }
440
441 hb_bool_t
442 hb_font_get_glyph_from_name (hb_font_t *font,
443                              const char *name, int len, /* -1 means nul-terminated */
444                              hb_codepoint_t *glyph)
445 {
446   return font->klass->get.glyph_from_name (font, font->user_data,
447                                            name, len,
448                                            glyph,
449                                            font->klass->user_data.glyph_from_name);
450 }
451
452
453 /* A bit higher-level, and with fallback */
454
455 void
456 hb_font_get_glyph_advance_for_direction (hb_font_t *font,
457                                          hb_codepoint_t glyph,
458                                          hb_direction_t direction,
459                                          hb_position_t *x, hb_position_t *y)
460 {
461   if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
462     *x = hb_font_get_glyph_h_advance (font, glyph);
463     *y = 0;
464   } else {
465     *x = 0;
466     *y = hb_font_get_glyph_v_advance (font, glyph);
467   }
468 }
469
470 static void
471 guess_v_origin_minus_h_origin (hb_font_t *font,
472                                hb_codepoint_t glyph,
473                                hb_position_t *x, hb_position_t *y)
474 {
475   *x = hb_font_get_glyph_h_advance (font, glyph) / 2;
476
477   /* TODO use font_metics.ascent */
478   *y = font->y_scale;
479 }
480
481
482 void
483 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
484                                         hb_codepoint_t glyph,
485                                         hb_direction_t direction,
486                                         hb_position_t *x, hb_position_t *y)
487 {
488   if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
489     hb_bool_t ret = hb_font_get_glyph_h_origin (font, glyph, x, y);
490     if (!ret && (ret = hb_font_get_glyph_v_origin (font, glyph, x, y))) {
491       hb_position_t dx, dy;
492       guess_v_origin_minus_h_origin (font, glyph, &dx, &dy);
493       *x -= dx; *y -= dy;
494     }
495   } else {
496     hb_bool_t ret = hb_font_get_glyph_v_origin (font, glyph, x, y);
497     if (!ret && (ret = hb_font_get_glyph_h_origin (font, glyph, x, y))) {
498       hb_position_t dx, dy;
499       guess_v_origin_minus_h_origin (font, glyph, &dx, &dy);
500       *x += dx; *y += dy;
501     }
502   }
503 }
504
505 void
506 hb_font_add_glyph_origin_for_direction (hb_font_t *font,
507                                         hb_codepoint_t glyph,
508                                         hb_direction_t direction,
509                                         hb_position_t *x, hb_position_t *y)
510 {
511   hb_position_t origin_x, origin_y;
512
513   hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y);
514
515   *x += origin_x;
516   *y += origin_y;
517 }
518
519 void
520 hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
521                                              hb_codepoint_t glyph,
522                                              hb_direction_t direction,
523                                              hb_position_t *x, hb_position_t *y)
524 {
525   hb_position_t origin_x, origin_y;
526
527   hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y);
528
529   *x -= origin_x;
530   *y -= origin_y;
531 }
532
533 void
534 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
535                                          hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
536                                          hb_direction_t direction,
537                                          hb_position_t *x, hb_position_t *y)
538 {
539   if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
540     *x = hb_font_get_glyph_h_kerning (font, first_glyph, second_glyph);
541     *y = 0;
542   } else {
543     *x = 0;
544     *y = hb_font_get_glyph_v_kerning (font, first_glyph, second_glyph);
545   }
546 }
547
548 hb_bool_t
549 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
550                                       hb_codepoint_t glyph,
551                                       hb_direction_t direction,
552                                       hb_glyph_extents_t *extents)
553 {
554   hb_bool_t ret = hb_font_get_glyph_extents (font, glyph, extents);
555
556   if (ret)
557     hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, &extents->x_bearing, &extents->y_bearing);
558
559   return ret;
560 }
561
562 hb_bool_t
563 hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
564                                             hb_codepoint_t glyph, unsigned int point_index,
565                                             hb_direction_t direction,
566                                             hb_position_t *x, hb_position_t *y)
567 {
568   hb_bool_t ret = hb_font_get_glyph_contour_point (font, glyph, point_index, x, y);
569
570   if (ret)
571     hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, x, y);
572
573   return ret;
574 }
575
576
577 /*
578  * hb_face_t
579  */
580
581 static const hb_face_t _hb_face_nil = {
582   HB_OBJECT_HEADER_STATIC,
583
584   true, /* immutable */
585
586   NULL, /* reference_table */
587   NULL, /* user_data */
588   NULL, /* destroy */
589
590   NULL, /* ot_layout */
591
592   0,    /* index */
593   1000  /* upem */
594 };
595
596
597 hb_face_t *
598 hb_face_create_for_tables (hb_reference_table_func_t  reference_table,
599                            void                      *user_data,
600                            hb_destroy_func_t          destroy)
601 {
602   hb_face_t *face;
603
604   if (!reference_table || !(face = hb_object_create<hb_face_t> ())) {
605     if (destroy)
606       destroy (user_data);
607     return hb_face_get_empty ();
608   }
609
610   face->reference_table = reference_table;
611   face->user_data = user_data;
612   face->destroy = destroy;
613
614   face->ot_layout = _hb_ot_layout_create (face);
615
616   face->upem = 0;
617
618   return face;
619 }
620
621
622 typedef struct _hb_face_for_data_closure_t {
623   hb_blob_t *blob;
624   unsigned int  index;
625 } hb_face_for_data_closure_t;
626
627 static hb_face_for_data_closure_t *
628 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
629 {
630   hb_face_for_data_closure_t *closure;
631
632   closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
633   if (unlikely (!closure))
634     return NULL;
635
636   closure->blob = blob;
637   closure->index = index;
638
639   return closure;
640 }
641
642 static void
643 _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
644 {
645   hb_blob_destroy (closure->blob);
646   free (closure);
647 }
648
649 static hb_blob_t *
650 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
651 {
652   hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
653
654   if (tag == HB_TAG_NONE)
655     return hb_blob_reference (data->blob);
656
657   const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
658   const OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
659
660   const OpenTypeTable &table = ot_face.get_table_by_tag (tag);
661
662   hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
663
664   return blob;
665 }
666
667 hb_face_t *
668 hb_face_create (hb_blob_t    *blob,
669                 unsigned int  index)
670 {
671   hb_face_t *face;
672
673   if (unlikely (!blob || !hb_blob_get_length (blob)))
674     return hb_face_get_empty ();
675
676   hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
677
678   if (unlikely (!closure))
679     return hb_face_get_empty ();
680
681   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
682                                     closure,
683                                     (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
684
685   hb_face_set_index (face, index);
686
687   return face;
688 }
689
690 hb_face_t *
691 hb_face_get_empty (void)
692 {
693   return const_cast<hb_face_t *> (&_hb_face_nil);
694 }
695
696
697 hb_face_t *
698 hb_face_reference (hb_face_t *face)
699 {
700   return hb_object_reference (face);
701 }
702
703 void
704 hb_face_destroy (hb_face_t *face)
705 {
706   if (!hb_object_destroy (face)) return;
707
708   _hb_ot_layout_destroy (face->ot_layout);
709
710   if (face->destroy)
711     face->destroy (face->user_data);
712
713   free (face);
714 }
715
716 hb_bool_t
717 hb_face_set_user_data (hb_face_t          *face,
718                        hb_user_data_key_t *key,
719                        void *              data,
720                        hb_destroy_func_t   destroy,
721                        hb_bool_t           replace)
722 {
723   return hb_object_set_user_data (face, key, data, destroy, replace);
724 }
725
726 void *
727 hb_face_get_user_data (hb_face_t          *face,
728                        hb_user_data_key_t *key)
729 {
730   return hb_object_get_user_data (face, key);
731 }
732
733 void
734 hb_face_make_immutable (hb_face_t *face)
735 {
736   if (hb_object_is_inert (face))
737     return;
738
739   face->immutable = true;
740 }
741
742 hb_bool_t
743 hb_face_is_immutable (hb_face_t *face)
744 {
745   return face->immutable;
746 }
747
748
749 hb_blob_t *
750 hb_face_reference_table (hb_face_t *face,
751                          hb_tag_t   tag)
752 {
753   hb_blob_t *blob;
754
755   if (unlikely (!face || !face->reference_table))
756     return hb_blob_get_empty ();
757
758   blob = face->reference_table (face, tag, face->user_data);
759   if (unlikely (!blob))
760     return hb_blob_get_empty ();
761
762   return blob;
763 }
764
765 hb_blob_t *
766 hb_face_reference_blob (hb_face_t *face)
767 {
768   return hb_face_reference_table (face, HB_TAG_NONE);
769 }
770
771 void
772 hb_face_set_index (hb_face_t    *face,
773                    unsigned int  index)
774 {
775   if (hb_object_is_inert (face))
776     return;
777
778   face->index = index;
779 }
780
781 unsigned int
782 hb_face_get_index (hb_face_t    *face)
783 {
784   return face->index;
785 }
786
787 void
788 hb_face_set_upem (hb_face_t    *face,
789                   unsigned int  upem)
790 {
791   if (hb_object_is_inert (face))
792     return;
793
794   face->upem = upem;
795 }
796
797 unsigned int
798 hb_face_get_upem (hb_face_t *face)
799 {
800   if (unlikely (!face->upem)) {
801     hb_blob_t *head_blob = Sanitizer<head>::sanitize (hb_face_reference_table (face, HB_OT_TAG_head));
802     const head *head_table = Sanitizer<head>::lock_instance (head_blob);
803     face->upem = head_table->get_upem ();
804     hb_blob_destroy (head_blob);
805   }
806   return face->upem;
807 }
808
809
810 /*
811  * hb_font_t
812  */
813
814 hb_font_t *
815 hb_font_create (hb_face_t *face)
816 {
817   hb_font_t *font;
818
819   if (unlikely (!face))
820     face = hb_face_get_empty ();
821   if (unlikely (hb_object_is_inert (face)))
822     return hb_font_get_empty ();
823   if (!(font = hb_object_create<hb_font_t> ()))
824     return hb_font_get_empty ();
825
826   hb_face_make_immutable (face);
827   font->face = hb_face_reference (face);
828   font->klass = hb_font_funcs_get_empty ();
829
830   return font;
831 }
832
833 hb_font_t *
834 hb_font_create_sub_font (hb_font_t *parent)
835 {
836   if (unlikely (!parent))
837     return hb_font_get_empty ();
838
839   hb_font_t *font = hb_font_create (parent->face);
840
841   if (unlikely (hb_object_is_inert (font)))
842     return font;
843
844   hb_font_make_immutable (parent);
845   font->parent = hb_font_reference (parent);
846
847   font->x_scale = parent->x_scale;
848   font->y_scale = parent->y_scale;
849   font->x_ppem = parent->x_ppem;
850   font->y_ppem = parent->y_ppem;
851
852   return font;
853 }
854
855 hb_font_t *
856 hb_font_get_empty (void)
857 {
858   static const hb_font_t _hb_font_nil = {
859     HB_OBJECT_HEADER_STATIC,
860
861     true, /* immutable */
862
863     NULL, /* parent */
864     const_cast<hb_face_t *> (&_hb_face_nil),
865
866     0, /* x_scale */
867     0, /* y_scale */
868
869     0, /* x_ppem */
870     0, /* y_ppem */
871
872     const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
873     NULL, /* user_data */
874     NULL  /* destroy */
875   };
876
877   return const_cast<hb_font_t *> (&_hb_font_nil);
878 }
879
880 hb_font_t *
881 hb_font_reference (hb_font_t *font)
882 {
883   return hb_object_reference (font);
884 }
885
886 void
887 hb_font_destroy (hb_font_t *font)
888 {
889   if (!hb_object_destroy (font)) return;
890
891   hb_font_destroy (font->parent);
892   hb_face_destroy (font->face);
893   hb_font_funcs_destroy (font->klass);
894   if (font->destroy)
895     font->destroy (font->user_data);
896
897   free (font);
898 }
899
900 hb_bool_t
901 hb_font_set_user_data (hb_font_t          *font,
902                        hb_user_data_key_t *key,
903                        void *              data,
904                        hb_destroy_func_t   destroy,
905                        hb_bool_t           replace)
906 {
907   return hb_object_set_user_data (font, key, data, destroy, replace);
908 }
909
910 void *
911 hb_font_get_user_data (hb_font_t          *font,
912                        hb_user_data_key_t *key)
913 {
914   return hb_object_get_user_data (font, key);
915 }
916
917 void
918 hb_font_make_immutable (hb_font_t *font)
919 {
920   if (hb_object_is_inert (font))
921     return;
922
923   font->immutable = true;
924 }
925
926 hb_bool_t
927 hb_font_is_immutable (hb_font_t *font)
928 {
929   return font->immutable;
930 }
931
932 hb_font_t *
933 hb_font_get_parent (hb_font_t *font)
934 {
935   return font->parent;
936 }
937
938 hb_face_t *
939 hb_font_get_face (hb_font_t *font)
940 {
941   return font->face;
942 }
943
944
945 void
946 hb_font_set_funcs (hb_font_t         *font,
947                    hb_font_funcs_t   *klass,
948                    void              *user_data,
949                    hb_destroy_func_t  destroy)
950 {
951   if (font->immutable) {
952     if (destroy)
953       destroy (user_data);
954     return;
955   }
956
957   if (font->destroy)
958     font->destroy (font->user_data);
959
960   if (!klass)
961     klass = hb_font_funcs_get_empty ();
962
963   hb_font_funcs_reference (klass);
964   hb_font_funcs_destroy (font->klass);
965   font->klass = klass;
966   font->user_data = user_data;
967   font->destroy = destroy;
968 }
969
970 void
971 hb_font_set_funcs_data (hb_font_t         *font,
972                         void              *user_data,
973                         hb_destroy_func_t  destroy)
974 {
975   /* Destroy user_data? */
976   if (font->immutable) {
977     if (destroy)
978       destroy (user_data);
979     return;
980   }
981
982   if (font->destroy)
983     font->destroy (font->user_data);
984
985   font->user_data = user_data;
986   font->destroy = destroy;
987 }
988
989
990 void
991 hb_font_set_scale (hb_font_t *font,
992                    int x_scale,
993                    int y_scale)
994 {
995   if (font->immutable)
996     return;
997
998   font->x_scale = x_scale;
999   font->y_scale = y_scale;
1000 }
1001
1002 void
1003 hb_font_get_scale (hb_font_t *font,
1004                    int *x_scale,
1005                    int *y_scale)
1006 {
1007   if (x_scale) *x_scale = font->x_scale;
1008   if (y_scale) *y_scale = font->y_scale;
1009 }
1010
1011 void
1012 hb_font_set_ppem (hb_font_t *font,
1013                   unsigned int x_ppem,
1014                   unsigned int y_ppem)
1015 {
1016   if (font->immutable)
1017     return;
1018
1019   font->x_ppem = x_ppem;
1020   font->y_ppem = y_ppem;
1021 }
1022
1023 void
1024 hb_font_get_ppem (hb_font_t *font,
1025                   unsigned int *x_ppem,
1026                   unsigned int *y_ppem)
1027 {
1028   if (x_ppem) *x_ppem = font->x_ppem;
1029   if (y_ppem) *y_ppem = font->y_ppem;
1030 }
1031
1032