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