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_font_funcs_t
  45  */
  46 
  47 static hb_bool_t
  48 hb_font_get_glyph_nil (hb_font_t *font,
  49                        void *font_data HB_UNUSED,
  50                        hb_codepoint_t unicode,
  51                        hb_codepoint_t variation_selector,
  52                        hb_codepoint_t *glyph,
  53                        void *user_data HB_UNUSED)
  54 {
  55   if (font->parent)
  56     return font->parent->get_glyph (unicode, variation_selector, glyph);
  57 
  58   *glyph = 0;
  59   return false;
  60 }
  61 
  62 static hb_position_t
  63 hb_font_get_glyph_h_advance_nil (hb_font_t *font,
  64                                  void *font_data HB_UNUSED,
  65                                  hb_codepoint_t glyph,
  66                                  void *user_data HB_UNUSED)
  67 {
  68   if (font->parent)
  69     return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
  70 
  71   return font->x_scale;
  72 }
  73 
  74 static hb_position_t
  75 hb_font_get_glyph_v_advance_nil (hb_font_t *font,
  76                                  void *font_data HB_UNUSED,
  77                                  hb_codepoint_t glyph,
  78                                  void *user_data HB_UNUSED)
  79 {
  80   if (font->parent)
  81     return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
  82 
  83   return font->y_scale;
  84 }
  85 
  86 static hb_bool_t
  87 hb_font_get_glyph_h_origin_nil (hb_font_t *font,
  88                                 void *font_data HB_UNUSED,
  89                                 hb_codepoint_t glyph,
  90                                 hb_position_t *x,
  91                                 hb_position_t *y,
  92                                 void *user_data HB_UNUSED)
  93 {
  94   if (font->parent) {
  95     hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
  96     if (ret)
  97       font->parent_scale_position (x, y);
  98     return ret;
  99   }
 100 
 101   *x = *y = 0;
 102   return false;
 103 }
 104 
 105 static hb_bool_t
 106 hb_font_get_glyph_v_origin_nil (hb_font_t *font,
 107                                 void *font_data HB_UNUSED,
 108                                 hb_codepoint_t glyph,
 109                                 hb_position_t *x,
 110                                 hb_position_t *y,
 111                                 void *user_data HB_UNUSED)
 112 {
 113   if (font->parent) {
 114     hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
 115     if (ret)
 116       font->parent_scale_position (x, y);
 117     return ret;
 118   }
 119 
 120   *x = *y = 0;
 121   return false;
 122 }
 123 
 124 static hb_position_t
 125 hb_font_get_glyph_h_kerning_nil (hb_font_t *font,
 126                                  void *font_data HB_UNUSED,
 127                                  hb_codepoint_t left_glyph,
 128                                  hb_codepoint_t right_glyph,
 129                                  void *user_data HB_UNUSED)
 130 {
 131   if (font->parent)
 132     return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
 133 
 134   return 0;
 135 }
 136 
 137 static hb_position_t
 138 hb_font_get_glyph_v_kerning_nil (hb_font_t *font,
 139                                  void *font_data HB_UNUSED,
 140                                  hb_codepoint_t top_glyph,
 141                                  hb_codepoint_t bottom_glyph,
 142                                  void *user_data HB_UNUSED)
 143 {
 144   if (font->parent)
 145     return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
 146 
 147   return 0;
 148 }
 149 
 150 static hb_bool_t
 151 hb_font_get_glyph_extents_nil (hb_font_t *font,
 152                                void *font_data HB_UNUSED,
 153                                hb_codepoint_t glyph,
 154                                hb_glyph_extents_t *extents,
 155                                void *user_data HB_UNUSED)
 156 {
 157   if (font->parent) {
 158     hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
 159     if (ret) {
 160       font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
 161       font->parent_scale_distance (&extents->width, &extents->height);
 162     }
 163     return ret;
 164   }
 165 
 166   memset (extents, 0, sizeof (*extents));
 167   return false;
 168 }
 169 
 170 static hb_bool_t
 171 hb_font_get_glyph_contour_point_nil (hb_font_t *font,
 172                                      void *font_data HB_UNUSED,
 173                                      hb_codepoint_t glyph,
 174                                      unsigned int point_index,
 175                                      hb_position_t *x,
 176                                      hb_position_t *y,
 177                                      void *user_data HB_UNUSED)
 178 {
 179   if (font->parent) {
 180     hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
 181     if (ret)
 182       font->parent_scale_position (x, y);
 183     return ret;
 184   }
 185 
 186   *x = *y = 0;
 187   return false;
 188 }
 189 
 190 static hb_bool_t
 191 hb_font_get_glyph_name_nil (hb_font_t *font,
 192                             void *font_data HB_UNUSED,
 193                             hb_codepoint_t glyph,
 194                             char *name, unsigned int size,
 195                             void *user_data HB_UNUSED)
 196 {
 197   if (font->parent)
 198     return font->parent->get_glyph_name (glyph, name, size);
 199 
 200   if (size) *name = '\0';
 201   return false;
 202 }
 203 
 204 static hb_bool_t
 205 hb_font_get_glyph_from_name_nil (hb_font_t *font,
 206                                  void *font_data HB_UNUSED,
 207                                  const char *name, int len, /* -1 means nul-terminated */
 208                                  hb_codepoint_t *glyph,
 209                                  void *user_data HB_UNUSED)
 210 {
 211   if (font->parent)
 212     return font->parent->get_glyph_from_name (name, len, glyph);
 213 
 214   *glyph = 0;
 215   return false;
 216 }
 217 
 218 
 219 static const hb_font_funcs_t _hb_font_funcs_nil = {
 220   HB_OBJECT_HEADER_STATIC,
 221 
 222   true, /* immutable */
 223 
 224   {
 225 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
 226     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 227 #undef HB_FONT_FUNC_IMPLEMENT
 228   }
 229 };
 230 
 231 
 232 /**
 233  * hb_font_funcs_create: (Xconstructor)
 234  *
 235  *
 236  *
 237  * Return value: (transfer full):
 238  *
 239  * Since: 0.9.2
 240  **/
 241 hb_font_funcs_t *
 242 hb_font_funcs_create (void)
 243 {
 244   hb_font_funcs_t *ffuncs;
 245 
 246   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
 247     return hb_font_funcs_get_empty ();
 248 
 249   ffuncs->get = _hb_font_funcs_nil.get;
 250 
 251   return ffuncs;
 252 }
 253 
 254 /**
 255  * hb_font_funcs_get_empty:
 256  *
 257  *
 258  *
 259  * Return value: (transfer full):
 260  *
 261  * Since: 0.9.2
 262  **/
 263 hb_font_funcs_t *
 264 hb_font_funcs_get_empty (void)
 265 {
 266   return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil);
 267 }
 268 
 269 /**
 270  * hb_font_funcs_reference: (skip)
 271  * @ffuncs: font functions.
 272  *
 273  *
 274  *
 275  * Return value:
 276  *
 277  * Since: 0.9.2
 278  **/
 279 hb_font_funcs_t *
 280 hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
 281 {
 282   return hb_object_reference (ffuncs);
 283 }
 284 
 285 /**
 286  * hb_font_funcs_destroy: (skip)
 287  * @ffuncs: font functions.
 288  *
 289  *
 290  *
 291  * Since: 0.9.2
 292  **/
 293 void
 294 hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
 295 {
 296   if (!hb_object_destroy (ffuncs)) return;
 297 
 298 #define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
 299   ffuncs->destroy.name (ffuncs->user_data.name);
 300   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 301 #undef HB_FONT_FUNC_IMPLEMENT
 302 
 303   free (ffuncs);
 304 }
 305 
 306 /**
 307  * hb_font_funcs_set_user_data: (skip)
 308  * @ffuncs: font functions.
 309  * @key:
 310  * @data:
 311  * @destroy:
 312  * @replace:
 313  *
 314  *
 315  *
 316  * Return value:
 317  *
 318  * Since: 0.9.2
 319  **/
 320 hb_bool_t
 321 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
 322                              hb_user_data_key_t *key,
 323                              void *              data,
 324                              hb_destroy_func_t   destroy,
 325                              hb_bool_t           replace)
 326 {
 327   return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
 328 }
 329 
 330 /**
 331  * hb_font_funcs_get_user_data: (skip)
 332  * @ffuncs: font functions.
 333  * @key:
 334  *
 335  *
 336  *
 337  * Return value: (transfer none):
 338  *
 339  * Since: 0.9.2
 340  **/
 341 void *
 342 hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
 343                              hb_user_data_key_t *key)
 344 {
 345   return hb_object_get_user_data (ffuncs, key);
 346 }
 347 
 348 
 349 /**
 350  * hb_font_funcs_make_immutable:
 351  * @ffuncs: font functions.
 352  *
 353  *
 354  *
 355  * Since: 0.9.2
 356  **/
 357 void
 358 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
 359 {
 360   if (unlikely (hb_object_is_inert (ffuncs)))
 361     return;
 362 
 363   ffuncs->immutable = true;
 364 }
 365 
 366 /**
 367  * hb_font_funcs_is_immutable:
 368  * @ffuncs: font functions.
 369  *
 370  *
 371  *
 372  * Return value:
 373  *
 374  * Since: 0.9.2
 375  **/
 376 hb_bool_t
 377 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
 378 {
 379   return ffuncs->immutable;
 380 }
 381 
 382 
 383 #define HB_FONT_FUNC_IMPLEMENT(name) \
 384                                                                          \
 385 void                                                                     \
 386 hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
 387                                  hb_font_get_##name##_func_t  func,      \
 388                                  void                        *user_data, \
 389                                  hb_destroy_func_t            destroy)   \
 390 {                                                                        \
 391   if (ffuncs->immutable) {                                               \
 392     if (destroy)                                                         \
 393       destroy (user_data);                                               \
 394     return;                                                              \
 395   }                                                                      \
 396                                                                          \
 397   if (ffuncs->destroy.name)                                              \
 398     ffuncs->destroy.name (ffuncs->user_data.name);                       \
 399                                                                          \
 400   if (func) {                                                            \
 401     ffuncs->get.name = func;                                             \
 402     ffuncs->user_data.name = user_data;                                  \
 403     ffuncs->destroy.name = destroy;                                      \
 404   } else {                                                               \
 405     ffuncs->get.name = hb_font_get_##name##_nil;                         \
 406     ffuncs->user_data.name = NULL;                                       \
 407     ffuncs->destroy.name = NULL;                                         \
 408   }                                                                      \
 409 }
 410 
 411 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 412 #undef HB_FONT_FUNC_IMPLEMENT
 413 
 414 
 415 /* Public getters */
 416 
 417 /**
 418  * hb_font_get_glyph:
 419  * @font: a font.
 420  * @unicode:
 421  * @variation_selector:
 422  * @glyph: (out):
 423  *
 424  *
 425  *
 426  * Return value:
 427  *
 428  * Since: 0.9.2
 429  **/
 430 hb_bool_t
 431 hb_font_get_glyph (hb_font_t *font,
 432                    hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 433                    hb_codepoint_t *glyph)
 434 {
 435   return font->get_glyph (unicode, variation_selector, glyph);
 436 }
 437 
 438 /**
 439  * hb_font_get_glyph_h_advance:
 440  * @font: a font.
 441  * @glyph:
 442  *
 443  *
 444  *
 445  * Return value:
 446  *
 447  * Since: 0.9.2
 448  **/
 449 hb_position_t
 450 hb_font_get_glyph_h_advance (hb_font_t *font,
 451                              hb_codepoint_t glyph)
 452 {
 453   return font->get_glyph_h_advance (glyph);
 454 }
 455 
 456 /**
 457  * hb_font_get_glyph_v_advance:
 458  * @font: a font.
 459  * @glyph:
 460  *
 461  *
 462  *
 463  * Return value:
 464  *
 465  * Since: 0.9.2
 466  **/
 467 hb_position_t
 468 hb_font_get_glyph_v_advance (hb_font_t *font,
 469                              hb_codepoint_t glyph)
 470 {
 471   return font->get_glyph_v_advance (glyph);
 472 }
 473 
 474 /**
 475  * hb_font_get_glyph_h_origin:
 476  * @font: a font.
 477  * @glyph:
 478  * @x: (out):
 479  * @y: (out):
 480  *
 481  *
 482  *
 483  * Return value:
 484  *
 485  * Since: 0.9.2
 486  **/
 487 hb_bool_t
 488 hb_font_get_glyph_h_origin (hb_font_t *font,
 489                             hb_codepoint_t glyph,
 490                             hb_position_t *x, hb_position_t *y)
 491 {
 492   return font->get_glyph_h_origin (glyph, x, y);
 493 }
 494 
 495 /**
 496  * hb_font_get_glyph_v_origin:
 497  * @font: a font.
 498  * @glyph:
 499  * @x: (out):
 500  * @y: (out):
 501  *
 502  *
 503  *
 504  * Return value:
 505  *
 506  * Since: 0.9.2
 507  **/
 508 hb_bool_t
 509 hb_font_get_glyph_v_origin (hb_font_t *font,
 510                             hb_codepoint_t glyph,
 511                             hb_position_t *x, hb_position_t *y)
 512 {
 513   return font->get_glyph_v_origin (glyph, x, y);
 514 }
 515 
 516 /**
 517  * hb_font_get_glyph_h_kerning:
 518  * @font: a font.
 519  * @left_glyph:
 520  * @right_glyph:
 521  *
 522  *
 523  *
 524  * Return value:
 525  *
 526  * Since: 0.9.2
 527  **/
 528 hb_position_t
 529 hb_font_get_glyph_h_kerning (hb_font_t *font,
 530                              hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
 531 {
 532   return font->get_glyph_h_kerning (left_glyph, right_glyph);
 533 }
 534 
 535 /**
 536  * hb_font_get_glyph_v_kerning:
 537  * @font: a font.
 538  * @top_glyph:
 539  * @bottom_glyph:
 540  *
 541  *
 542  *
 543  * Return value:
 544  *
 545  * Since: 0.9.2
 546  **/
 547 hb_position_t
 548 hb_font_get_glyph_v_kerning (hb_font_t *font,
 549                              hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
 550 {
 551   return font->get_glyph_v_kerning (top_glyph, bottom_glyph);
 552 }
 553 
 554 /**
 555  * hb_font_get_glyph_extents:
 556  * @font: a font.
 557  * @glyph:
 558  * @extents: (out):
 559  *
 560  *
 561  *
 562  * Return value:
 563  *
 564  * Since: 0.9.2
 565  **/
 566 hb_bool_t
 567 hb_font_get_glyph_extents (hb_font_t *font,
 568                            hb_codepoint_t glyph,
 569                            hb_glyph_extents_t *extents)
 570 {
 571   return font->get_glyph_extents (glyph, extents);
 572 }
 573 
 574 /**
 575  * hb_font_get_glyph_contour_point:
 576  * @font: a font.
 577  * @glyph:
 578  * @point_index:
 579  * @x: (out):
 580  * @y: (out):
 581  *
 582  *
 583  *
 584  * Return value:
 585  *
 586  * Since: 0.9.2
 587  **/
 588 hb_bool_t
 589 hb_font_get_glyph_contour_point (hb_font_t *font,
 590                                  hb_codepoint_t glyph, unsigned int point_index,
 591                                  hb_position_t *x, hb_position_t *y)
 592 {
 593   return font->get_glyph_contour_point (glyph, point_index, x, y);
 594 }
 595 
 596 /**
 597  * hb_font_get_glyph_name:
 598  * @font: a font.
 599  * @glyph:
 600  * @name: (array length=size):
 601  * @size:
 602  *
 603  *
 604  *
 605  * Return value:
 606  *
 607  * Since: 0.9.2
 608  **/
 609 hb_bool_t
 610 hb_font_get_glyph_name (hb_font_t *font,
 611                         hb_codepoint_t glyph,
 612                         char *name, unsigned int size)
 613 {
 614   return font->get_glyph_name (glyph, name, size);
 615 }
 616 
 617 /**
 618  * hb_font_get_glyph_from_name:
 619  * @font: a font.
 620  * @name: (array length=len):
 621  * @len:
 622  * @glyph: (out):
 623  *
 624  *
 625  *
 626  * Return value:
 627  *
 628  * Since: 0.9.2
 629  **/
 630 hb_bool_t
 631 hb_font_get_glyph_from_name (hb_font_t *font,
 632                              const char *name, int len, /* -1 means nul-terminated */
 633                              hb_codepoint_t *glyph)
 634 {
 635   return font->get_glyph_from_name (name, len, glyph);
 636 }
 637 
 638 
 639 /* A bit higher-level, and with fallback */
 640 
 641 /**
 642  * hb_font_get_glyph_advance_for_direction:
 643  * @font: a font.
 644  * @glyph:
 645  * @direction:
 646  * @x: (out):
 647  * @y: (out):
 648  *
 649  *
 650  *
 651  * Since: 0.9.2
 652  **/
 653 void
 654 hb_font_get_glyph_advance_for_direction (hb_font_t *font,
 655                                          hb_codepoint_t glyph,
 656                                          hb_direction_t direction,
 657                                          hb_position_t *x, hb_position_t *y)
 658 {
 659   return font->get_glyph_advance_for_direction (glyph, direction, x, y);
 660 }
 661 
 662 /**
 663  * hb_font_get_glyph_origin_for_direction:
 664  * @font: a font.
 665  * @glyph:
 666  * @direction:
 667  * @x: (out):
 668  * @y: (out):
 669  *
 670  *
 671  *
 672  * Since: 0.9.2
 673  **/
 674 void
 675 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
 676                                         hb_codepoint_t glyph,
 677                                         hb_direction_t direction,
 678                                         hb_position_t *x, hb_position_t *y)
 679 {
 680   return font->get_glyph_origin_for_direction (glyph, direction, x, y);
 681 }
 682 
 683 /**
 684  * hb_font_add_glyph_origin_for_direction:
 685  * @font: a font.
 686  * @glyph:
 687  * @direction:
 688  * @x: (out):
 689  * @y: (out):
 690  *
 691  *
 692  *
 693  * Since: 0.9.2
 694  **/
 695 void
 696 hb_font_add_glyph_origin_for_direction (hb_font_t *font,
 697                                         hb_codepoint_t glyph,
 698                                         hb_direction_t direction,
 699                                         hb_position_t *x, hb_position_t *y)
 700 {
 701   return font->add_glyph_origin_for_direction (glyph, direction, x, y);
 702 }
 703 
 704 /**
 705  * hb_font_subtract_glyph_origin_for_direction:
 706  * @font: a font.
 707  * @glyph:
 708  * @direction:
 709  * @x: (out):
 710  * @y: (out):
 711  *
 712  *
 713  *
 714  * Since: 0.9.2
 715  **/
 716 void
 717 hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
 718                                              hb_codepoint_t glyph,
 719                                              hb_direction_t direction,
 720                                              hb_position_t *x, hb_position_t *y)
 721 {
 722   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
 723 }
 724 
 725 /**
 726  * hb_font_get_glyph_kerning_for_direction:
 727  * @font: a font.
 728  * @first_glyph:
 729  * @second_glyph:
 730  * @direction:
 731  * @x: (out):
 732  * @y: (out):
 733  *
 734  *
 735  *
 736  * Since: 0.9.2
 737  **/
 738 void
 739 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
 740                                          hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
 741                                          hb_direction_t direction,
 742                                          hb_position_t *x, hb_position_t *y)
 743 {
 744   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
 745 }
 746 
 747 /**
 748  * hb_font_get_glyph_extents_for_origin:
 749  * @font: a font.
 750  * @glyph:
 751  * @direction:
 752  * @extents: (out):
 753  *
 754  *
 755  *
 756  * Return value:
 757  *
 758  * Since: 0.9.2
 759  **/
 760 hb_bool_t
 761 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
 762                                       hb_codepoint_t glyph,
 763                                       hb_direction_t direction,
 764                                       hb_glyph_extents_t *extents)
 765 {
 766   return font->get_glyph_extents_for_origin (glyph, direction, extents);
 767 }
 768 
 769 /**
 770  * hb_font_get_glyph_contour_point_for_origin:
 771  * @font: a font.
 772  * @glyph:
 773  * @point_index:
 774  * @direction:
 775  * @x: (out):
 776  * @y: (out):
 777  *
 778  *
 779  *
 780  * Return value:
 781  *
 782  * Since: 0.9.2
 783  **/
 784 hb_bool_t
 785 hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
 786                                             hb_codepoint_t glyph, unsigned int point_index,
 787                                             hb_direction_t direction,
 788                                             hb_position_t *x, hb_position_t *y)
 789 {
 790   return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
 791 }
 792 
 793 /* Generates gidDDD if glyph has no name. */
 794 /**
 795  * hb_font_glyph_to_string:
 796  * @font: a font.
 797  * @glyph:
 798  * @s: (array length=size):
 799  * @size:
 800  *
 801  *
 802  *
 803  * Since: 0.9.2
 804  **/
 805 void
 806 hb_font_glyph_to_string (hb_font_t *font,
 807                          hb_codepoint_t glyph,
 808                          char *s, unsigned int size)
 809 {
 810   font->glyph_to_string (glyph, s, size);
 811 }
 812 
 813 /* Parses gidDDD and uniUUUU strings automatically. */
 814 /**
 815  * hb_font_glyph_from_string:
 816  * @font: a font.
 817  * @s: (array length=len) (element-type uint8_t):
 818  * @len:
 819  * @glyph: (out):
 820  *
 821  *
 822  *
 823  * Return value:
 824  *
 825  * Since: 0.9.2
 826  **/
 827 hb_bool_t
 828 hb_font_glyph_from_string (hb_font_t *font,
 829                            const char *s, int len, /* -1 means nul-terminated */
 830                            hb_codepoint_t *glyph)
 831 {
 832   return font->glyph_from_string (s, len, glyph);
 833 }
 834 
 835 
 836 /*
 837  * hb_font_t
 838  */
 839 
 840 /**
 841  * hb_font_create: (Xconstructor)
 842  * @face: a face.
 843  *
 844  *
 845  *
 846  * Return value: (transfer full):
 847  *
 848  * Since: 0.9.2
 849  **/
 850 hb_font_t *
 851 hb_font_create (hb_face_t *face)
 852 {
 853   hb_font_t *font;
 854 
 855   if (unlikely (!face))
 856     face = hb_face_get_empty ();
 857   if (!(font = hb_object_create<hb_font_t> ()))
 858     return hb_font_get_empty ();
 859 
 860   hb_face_make_immutable (face);
 861   font->face = hb_face_reference (face);
 862   font->klass = hb_font_funcs_get_empty ();
 863 
 864   font->x_scale = font->y_scale = hb_face_get_upem (face);
 865 
 866   return font;
 867 }
 868 
 869 /**
 870  * hb_font_create_sub_font:
 871  * @parent: parent font.
 872  *
 873  *
 874  *
 875  * Return value: (transfer full):
 876  *
 877  * Since: 0.9.2
 878  **/
 879 hb_font_t *
 880 hb_font_create_sub_font (hb_font_t *parent)
 881 {
 882   if (unlikely (!parent))
 883     parent = hb_font_get_empty ();
 884 
 885   hb_font_t *font = hb_font_create (parent->face);
 886 
 887   if (unlikely (hb_object_is_inert (font)))
 888     return font;
 889 
 890   font->parent = hb_font_reference (parent);
 891 
 892   font->x_scale = parent->x_scale;
 893   font->y_scale = parent->y_scale;
 894   font->x_ppem = parent->x_ppem;
 895   font->y_ppem = parent->y_ppem;
 896 
 897   return font;
 898 }
 899 
 900 /**
 901  * hb_font_get_empty:
 902  *
 903  *
 904  *
 905  * Return value: (transfer full)
 906  *
 907  * Since: 0.9.2
 908  **/
 909 hb_font_t *
 910 hb_font_get_empty (void)
 911 {
 912   static const hb_font_t _hb_font_nil = {
 913     HB_OBJECT_HEADER_STATIC,
 914 
 915     true, /* immutable */
 916 
 917     NULL, /* parent */
 918     const_cast<hb_face_t *> (&_hb_face_nil),
 919 
 920     0, /* x_scale */
 921     0, /* y_scale */
 922 
 923     0, /* x_ppem */
 924     0, /* y_ppem */
 925 
 926     const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
 927     NULL, /* user_data */
 928     NULL, /* destroy */
 929 
 930     {
 931 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
 932 #include "hb-shaper-list.hh"
 933 #undef HB_SHAPER_IMPLEMENT
 934     }
 935   };
 936 
 937   return const_cast<hb_font_t *> (&_hb_font_nil);
 938 }
 939 
 940 /**
 941  * hb_font_reference: (skip)
 942  * @font: a font.
 943  *
 944  *
 945  *
 946  * Return value: (transfer full):
 947  *
 948  * Since: 0.9.2
 949  **/
 950 hb_font_t *
 951 hb_font_reference (hb_font_t *font)
 952 {
 953   return hb_object_reference (font);
 954 }
 955 
 956 /**
 957  * hb_font_destroy: (skip)
 958  * @font: a font.
 959  *
 960  *
 961  *
 962  * Since: 0.9.2
 963  **/
 964 void
 965 hb_font_destroy (hb_font_t *font)
 966 {
 967   if (!hb_object_destroy (font)) return;
 968 
 969 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
 970 #include "hb-shaper-list.hh"
 971 #undef HB_SHAPER_IMPLEMENT
 972 
 973   if (font->destroy)
 974     font->destroy (font->user_data);
 975 
 976   hb_font_destroy (font->parent);
 977   hb_face_destroy (font->face);
 978   hb_font_funcs_destroy (font->klass);
 979 
 980   free (font);
 981 }
 982 
 983 /**
 984  * hb_font_set_user_data: (skip)
 985  * @font: a font.
 986  * @key:
 987  * @data:
 988  * @destroy:
 989  * @replace:
 990  *
 991  *
 992  *
 993  * Return value:
 994  *
 995  * Since: 0.9.2
 996  **/
 997 hb_bool_t
 998 hb_font_set_user_data (hb_font_t          *font,
 999                        hb_user_data_key_t *key,
1000                        void *              data,
1001                        hb_destroy_func_t   destroy,
1002                        hb_bool_t           replace)
1003 {
1004   return hb_object_set_user_data (font, key, data, destroy, replace);
1005 }
1006 
1007 /**
1008  * hb_font_get_user_data: (skip)
1009  * @font: a font.
1010  * @key:
1011  *
1012  *
1013  *
1014  * Return value: (transfer none):
1015  *
1016  * Since: 0.9.2
1017  **/
1018 void *
1019 hb_font_get_user_data (hb_font_t          *font,
1020                        hb_user_data_key_t *key)
1021 {
1022   return hb_object_get_user_data (font, key);
1023 }
1024 
1025 /**
1026  * hb_font_make_immutable:
1027  * @font: a font.
1028  *
1029  *
1030  *
1031  * Since: 0.9.2
1032  **/
1033 void
1034 hb_font_make_immutable (hb_font_t *font)
1035 {
1036   if (unlikely (hb_object_is_inert (font)))
1037     return;
1038 
1039   if (font->parent)
1040     hb_font_make_immutable (font->parent);
1041 
1042   font->immutable = true;
1043 }
1044 
1045 /**
1046  * hb_font_is_immutable:
1047  * @font: a font.
1048  *
1049  *
1050  *
1051  * Return value:
1052  *
1053  * Since: 0.9.2
1054  **/
1055 hb_bool_t
1056 hb_font_is_immutable (hb_font_t *font)
1057 {
1058   return font->immutable;
1059 }
1060 
1061 /**
1062  * hb_font_set_parent:
1063  * @font: a font.
1064  * @parent: new parent.
1065  *
1066  * Sets parent font of @font.
1067  *
1068  * Since: 1.0.5
1069  **/
1070 void
1071 hb_font_set_parent (hb_font_t *font,
1072                     hb_font_t *parent)
1073 {
1074   if (font->immutable)
1075     return;
1076 
1077   if (!parent)
1078     parent = hb_font_get_empty ();
1079 
1080   hb_font_t *old = font->parent;
1081 
1082   font->parent = hb_font_reference (parent);
1083 
1084   hb_font_destroy (old);
1085 }
1086 
1087 /**
1088  * hb_font_get_parent:
1089  * @font: a font.
1090  *
1091  *
1092  *
1093  * Return value: (transfer none):
1094  *
1095  * Since: 0.9.2
1096  **/
1097 hb_font_t *
1098 hb_font_get_parent (hb_font_t *font)
1099 {
1100   return font->parent;
1101 }
1102 
1103 /**
1104  * hb_font_get_face:
1105  * @font: a font.
1106  *
1107  *
1108  *
1109  * Return value: (transfer none):
1110  *
1111  * Since: 0.9.2
1112  **/
1113 hb_face_t *
1114 hb_font_get_face (hb_font_t *font)
1115 {
1116   return font->face;
1117 }
1118 
1119 
1120 /**
1121  * hb_font_set_funcs:
1122  * @font: a font.
1123  * @klass: (closure font_data) (destroy destroy) (scope notified):
1124  * @font_data:
1125  * @destroy:
1126  *
1127  *
1128  *
1129  * Since: 0.9.2
1130  **/
1131 void
1132 hb_font_set_funcs (hb_font_t         *font,
1133                    hb_font_funcs_t   *klass,
1134                    void              *font_data,
1135                    hb_destroy_func_t  destroy)
1136 {
1137   if (font->immutable) {
1138     if (destroy)
1139       destroy (font_data);
1140     return;
1141   }
1142 
1143   if (font->destroy)
1144     font->destroy (font->user_data);
1145 
1146   if (!klass)
1147     klass = hb_font_funcs_get_empty ();
1148 
1149   hb_font_funcs_reference (klass);
1150   hb_font_funcs_destroy (font->klass);
1151   font->klass = klass;
1152   font->user_data = font_data;
1153   font->destroy = destroy;
1154 }
1155 
1156 /**
1157  * hb_font_set_funcs_data:
1158  * @font: a font.
1159  * @font_data: (destroy destroy) (scope notified):
1160  * @destroy:
1161  *
1162  *
1163  *
1164  * Since: 0.9.2
1165  **/
1166 void
1167 hb_font_set_funcs_data (hb_font_t         *font,
1168                         void              *font_data,
1169                         hb_destroy_func_t  destroy)
1170 {
1171   /* Destroy user_data? */
1172   if (font->immutable) {
1173     if (destroy)
1174       destroy (font_data);
1175     return;
1176   }
1177 
1178   if (font->destroy)
1179     font->destroy (font->user_data);
1180 
1181   font->user_data = font_data;
1182   font->destroy = destroy;
1183 }
1184 
1185 
1186 /**
1187  * hb_font_set_scale:
1188  * @font: a font.
1189  * @x_scale:
1190  * @y_scale:
1191  *
1192  *
1193  *
1194  * Since: 0.9.2
1195  **/
1196 void
1197 hb_font_set_scale (hb_font_t *font,
1198                    int x_scale,
1199                    int y_scale)
1200 {
1201   if (font->immutable)
1202     return;
1203 
1204   font->x_scale = x_scale;
1205   font->y_scale = y_scale;
1206 }
1207 
1208 /**
1209  * hb_font_get_scale:
1210  * @font: a font.
1211  * @x_scale: (out):
1212  * @y_scale: (out):
1213  *
1214  *
1215  *
1216  * Since: 0.9.2
1217  **/
1218 void
1219 hb_font_get_scale (hb_font_t *font,
1220                    int *x_scale,
1221                    int *y_scale)
1222 {
1223   if (x_scale) *x_scale = font->x_scale;
1224   if (y_scale) *y_scale = font->y_scale;
1225 }
1226 
1227 /**
1228  * hb_font_set_ppem:
1229  * @font: a font.
1230  * @x_ppem:
1231  * @y_ppem:
1232  *
1233  *
1234  *
1235  * Since: 0.9.2
1236  **/
1237 void
1238 hb_font_set_ppem (hb_font_t *font,
1239                   unsigned int x_ppem,
1240                   unsigned int y_ppem)
1241 {
1242   if (font->immutable)
1243     return;
1244 
1245   font->x_ppem = x_ppem;
1246   font->y_ppem = y_ppem;
1247 }
1248 
1249 /**
1250  * hb_font_get_ppem:
1251  * @font: a font.
1252  * @x_ppem: (out):
1253  * @y_ppem: (out):
1254  *
1255  *
1256  *
1257  * Since: 0.9.2
1258  **/
1259 void
1260 hb_font_get_ppem (hb_font_t *font,
1261                   unsigned int *x_ppem,
1262                   unsigned int *y_ppem)
1263 {
1264   if (x_ppem) *x_ppem = font->x_ppem;
1265   if (y_ppem) *y_ppem = font->y_ppem;
1266 }