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.hh"
  30 
  31 #include "hb-face.hh"
  32 #include "hb-blob.hh"
  33 #include "hb-open-file.hh"
  34 #include "hb-ot-face.hh"
  35 #include "hb-ot-cmap-table.hh"
  36 
  37 
  38 /**
  39  * SECTION:hb-face
  40  * @title: hb-face
  41  * @short_description: Font face objects
  42  * @include: hb.h
  43  *
  44  * Font face is objects represent a single face in a font family.
  45  * More exactly, a font face represents a single face in a binary font file.
  46  * Font faces are typically built from a binary blob and a face index.
  47  * Font faces are used to create fonts.
  48  **/
  49 
  50 
  51 /**
  52  * hb_face_count:
  53  * @blob: a blob.
  54  *
  55  * Get number of faces in a blob.
  56  *
  57  * Return value: Number of faces in @blob
  58  *
  59  * Since: 1.7.7
  60  **/
  61 unsigned int
  62 hb_face_count (hb_blob_t *blob)
  63 {
  64   if (unlikely (!blob))
  65     return 0;
  66 
  67   /* TODO We shouldn't be sanitizing blob.  Port to run sanitizer and return if not sane. */
  68   /* Make API signature const after. */
  69   hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
  70   const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
  71   unsigned int ret = ot.get_face_count ();
  72   hb_blob_destroy (sanitized);
  73 
  74   return ret;
  75 }
  76 
  77 /*
  78  * hb_face_t
  79  */
  80 
  81 DEFINE_NULL_INSTANCE (hb_face_t) =
  82 {
  83   HB_OBJECT_HEADER_STATIC,
  84 
  85   nullptr, /* reference_table_func */
  86   nullptr, /* user_data */
  87   nullptr, /* destroy */
  88 
  89   0,    /* index */
  90   HB_ATOMIC_INT_INIT (1000), /* upem */
  91   HB_ATOMIC_INT_INIT (0),    /* num_glyphs */
  92 
  93   /* Zero for the rest is fine. */
  94 };
  95 
  96 
  97 /**
  98  * hb_face_create_for_tables:
  99  * @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
 100  * @user_data:
 101  * @destroy:
 102  *
 103  *
 104  *
 105  * Return value: (transfer full)
 106  *
 107  * Since: 0.9.2
 108  **/
 109 hb_face_t *
 110 hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
 111                            void                      *user_data,
 112                            hb_destroy_func_t          destroy)
 113 {
 114   hb_face_t *face;
 115 
 116   if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
 117     if (destroy)
 118       destroy (user_data);
 119     return hb_face_get_empty ();
 120   }
 121 
 122   face->reference_table_func = reference_table_func;
 123   face->user_data = user_data;
 124   face->destroy = destroy;
 125 
 126   face->num_glyphs.set_relaxed (-1);
 127 
 128   face->data.init0 (face);
 129   face->table.init0 (face);
 130 
 131   return face;
 132 }
 133 
 134 
 135 typedef struct hb_face_for_data_closure_t {
 136   hb_blob_t *blob;
 137   unsigned int  index;
 138 } hb_face_for_data_closure_t;
 139 
 140 static hb_face_for_data_closure_t *
 141 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
 142 {
 143   hb_face_for_data_closure_t *closure;
 144 
 145   closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
 146   if (unlikely (!closure))
 147     return nullptr;
 148 
 149   closure->blob = blob;
 150   closure->index = index;
 151 
 152   return closure;
 153 }
 154 
 155 static void
 156 _hb_face_for_data_closure_destroy (void *data)
 157 {
 158   hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
 159 
 160   hb_blob_destroy (closure->blob);
 161   free (closure);
 162 }
 163 
 164 static hb_blob_t *
 165 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
 166 {
 167   hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
 168 
 169   if (tag == HB_TAG_NONE)
 170     return hb_blob_reference (data->blob);
 171 
 172   const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
 173   unsigned int base_offset;
 174   const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
 175 
 176   const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
 177 
 178   hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
 179 
 180   return blob;
 181 }
 182 
 183 /**
 184  * hb_face_create: (Xconstructor)
 185  * @blob:
 186  * @index:
 187  *
 188  *
 189  *
 190  * Return value: (transfer full):
 191  *
 192  * Since: 0.9.2
 193  **/
 194 hb_face_t *
 195 hb_face_create (hb_blob_t    *blob,
 196                 unsigned int  index)
 197 {
 198   hb_face_t *face;
 199 
 200   if (unlikely (!blob))
 201     blob = hb_blob_get_empty ();
 202 
 203   hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
 204 
 205   if (unlikely (!closure))
 206     return hb_face_get_empty ();
 207 
 208   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
 209                                     closure,
 210                                     _hb_face_for_data_closure_destroy);
 211 
 212   face->index = index;
 213 
 214   return face;
 215 }
 216 
 217 /**
 218  * hb_face_get_empty:
 219  *
 220  *
 221  *
 222  * Return value: (transfer full)
 223  *
 224  * Since: 0.9.2
 225  **/
 226 hb_face_t *
 227 hb_face_get_empty ()
 228 {
 229   return const_cast<hb_face_t *> (&Null(hb_face_t));
 230 }
 231 
 232 
 233 /**
 234  * hb_face_reference: (skip)
 235  * @face: a face.
 236  *
 237  *
 238  *
 239  * Return value:
 240  *
 241  * Since: 0.9.2
 242  **/
 243 hb_face_t *
 244 hb_face_reference (hb_face_t *face)
 245 {
 246   return hb_object_reference (face);
 247 }
 248 
 249 /**
 250  * hb_face_destroy: (skip)
 251  * @face: a face.
 252  *
 253  *
 254  *
 255  * Since: 0.9.2
 256  **/
 257 void
 258 hb_face_destroy (hb_face_t *face)
 259 {
 260   if (!hb_object_destroy (face)) return;
 261 
 262   for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
 263   {
 264     hb_face_t::plan_node_t *next = node->next;
 265     hb_shape_plan_destroy (node->shape_plan);
 266     free (node);
 267     node = next;
 268   }
 269 
 270   face->data.fini ();
 271   face->table.fini ();
 272 
 273   if (face->destroy)
 274     face->destroy (face->user_data);
 275 
 276   free (face);
 277 }
 278 
 279 /**
 280  * hb_face_set_user_data: (skip)
 281  * @face: a face.
 282  * @key:
 283  * @data:
 284  * @destroy:
 285  * @replace:
 286  *
 287  *
 288  *
 289  * Return value:
 290  *
 291  * Since: 0.9.2
 292  **/
 293 hb_bool_t
 294 hb_face_set_user_data (hb_face_t          *face,
 295                        hb_user_data_key_t *key,
 296                        void *              data,
 297                        hb_destroy_func_t   destroy,
 298                        hb_bool_t           replace)
 299 {
 300   return hb_object_set_user_data (face, key, data, destroy, replace);
 301 }
 302 
 303 /**
 304  * hb_face_get_user_data: (skip)
 305  * @face: a face.
 306  * @key:
 307  *
 308  *
 309  *
 310  * Return value: (transfer none):
 311  *
 312  * Since: 0.9.2
 313  **/
 314 void *
 315 hb_face_get_user_data (const hb_face_t    *face,
 316                        hb_user_data_key_t *key)
 317 {
 318   return hb_object_get_user_data (face, key);
 319 }
 320 
 321 /**
 322  * hb_face_make_immutable:
 323  * @face: a face.
 324  *
 325  *
 326  *
 327  * Since: 0.9.2
 328  **/
 329 void
 330 hb_face_make_immutable (hb_face_t *face)
 331 {
 332   if (hb_object_is_immutable (face))
 333     return;
 334 
 335   hb_object_make_immutable (face);
 336 }
 337 
 338 /**
 339  * hb_face_is_immutable:
 340  * @face: a face.
 341  *
 342  *
 343  *
 344  * Return value:
 345  *
 346  * Since: 0.9.2
 347  **/
 348 hb_bool_t
 349 hb_face_is_immutable (const hb_face_t *face)
 350 {
 351   return hb_object_is_immutable (face);
 352 }
 353 
 354 
 355 /**
 356  * hb_face_reference_table:
 357  * @face: a face.
 358  * @tag:
 359  *
 360  *
 361  *
 362  * Return value: (transfer full):
 363  *
 364  * Since: 0.9.2
 365  **/
 366 hb_blob_t *
 367 hb_face_reference_table (const hb_face_t *face,
 368                          hb_tag_t tag)
 369 {
 370   return face->reference_table (tag);
 371 }
 372 
 373 /**
 374  * hb_face_reference_blob:
 375  * @face: a face.
 376  *
 377  *
 378  *
 379  * Return value: (transfer full):
 380  *
 381  * Since: 0.9.2
 382  **/
 383 hb_blob_t *
 384 hb_face_reference_blob (hb_face_t *face)
 385 {
 386   return face->reference_table (HB_TAG_NONE);
 387 }
 388 
 389 /**
 390  * hb_face_set_index:
 391  * @face: a face.
 392  * @index:
 393  *
 394  *
 395  *
 396  * Since: 0.9.2
 397  **/
 398 void
 399 hb_face_set_index (hb_face_t    *face,
 400                    unsigned int  index)
 401 {
 402   if (hb_object_is_immutable (face))
 403     return;
 404 
 405   face->index = index;
 406 }
 407 
 408 /**
 409  * hb_face_get_index:
 410  * @face: a face.
 411  *
 412  *
 413  *
 414  * Return value:
 415  *
 416  * Since: 0.9.2
 417  **/
 418 unsigned int
 419 hb_face_get_index (const hb_face_t *face)
 420 {
 421   return face->index;
 422 }
 423 
 424 /**
 425  * hb_face_set_upem:
 426  * @face: a face.
 427  * @upem:
 428  *
 429  *
 430  *
 431  * Since: 0.9.2
 432  **/
 433 void
 434 hb_face_set_upem (hb_face_t    *face,
 435                   unsigned int  upem)
 436 {
 437   if (hb_object_is_immutable (face))
 438     return;
 439 
 440   face->upem.set_relaxed (upem);
 441 }
 442 
 443 /**
 444  * hb_face_get_upem:
 445  * @face: a face.
 446  *
 447  *
 448  *
 449  * Return value:
 450  *
 451  * Since: 0.9.2
 452  **/
 453 unsigned int
 454 hb_face_get_upem (const hb_face_t *face)
 455 {
 456   return face->get_upem ();
 457 }
 458 
 459 /**
 460  * hb_face_set_glyph_count:
 461  * @face: a face.
 462  * @glyph_count:
 463  *
 464  *
 465  *
 466  * Since: 0.9.7
 467  **/
 468 void
 469 hb_face_set_glyph_count (hb_face_t    *face,
 470                          unsigned int  glyph_count)
 471 {
 472   if (hb_object_is_immutable (face))
 473     return;
 474 
 475   face->num_glyphs.set_relaxed (glyph_count);
 476 }
 477 
 478 /**
 479  * hb_face_get_glyph_count:
 480  * @face: a face.
 481  *
 482  *
 483  *
 484  * Return value:
 485  *
 486  * Since: 0.9.7
 487  **/
 488 unsigned int
 489 hb_face_get_glyph_count (const hb_face_t *face)
 490 {
 491   return face->get_num_glyphs ();
 492 }
 493 
 494 /**
 495  * hb_face_get_table_tags:
 496  * @face: a face.
 497  * @start_offset: index of first tag to return.
 498  * @table_count: input length of @table_tags array, output number of items written.
 499  * @table_tags: array to write tags into.
 500  *
 501  * Retrieves table tags for a face, if possible.
 502  *
 503  * Return value: total number of tables, or 0 if not possible to list.
 504  *
 505  * Since: 1.6.0
 506  **/
 507 unsigned int
 508 hb_face_get_table_tags (const hb_face_t *face,
 509                         unsigned int  start_offset,
 510                         unsigned int *table_count, /* IN/OUT */
 511                         hb_tag_t     *table_tags /* OUT */)
 512 {
 513   if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
 514   {
 515     if (table_count)
 516       *table_count = 0;
 517     return 0;
 518   }
 519 
 520   hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
 521 
 522   const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
 523   const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
 524 
 525   return ot_face.get_table_tags (start_offset, table_count, table_tags);
 526 }
 527 
 528 
 529 /*
 530  * Character set.
 531  */
 532 
 533 
 534 /**
 535  * hb_face_collect_unicodes:
 536  * @face: font face.
 537  * @out: set to add Unicode characters covered by @face to.
 538  *
 539  * Since: 1.9.0
 540  */
 541 void
 542 hb_face_collect_unicodes (hb_face_t *face,
 543                           hb_set_t  *out)
 544 {
 545   face->table.cmap->collect_unicodes (out);
 546 }
 547 
 548 /**
 549  * hb_face_collect_variation_selectors:
 550  * @face: font face.
 551  * @out: set to add Variation Selector characters covered by @face to.
 552  *
 553  *
 554  *
 555  * Since: 1.9.0
 556  */
 557 void
 558 hb_face_collect_variation_selectors (hb_face_t *face,
 559                                      hb_set_t  *out)
 560 {
 561   face->table.cmap->collect_variation_selectors (out);
 562 }
 563 
 564 /**
 565  * hb_face_collect_variation_unicodes:
 566  * @face: font face.
 567  * @out: set to add Unicode characters for @variation_selector covered by @face to.
 568  *
 569  *
 570  *
 571  * Since: 1.9.0
 572  */
 573 void
 574 hb_face_collect_variation_unicodes (hb_face_t *face,
 575                                     hb_codepoint_t variation_selector,
 576                                     hb_set_t  *out)
 577 {
 578   face->table.cmap->collect_variation_unicodes (variation_selector, out);
 579 }
 580 
 581 
 582 
 583 /*
 584  * face-builder: A face that has add_table().
 585  */
 586 
 587 struct hb_face_builder_data_t
 588 {
 589   struct table_entry_t
 590   {
 591     int cmp (hb_tag_t t) const
 592     {
 593       if (t < tag) return -1;
 594       if (t > tag) return -1;
 595       return 0;
 596     }
 597 
 598     hb_tag_t   tag;
 599     hb_blob_t *blob;
 600   };
 601 
 602   hb_vector_t<table_entry_t> tables;
 603 };
 604 
 605 static hb_face_builder_data_t *
 606 _hb_face_builder_data_create ()
 607 {
 608   hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
 609   if (unlikely (!data))
 610     return nullptr;
 611 
 612   data->tables.init ();
 613 
 614   return data;
 615 }
 616 
 617 static void
 618 _hb_face_builder_data_destroy (void *user_data)
 619 {
 620   hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
 621 
 622   for (unsigned int i = 0; i < data->tables.length; i++)
 623     hb_blob_destroy (data->tables[i].blob);
 624 
 625   data->tables.fini ();
 626 
 627   free (data);
 628 }
 629 
 630 static hb_blob_t *
 631 _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
 632 {
 633 
 634   unsigned int table_count = data->tables.length;
 635   unsigned int face_length = table_count * 16 + 12;
 636 
 637   for (unsigned int i = 0; i < table_count; i++)
 638     face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob));
 639 
 640   char *buf = (char *) malloc (face_length);
 641   if (unlikely (!buf))
 642     return nullptr;
 643 
 644   hb_serialize_context_t c (buf, face_length);
 645   c.propagate_error (data->tables);
 646   OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
 647 
 648   bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
 649   hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
 650 
 651   bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ());
 652 
 653   c.end_serialize ();
 654 
 655   if (unlikely (!ret))
 656   {
 657     free (buf);
 658     return nullptr;
 659   }
 660 
 661   return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
 662 }
 663 
 664 static hb_blob_t *
 665 _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
 666 {
 667   hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
 668 
 669   if (!tag)
 670     return _hb_face_builder_data_reference_blob (data);
 671 
 672   hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
 673   if (entry)
 674     return hb_blob_reference (entry->blob);
 675 
 676   return nullptr;
 677 }
 678 
 679 
 680 /**
 681  * hb_face_builder_create:
 682  *
 683  * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
 684  * After tables are added to the face, it can be compiled to a binary
 685  * font file by calling hb_face_reference_blob().
 686  *
 687  * Return value: (transfer full): New face.
 688  *
 689  * Since: 1.9.0
 690  **/
 691 hb_face_t *
 692 hb_face_builder_create ()
 693 {
 694   hb_face_builder_data_t *data = _hb_face_builder_data_create ();
 695   if (unlikely (!data)) return hb_face_get_empty ();
 696 
 697   return hb_face_create_for_tables (_hb_face_builder_reference_table,
 698                                     data,
 699                                     _hb_face_builder_data_destroy);
 700 }
 701 
 702 /**
 703  * hb_face_builder_add_table:
 704  *
 705  * Add table for @tag with data provided by @blob to the face.  @face must
 706  * be created using hb_face_builder_create().
 707  *
 708  * Since: 1.9.0
 709  **/
 710 hb_bool_t
 711 hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
 712 {
 713   if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
 714     return false;
 715 
 716   hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
 717   hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
 718 
 719   entry->tag = tag;
 720   entry->blob = hb_blob_reference (blob);
 721 
 722   return true;
 723 }