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