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-open-file-private.hh"
     35 #include "hb-ot-head-table.hh"
     36 #include "hb-ot-maxp-table.hh"
     37 
     38 #include "hb-cache-private.hh"
     39 
     40 #include <string.h>
     41 
     42 
     43 /*
     44  * hb_face_t
     45  */
     46 
     47 const hb_face_t _hb_face_nil = {
     48   HB_OBJECT_HEADER_STATIC,
     49 
     50   true, /* immutable */
     51 
     52   NULL, /* reference_table_func */
     53   NULL, /* user_data */
     54   NULL, /* destroy */
     55 
     56   0,    /* index */
     57   1000, /* upem */
     58   0,    /* num_glyphs */
     59 
     60   {
     61 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
     62 #include "hb-shaper-list.hh"
     63 #undef HB_SHAPER_IMPLEMENT
     64   },
     65 
     66   NULL, /* shape_plans */
     67 };
     68 
     69 
     70 /**
     71  * hb_face_create_for_tables:
     72  * @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
     73  * @user_data:
     74  * @destroy:
     75  *
     76  *
     77  *
     78  * Return value: (transfer full)
     79  *
     80  * Since: 1.0
     81  **/
     82 hb_face_t *
     83 hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
     84 			   void                      *user_data,
     85 			   hb_destroy_func_t          destroy)
     86 {
     87   hb_face_t *face;
     88 
     89   if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
     90     if (destroy)
     91       destroy (user_data);
     92     return hb_face_get_empty ();
     93   }
     94 
     95   face->reference_table_func = reference_table_func;
     96   face->user_data = user_data;
     97   face->destroy = destroy;
     98 
     99   face->upem = 0;
    100   face->num_glyphs = (unsigned int) -1;
    101 
    102   return face;
    103 }
    104 
    105 
    106 typedef struct hb_face_for_data_closure_t {
    107   hb_blob_t *blob;
    108   unsigned int  index;
    109 } hb_face_for_data_closure_t;
    110 
    111 static hb_face_for_data_closure_t *
    112 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
    113 {
    114   hb_face_for_data_closure_t *closure;
    115 
    116   closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
    117   if (unlikely (!closure))
    118     return NULL;
    119 
    120   closure->blob = blob;
    121   closure->index = index;
    122 
    123   return closure;
    124 }
    125 
    126 static void
    127 _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
    128 {
    129   hb_blob_destroy (closure->blob);
    130   free (closure);
    131 }
    132 
    133 static hb_blob_t *
    134 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
    135 {
    136   hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
    137 
    138   if (tag == HB_TAG_NONE)
    139     return hb_blob_reference (data->blob);
    140 
    141   const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
    142   const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
    143 
    144   const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
    145 
    146   hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
    147 
    148   return blob;
    149 }
    150 
    151 /**
    152  * hb_face_create: (Xconstructor)
    153  * @blob:
    154  * @index:
    155  *
    156  *
    157  *
    158  * Return value: (transfer full):
    159  *
    160  * Since: 1.0
    161  **/
    162 hb_face_t *
    163 hb_face_create (hb_blob_t    *blob,
    164 		unsigned int  index)
    165 {
    166   hb_face_t *face;
    167 
    168   if (unlikely (!blob || !hb_blob_get_length (blob)))
    169     return hb_face_get_empty ();
    170 
    171   hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
    172 
    173   if (unlikely (!closure))
    174     return hb_face_get_empty ();
    175 
    176   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
    177 				    closure,
    178 				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
    179 
    180   hb_face_set_index (face, index);
    181 
    182   return face;
    183 }
    184 
    185 /**
    186  * hb_face_get_empty:
    187  *
    188  *
    189  *
    190  * Return value: (transfer full)
    191  *
    192  * Since: 1.0
    193  **/
    194 hb_face_t *
    195 hb_face_get_empty (void)
    196 {
    197   return const_cast<hb_face_t *> (&_hb_face_nil);
    198 }
    199 
    200 
    201 /**
    202  * hb_face_reference: (skip)
    203  * @face: a face.
    204  *
    205  *
    206  *
    207  * Return value:
    208  *
    209  * Since: 1.0
    210  **/
    211 hb_face_t *
    212 hb_face_reference (hb_face_t *face)
    213 {
    214   return hb_object_reference (face);
    215 }
    216 
    217 /**
    218  * hb_face_destroy: (skip)
    219  * @face: a face.
    220  *
    221  *
    222  *
    223  * Since: 1.0
    224  **/
    225 void
    226 hb_face_destroy (hb_face_t *face)
    227 {
    228   if (!hb_object_destroy (face)) return;
    229 
    230   for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
    231   {
    232     hb_face_t::plan_node_t *next = node->next;
    233     hb_shape_plan_destroy (node->shape_plan);
    234     free (node);
    235     node = next;
    236   }
    237 
    238 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
    239 #include "hb-shaper-list.hh"
    240 #undef HB_SHAPER_IMPLEMENT
    241 
    242   if (face->destroy)
    243     face->destroy (face->user_data);
    244 
    245   free (face);
    246 }
    247 
    248 /**
    249  * hb_face_set_user_data: (skip)
    250  * @face: a face.
    251  * @key:
    252  * @data:
    253  * @destroy:
    254  * @replace:
    255  *
    256  *
    257  *
    258  * Return value:
    259  *
    260  * Since: 1.0
    261  **/
    262 hb_bool_t
    263 hb_face_set_user_data (hb_face_t          *face,
    264 		       hb_user_data_key_t *key,
    265 		       void *              data,
    266 		       hb_destroy_func_t   destroy,
    267 		       hb_bool_t           replace)
    268 {
    269   return hb_object_set_user_data (face, key, data, destroy, replace);
    270 }
    271 
    272 /**
    273  * hb_face_get_user_data: (skip)
    274  * @face: a face.
    275  * @key:
    276  *
    277  *
    278  *
    279  * Return value: (transfer none):
    280  *
    281  * Since: 1.0
    282  **/
    283 void *
    284 hb_face_get_user_data (hb_face_t          *face,
    285 		       hb_user_data_key_t *key)
    286 {
    287   return hb_object_get_user_data (face, key);
    288 }
    289 
    290 /**
    291  * hb_face_make_immutable:
    292  * @face: a face.
    293  *
    294  *
    295  *
    296  * Since: 1.0
    297  **/
    298 void
    299 hb_face_make_immutable (hb_face_t *face)
    300 {
    301   if (hb_object_is_inert (face))
    302     return;
    303 
    304   face->immutable = true;
    305 }
    306 
    307 /**
    308  * hb_face_is_immutable:
    309  * @face: a face.
    310  *
    311  *
    312  *
    313  * Return value:
    314  *
    315  * Since: 1.0
    316  **/
    317 hb_bool_t
    318 hb_face_is_immutable (hb_face_t *face)
    319 {
    320   return face->immutable;
    321 }
    322 
    323 
    324 /**
    325  * hb_face_reference_table:
    326  * @face: a face.
    327  * @tag:
    328  *
    329  *
    330  *
    331  * Return value: (transfer full):
    332  *
    333  * Since: 1.0
    334  **/
    335 hb_blob_t *
    336 hb_face_reference_table (hb_face_t *face,
    337 			 hb_tag_t   tag)
    338 {
    339   return face->reference_table (tag);
    340 }
    341 
    342 /**
    343  * hb_face_reference_blob:
    344  * @face: a face.
    345  *
    346  *
    347  *
    348  * Return value: (transfer full):
    349  *
    350  * Since: 1.0
    351  **/
    352 hb_blob_t *
    353 hb_face_reference_blob (hb_face_t *face)
    354 {
    355   return face->reference_table (HB_TAG_NONE);
    356 }
    357 
    358 /**
    359  * hb_face_set_index:
    360  * @face: a face.
    361  * @index:
    362  *
    363  *
    364  *
    365  * Since: 1.0
    366  **/
    367 void
    368 hb_face_set_index (hb_face_t    *face,
    369 		   unsigned int  index)
    370 {
    371   if (hb_object_is_inert (face))
    372     return;
    373 
    374   face->index = index;
    375 }
    376 
    377 /**
    378  * hb_face_get_index:
    379  * @face: a face.
    380  *
    381  *
    382  *
    383  * Return value:
    384  *
    385  * Since: 1.0
    386  **/
    387 unsigned int
    388 hb_face_get_index (hb_face_t    *face)
    389 {
    390   return face->index;
    391 }
    392 
    393 /**
    394  * hb_face_set_upem:
    395  * @face: a face.
    396  * @upem:
    397  *
    398  *
    399  *
    400  * Since: 1.0
    401  **/
    402 void
    403 hb_face_set_upem (hb_face_t    *face,
    404 		  unsigned int  upem)
    405 {
    406   if (hb_object_is_inert (face))
    407     return;
    408 
    409   face->upem = upem;
    410 }
    411 
    412 /**
    413  * hb_face_get_upem:
    414  * @face: a face.
    415  *
    416  *
    417  *
    418  * Return value:
    419  *
    420  * Since: 1.0
    421  **/
    422 unsigned int
    423 hb_face_get_upem (hb_face_t *face)
    424 {
    425   return face->get_upem ();
    426 }
    427 
    428 void
    429 hb_face_t::load_upem (void) const
    430 {
    431   hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (reference_table (HB_OT_TAG_head));
    432   const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob);
    433   upem = head_table->get_upem ();
    434   hb_blob_destroy (head_blob);
    435 }
    436 
    437 /**
    438  * hb_face_set_glyph_count:
    439  * @face: a face.
    440  * @glyph_count:
    441  *
    442  *
    443  *
    444  * Since: 1.0
    445  **/
    446 void
    447 hb_face_set_glyph_count (hb_face_t    *face,
    448 			 unsigned int  glyph_count)
    449 {
    450   if (hb_object_is_inert (face))
    451     return;
    452 
    453   face->num_glyphs = glyph_count;
    454 }
    455 
    456 /**
    457  * hb_face_get_glyph_count:
    458  * @face: a face.
    459  *
    460  *
    461  *
    462  * Return value:
    463  *
    464  * Since: 1.0
    465  **/
    466 unsigned int
    467 hb_face_get_glyph_count (hb_face_t *face)
    468 {
    469   return face->get_num_glyphs ();
    470 }
    471 
    472 void
    473 hb_face_t::load_num_glyphs (void) const
    474 {
    475   hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp));
    476   const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
    477   num_glyphs = maxp_table->get_num_glyphs ();
    478   hb_blob_destroy (maxp_blob);
    479 }
    480 
    481 
    482