b59fdebaea782af48fefda154d4178be652aa076
[platform/upstream/harfbuzz.git] / src / hb-font.cc
1 /*
2  * Copyright © 2009  Red Hat, Inc.
3  * Copyright © 2012  Google, Inc.
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Red Hat Author(s): Behdad Esfahbod
26  * Google Author(s): Behdad Esfahbod
27  */
28
29 #include "hb-private.hh"
30
31 #include "hb-ot-layout-private.hh"
32
33 #include "hb-font-private.hh"
34 #include "hb-blob.h"
35 #include "hb-open-file-private.hh"
36 #include "hb-ot-head-table.hh"
37 #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
49 static hb_bool_t
50 hb_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
64 static hb_position_t
65 hb_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
76 static hb_position_t
77 hb_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
88 static hb_bool_t
89 hb_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
107 static hb_bool_t
108 hb_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
126 static hb_position_t
127 hb_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
139 static hb_position_t
140 hb_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
152 static hb_bool_t
153 hb_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
172 static hb_bool_t
173 hb_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
192 static hb_bool_t
193 hb_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
206 static hb_bool_t
207 hb_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
221 static 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
234 hb_font_funcs_t *
235 hb_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
247 hb_font_funcs_t *
248 hb_font_funcs_get_empty (void)
249 {
250   return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil);
251 }
252
253 hb_font_funcs_t *
254 hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
255 {
256   return hb_object_reference (ffuncs);
257 }
258
259 void
260 hb_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
272 hb_bool_t
273 hb_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
282 void *
283 hb_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
290 void
291 hb_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
299 hb_bool_t
300 hb_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                                                                          \
308 void                                                                     \
309 hb_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
334 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
335 #undef HB_FONT_FUNC_IMPLEMENT
336
337
338 /* Public getters */
339
340 hb_bool_t
341 hb_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
348 hb_position_t
349 hb_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
355 hb_position_t
356 hb_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
362 hb_bool_t
363 hb_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
370 hb_bool_t
371 hb_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
378 hb_position_t
379 hb_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
385 hb_position_t
386 hb_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
392 hb_bool_t
393 hb_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
400 hb_bool_t
401 hb_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
408 hb_bool_t
409 hb_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
416 hb_bool_t
417 hb_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
427 void
428 hb_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
436 void
437 hb_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
445 void
446 hb_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
454 void
455 hb_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
463 void
464 hb_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
472 hb_bool_t
473 hb_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
481 hb_bool_t
482 hb_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. */
491 void
492 hb_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. */
500 hb_bool_t
501 hb_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
513 static 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
536 hb_face_t *
537 hb_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
560 typedef struct hb_face_for_data_closure_t {
561   hb_blob_t *blob;
562   unsigned int  index;
563 } hb_face_for_data_closure_t;
564
565 static 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
580 static 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
587 static 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
605 hb_face_t *
606 hb_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
628 hb_face_t *
629 hb_face_get_empty (void)
630 {
631   return const_cast<hb_face_t *> (&_hb_face_nil);
632 }
633
634
635 hb_face_t *
636 hb_face_reference (hb_face_t *face)
637 {
638   return hb_object_reference (face);
639 }
640
641 void
642 hb_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
664 hb_bool_t
665 hb_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
674 void *
675 hb_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
681 void
682 hb_face_make_immutable (hb_face_t *face)
683 {
684   if (hb_object_is_inert (face))
685     return;
686
687   face->immutable = true;
688 }
689
690 hb_bool_t
691 hb_face_is_immutable (hb_face_t *face)
692 {
693   return face->immutable;
694 }
695
696
697 hb_blob_t *
698 hb_face_reference_table (hb_face_t *face,
699                          hb_tag_t   tag)
700 {
701   return face->reference_table (tag);
702 }
703
704 hb_blob_t *
705 hb_face_reference_blob (hb_face_t *face)
706 {
707   return face->reference_table (HB_TAG_NONE);
708 }
709
710 void
711 hb_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
720 unsigned int
721 hb_face_get_index (hb_face_t    *face)
722 {
723   return face->index;
724 }
725
726 void
727 hb_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
736 unsigned int
737 hb_face_get_upem (hb_face_t *face)
738 {
739   return face->get_upem ();
740 }
741
742 void
743 hb_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
751 void
752 hb_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
761 unsigned int
762 hb_face_get_glyph_count (hb_face_t *face)
763 {
764   return face->get_num_glyphs ();
765 }
766
767 void
768 hb_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
781 hb_font_t *
782 hb_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
800 hb_font_t *
801 hb_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
822 hb_font_t *
823 hb_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
853 hb_font_t *
854 hb_font_reference (hb_font_t *font)
855 {
856   return hb_object_reference (font);
857 }
858
859 void
860 hb_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
878 hb_bool_t
879 hb_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
888 void *
889 hb_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
895 void
896 hb_font_make_immutable (hb_font_t *font)
897 {
898   if (hb_object_is_inert (font))
899     return;
900
901   font->immutable = true;
902 }
903
904 hb_bool_t
905 hb_font_is_immutable (hb_font_t *font)
906 {
907   return font->immutable;
908 }
909
910 hb_font_t *
911 hb_font_get_parent (hb_font_t *font)
912 {
913   return font->parent;
914 }
915
916 hb_face_t *
917 hb_font_get_face (hb_font_t *font)
918 {
919   return font->face;
920 }
921
922
923 void
924 hb_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
948 void
949 hb_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
968 void
969 hb_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
980 void
981 hb_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
989 void
990 hb_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
1001 void
1002 hb_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 }