Home | History | Annotate | Download | only in src
      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 }
   1009