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: 0.9.2
  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 *) calloc (1, 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: 0.9.2
 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))
 169     blob = hb_blob_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: 0.9.2
 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: 0.9.2
 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: 0.9.2
 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: 0.9.2
 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: 0.9.2
 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: 0.9.2
 297  **/
 298 void
 299 hb_face_make_immutable (hb_face_t *face)
 300 {
 301   if (unlikely (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: 0.9.2
 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: 0.9.2
 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: 0.9.2
 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: 0.9.2
 366  **/
 367 void
 368 hb_face_set_index (hb_face_t    *face,
 369                    unsigned int  index)
 370 {
 371   if (face->immutable)
 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: 0.9.2
 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: 0.9.2
 401  **/
 402 void
 403 hb_face_set_upem (hb_face_t    *face,
 404                   unsigned int  upem)
 405 {
 406   if (face->immutable)
 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: 0.9.2
 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: 0.9.7
 445  **/
 446 void
 447 hb_face_set_glyph_count (hb_face_t    *face,
 448                          unsigned int  glyph_count)
 449 {
 450   if (face->immutable)
 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: 0.9.7
 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