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_font_h_extents_nil (hb_font_t *font,
  49                                 void *font_data HB_UNUSED,
  50                                 hb_font_extents_t *metrics,
  51                                 void *user_data HB_UNUSED)
  52 {
  53   memset (metrics, 0, sizeof (*metrics));
  54   return false;
  55 }
  56 static hb_bool_t
  57 hb_font_get_font_h_extents_parent (hb_font_t *font,
  58                                    void *font_data HB_UNUSED,
  59                                    hb_font_extents_t *metrics,
  60                                    void *user_data HB_UNUSED)
  61 {
  62   hb_bool_t ret = font->parent->get_font_h_extents (metrics);
  63   if (ret) {
  64     metrics->ascender = font->parent_scale_y_distance (metrics->ascender);
  65     metrics->descender = font->parent_scale_y_distance (metrics->descender);
  66     metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap);
  67   }
  68   return ret;
  69 }
  70 
  71 static hb_bool_t
  72 hb_font_get_font_v_extents_nil (hb_font_t *font,
  73                                 void *font_data HB_UNUSED,
  74                                 hb_font_extents_t *metrics,
  75                                 void *user_data HB_UNUSED)
  76 {
  77   memset (metrics, 0, sizeof (*metrics));
  78   return false;
  79 }
  80 static hb_bool_t
  81 hb_font_get_font_v_extents_parent (hb_font_t *font,
  82                                    void *font_data HB_UNUSED,
  83                                    hb_font_extents_t *metrics,
  84                                    void *user_data HB_UNUSED)
  85 {
  86   hb_bool_t ret = font->parent->get_font_v_extents (metrics);
  87   if (ret) {
  88     metrics->ascender = font->parent_scale_x_distance (metrics->ascender);
  89     metrics->descender = font->parent_scale_x_distance (metrics->descender);
  90     metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap);
  91   }
  92   return ret;
  93 }
  94 
  95 static hb_bool_t
  96 hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
  97                                void *font_data HB_UNUSED,
  98                                hb_codepoint_t unicode,
  99                                hb_codepoint_t *glyph,
 100                                void *user_data HB_UNUSED)
 101 {
 102   *glyph = 0;
 103   return false;
 104 }
 105 static hb_bool_t
 106 hb_font_get_nominal_glyph_parent (hb_font_t *font,
 107                                   void *font_data HB_UNUSED,
 108                                   hb_codepoint_t unicode,
 109                                   hb_codepoint_t *glyph,
 110                                   void *user_data HB_UNUSED)
 111 {
 112   return font->parent->get_nominal_glyph (unicode, glyph);
 113 }
 114 
 115 static hb_bool_t
 116 hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
 117                                  void *font_data HB_UNUSED,
 118                                  hb_codepoint_t unicode,
 119                                  hb_codepoint_t variation_selector,
 120                                  hb_codepoint_t *glyph,
 121                                  void *user_data HB_UNUSED)
 122 {
 123   *glyph = 0;
 124   return false;
 125 }
 126 static hb_bool_t
 127 hb_font_get_variation_glyph_parent (hb_font_t *font,
 128                                     void *font_data HB_UNUSED,
 129                                     hb_codepoint_t unicode,
 130                                     hb_codepoint_t variation_selector,
 131                                     hb_codepoint_t *glyph,
 132                                     void *user_data HB_UNUSED)
 133 {
 134   return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
 135 }
 136 
 137 
 138 static hb_position_t
 139 hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
 140                                  void *font_data HB_UNUSED,
 141                                  hb_codepoint_t glyph,
 142                                  void *user_data HB_UNUSED)
 143 {
 144   return font->x_scale;
 145 }
 146 static hb_position_t
 147 hb_font_get_glyph_h_advance_parent (hb_font_t *font,
 148                                     void *font_data HB_UNUSED,
 149                                     hb_codepoint_t glyph,
 150                                     void *user_data HB_UNUSED)
 151 {
 152   return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
 153 }
 154 
 155 static hb_position_t
 156 hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
 157                                  void *font_data HB_UNUSED,
 158                                  hb_codepoint_t glyph,
 159                                  void *user_data HB_UNUSED)
 160 {
 161   /* TODO use font_extents.ascender+descender */
 162   return font->y_scale;
 163 }
 164 static hb_position_t
 165 hb_font_get_glyph_v_advance_parent (hb_font_t *font,
 166                                     void *font_data HB_UNUSED,
 167                                     hb_codepoint_t glyph,
 168                                     void *user_data HB_UNUSED)
 169 {
 170   return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
 171 }
 172 
 173 static hb_bool_t
 174 hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
 175                                 void *font_data HB_UNUSED,
 176                                 hb_codepoint_t glyph,
 177                                 hb_position_t *x,
 178                                 hb_position_t *y,
 179                                 void *user_data HB_UNUSED)
 180 {
 181   *x = *y = 0;
 182   return true;
 183 }
 184 static hb_bool_t
 185 hb_font_get_glyph_h_origin_parent (hb_font_t *font,
 186                                    void *font_data HB_UNUSED,
 187                                    hb_codepoint_t glyph,
 188                                    hb_position_t *x,
 189                                    hb_position_t *y,
 190                                    void *user_data HB_UNUSED)
 191 {
 192   hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
 193   if (ret)
 194     font->parent_scale_position (x, y);
 195   return ret;
 196 }
 197 
 198 static hb_bool_t
 199 hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
 200                                 void *font_data HB_UNUSED,
 201                                 hb_codepoint_t glyph,
 202                                 hb_position_t *x,
 203                                 hb_position_t *y,
 204                                 void *user_data HB_UNUSED)
 205 {
 206   *x = *y = 0;
 207   return false;
 208 }
 209 static hb_bool_t
 210 hb_font_get_glyph_v_origin_parent (hb_font_t *font,
 211                                    void *font_data HB_UNUSED,
 212                                    hb_codepoint_t glyph,
 213                                    hb_position_t *x,
 214                                    hb_position_t *y,
 215                                    void *user_data HB_UNUSED)
 216 {
 217   hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
 218   if (ret)
 219     font->parent_scale_position (x, y);
 220   return ret;
 221 }
 222 
 223 static hb_position_t
 224 hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
 225                                  void *font_data HB_UNUSED,
 226                                  hb_codepoint_t left_glyph,
 227                                  hb_codepoint_t right_glyph,
 228                                  void *user_data HB_UNUSED)
 229 {
 230   return 0;
 231 }
 232 static hb_position_t
 233 hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
 234                                     void *font_data HB_UNUSED,
 235                                     hb_codepoint_t left_glyph,
 236                                     hb_codepoint_t right_glyph,
 237                                     void *user_data HB_UNUSED)
 238 {
 239   return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
 240 }
 241 
 242 static hb_position_t
 243 hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
 244                                  void *font_data HB_UNUSED,
 245                                  hb_codepoint_t top_glyph,
 246                                  hb_codepoint_t bottom_glyph,
 247                                  void *user_data HB_UNUSED)
 248 {
 249   return 0;
 250 }
 251 static hb_position_t
 252 hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
 253                                     void *font_data HB_UNUSED,
 254                                     hb_codepoint_t top_glyph,
 255                                     hb_codepoint_t bottom_glyph,
 256                                     void *user_data HB_UNUSED)
 257 {
 258   return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
 259 }
 260 
 261 static hb_bool_t
 262 hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
 263                                void *font_data HB_UNUSED,
 264                                hb_codepoint_t glyph,
 265                                hb_glyph_extents_t *extents,
 266                                void *user_data HB_UNUSED)
 267 {
 268   memset (extents, 0, sizeof (*extents));
 269   return false;
 270 }
 271 static hb_bool_t
 272 hb_font_get_glyph_extents_parent (hb_font_t *font,
 273                                   void *font_data HB_UNUSED,
 274                                   hb_codepoint_t glyph,
 275                                   hb_glyph_extents_t *extents,
 276                                   void *user_data HB_UNUSED)
 277 {
 278   hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
 279   if (ret) {
 280     font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
 281     font->parent_scale_distance (&extents->width, &extents->height);
 282   }
 283   return ret;
 284 }
 285 
 286 static hb_bool_t
 287 hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
 288                                      void *font_data HB_UNUSED,
 289                                      hb_codepoint_t glyph,
 290                                      unsigned int point_index,
 291                                      hb_position_t *x,
 292                                      hb_position_t *y,
 293                                      void *user_data HB_UNUSED)
 294 {
 295   *x = *y = 0;
 296   return false;
 297 }
 298 static hb_bool_t
 299 hb_font_get_glyph_contour_point_parent (hb_font_t *font,
 300                                         void *font_data HB_UNUSED,
 301                                         hb_codepoint_t glyph,
 302                                         unsigned int point_index,
 303                                         hb_position_t *x,
 304                                         hb_position_t *y,
 305                                         void *user_data HB_UNUSED)
 306 {
 307   hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
 308   if (ret)
 309     font->parent_scale_position (x, y);
 310   return ret;
 311 }
 312 
 313 static hb_bool_t
 314 hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
 315                             void *font_data HB_UNUSED,
 316                             hb_codepoint_t glyph,
 317                             char *name, unsigned int size,
 318                             void *user_data HB_UNUSED)
 319 {
 320   if (size) *name = '\0';
 321   return false;
 322 }
 323 static hb_bool_t
 324 hb_font_get_glyph_name_parent (hb_font_t *font,
 325                                void *font_data HB_UNUSED,
 326                                hb_codepoint_t glyph,
 327                                char *name, unsigned int size,
 328                                void *user_data HB_UNUSED)
 329 {
 330   return font->parent->get_glyph_name (glyph, name, size);
 331 }
 332 
 333 static hb_bool_t
 334 hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
 335                                  void *font_data HB_UNUSED,
 336                                  const char *name, int len, /* -1 means nul-terminated */
 337                                  hb_codepoint_t *glyph,
 338                                  void *user_data HB_UNUSED)
 339 {
 340   *glyph = 0;
 341   return false;
 342 }
 343 static hb_bool_t
 344 hb_font_get_glyph_from_name_parent (hb_font_t *font,
 345                                     void *font_data HB_UNUSED,
 346                                     const char *name, int len, /* -1 means nul-terminated */
 347                                     hb_codepoint_t *glyph,
 348                                     void *user_data HB_UNUSED)
 349 {
 350   return font->parent->get_glyph_from_name (name, len, glyph);
 351 }
 352 
 353 static const hb_font_funcs_t _hb_font_funcs_nil = {
 354   HB_OBJECT_HEADER_STATIC,
 355 
 356   true, /* immutable */
 357 
 358   {
 359 #define HB_FONT_FUNC_IMPLEMENT(name) NULL,
 360     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 361 #undef HB_FONT_FUNC_IMPLEMENT
 362   },
 363   {
 364 #define HB_FONT_FUNC_IMPLEMENT(name) NULL,
 365     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 366 #undef HB_FONT_FUNC_IMPLEMENT
 367   },
 368   {
 369     {
 370 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
 371       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 372 #undef HB_FONT_FUNC_IMPLEMENT
 373     }
 374   }
 375 };
 376 static const hb_font_funcs_t _hb_font_funcs_parent = {
 377   HB_OBJECT_HEADER_STATIC,
 378 
 379   true, /* immutable */
 380 
 381   {
 382 #define HB_FONT_FUNC_IMPLEMENT(name) NULL,
 383     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 384 #undef HB_FONT_FUNC_IMPLEMENT
 385   },
 386   {
 387 #define HB_FONT_FUNC_IMPLEMENT(name) NULL,
 388     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 389 #undef HB_FONT_FUNC_IMPLEMENT
 390   },
 391   {
 392     {
 393 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
 394       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 395 #undef HB_FONT_FUNC_IMPLEMENT
 396     }
 397   }
 398 };
 399 
 400 
 401 /**
 402  * hb_font_funcs_create: (Xconstructor)
 403  *
 404  *
 405  *
 406  * Return value: (transfer full):
 407  *
 408  * Since: 0.9.2
 409  **/
 410 hb_font_funcs_t *
 411 hb_font_funcs_create (void)
 412 {
 413   hb_font_funcs_t *ffuncs;
 414 
 415   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
 416     return hb_font_funcs_get_empty ();
 417 
 418   ffuncs->get = _hb_font_funcs_parent.get;
 419 
 420   return ffuncs;
 421 }
 422 
 423 /**
 424  * hb_font_funcs_get_empty:
 425  *
 426  *
 427  *
 428  * Return value: (transfer full):
 429  *
 430  * Since: 0.9.2
 431  **/
 432 hb_font_funcs_t *
 433 hb_font_funcs_get_empty (void)
 434 {
 435   return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
 436 }
 437 
 438 /**
 439  * hb_font_funcs_reference: (skip)
 440  * @ffuncs: font functions.
 441  *
 442  *
 443  *
 444  * Return value:
 445  *
 446  * Since: 0.9.2
 447  **/
 448 hb_font_funcs_t *
 449 hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
 450 {
 451   return hb_object_reference (ffuncs);
 452 }
 453 
 454 /**
 455  * hb_font_funcs_destroy: (skip)
 456  * @ffuncs: font functions.
 457  *
 458  *
 459  *
 460  * Since: 0.9.2
 461  **/
 462 void
 463 hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
 464 {
 465   if (!hb_object_destroy (ffuncs)) return;
 466 
 467 #define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
 468   ffuncs->destroy.name (ffuncs->user_data.name);
 469   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 470 #undef HB_FONT_FUNC_IMPLEMENT
 471 
 472   free (ffuncs);
 473 }
 474 
 475 /**
 476  * hb_font_funcs_set_user_data: (skip)
 477  * @ffuncs: font functions.
 478  * @key:
 479  * @data:
 480  * @destroy:
 481  * @replace:
 482  *
 483  *
 484  *
 485  * Return value:
 486  *
 487  * Since: 0.9.2
 488  **/
 489 hb_bool_t
 490 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
 491                              hb_user_data_key_t *key,
 492                              void *              data,
 493                              hb_destroy_func_t   destroy,
 494                              hb_bool_t           replace)
 495 {
 496   return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
 497 }
 498 
 499 /**
 500  * hb_font_funcs_get_user_data: (skip)
 501  * @ffuncs: font functions.
 502  * @key:
 503  *
 504  *
 505  *
 506  * Return value: (transfer none):
 507  *
 508  * Since: 0.9.2
 509  **/
 510 void *
 511 hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
 512                              hb_user_data_key_t *key)
 513 {
 514   return hb_object_get_user_data (ffuncs, key);
 515 }
 516 
 517 
 518 /**
 519  * hb_font_funcs_make_immutable:
 520  * @ffuncs: font functions.
 521  *
 522  *
 523  *
 524  * Since: 0.9.2
 525  **/
 526 void
 527 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
 528 {
 529   if (unlikely (hb_object_is_inert (ffuncs)))
 530     return;
 531 
 532   ffuncs->immutable = true;
 533 }
 534 
 535 /**
 536  * hb_font_funcs_is_immutable:
 537  * @ffuncs: font functions.
 538  *
 539  *
 540  *
 541  * Return value:
 542  *
 543  * Since: 0.9.2
 544  **/
 545 hb_bool_t
 546 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
 547 {
 548   return ffuncs->immutable;
 549 }
 550 
 551 
 552 #define HB_FONT_FUNC_IMPLEMENT(name) \
 553                                                                          \
 554 void                                                                     \
 555 hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
 556                                  hb_font_get_##name##_func_t  func,      \
 557                                  void                        *user_data, \
 558                                  hb_destroy_func_t            destroy)   \
 559 {                                                                        \
 560   if (ffuncs->immutable) {                                               \
 561     if (destroy)                                                         \
 562       destroy (user_data);                                               \
 563     return;                                                              \
 564   }                                                                      \
 565                                                                          \
 566   if (ffuncs->destroy.name)                                              \
 567     ffuncs->destroy.name (ffuncs->user_data.name);                       \
 568                                                                          \
 569   if (func) {                                                            \
 570     ffuncs->get.f.name = func;                                           \
 571     ffuncs->user_data.name = user_data;                                  \
 572     ffuncs->destroy.name = destroy;                                      \
 573   } else {                                                               \
 574     ffuncs->get.f.name = hb_font_get_##name##_parent;                    \
 575     ffuncs->user_data.name = NULL;                                       \
 576     ffuncs->destroy.name = NULL;                                         \
 577   }                                                                      \
 578 }
 579 
 580 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 581 #undef HB_FONT_FUNC_IMPLEMENT
 582 
 583 bool
 584 hb_font_t::has_func (unsigned int i)
 585 {
 586   if (parent && parent != hb_font_get_empty () && parent->has_func (i))
 587     return true;
 588   return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
 589 }
 590 
 591 /* Public getters */
 592 
 593 /**
 594  * hb_font_get_h_extents:
 595  * @font: a font.
 596  * @extents: (out):
 597  *
 598  *
 599  *
 600  * Return value:
 601  *
 602  * Since: 1.1.3
 603  **/
 604 hb_bool_t
 605 hb_font_get_h_extents (hb_font_t *font,
 606                        hb_font_extents_t *extents)
 607 {
 608   return font->get_font_h_extents (extents);
 609 }
 610 
 611 /**
 612  * hb_font_get_v_extents:
 613  * @font: a font.
 614  * @extents: (out):
 615  *
 616  *
 617  *
 618  * Return value:
 619  *
 620  * Since: 1.1.3
 621  **/
 622 hb_bool_t
 623 hb_font_get_v_extents (hb_font_t *font,
 624                        hb_font_extents_t *extents)
 625 {
 626   return font->get_font_v_extents (extents);
 627 }
 628 
 629 /**
 630  * hb_font_get_glyph:
 631  * @font: a font.
 632  * @unicode:
 633  * @variation_selector:
 634  * @glyph: (out):
 635  *
 636  *
 637  *
 638  * Return value:
 639  *
 640  * Since: 0.9.2
 641  **/
 642 hb_bool_t
 643 hb_font_get_glyph (hb_font_t *font,
 644                    hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 645                    hb_codepoint_t *glyph)
 646 {
 647   if (unlikely (variation_selector))
 648     return font->get_variation_glyph (unicode, variation_selector, glyph);
 649   return font->get_nominal_glyph (unicode, glyph);
 650 }
 651 
 652 /**
 653  * hb_font_get_nominal_glyph:
 654  * @font: a font.
 655  * @unicode:
 656  * @glyph: (out):
 657  *
 658  *
 659  *
 660  * Return value:
 661  *
 662  * Since: 1.2.3
 663  **/
 664 hb_bool_t
 665 hb_font_get_nominal_glyph (hb_font_t *font,
 666                            hb_codepoint_t unicode,
 667                            hb_codepoint_t *glyph)
 668 {
 669   return font->get_nominal_glyph (unicode, glyph);
 670 }
 671 
 672 /**
 673  * hb_font_get_variation_glyph:
 674  * @font: a font.
 675  * @unicode:
 676  * @variation_selector:
 677  * @glyph: (out):
 678  *
 679  *
 680  *
 681  * Return value:
 682  *
 683  * Since: 1.2.3
 684  **/
 685 hb_bool_t
 686 hb_font_get_variation_glyph (hb_font_t *font,
 687                              hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 688                              hb_codepoint_t *glyph)
 689 {
 690   return font->get_variation_glyph (unicode, variation_selector, glyph);
 691 }
 692 
 693 /**
 694  * hb_font_get_glyph_h_advance:
 695  * @font: a font.
 696  * @glyph:
 697  *
 698  *
 699  *
 700  * Return value:
 701  *
 702  * Since: 0.9.2
 703  **/
 704 hb_position_t
 705 hb_font_get_glyph_h_advance (hb_font_t *font,
 706                              hb_codepoint_t glyph)
 707 {
 708   return font->get_glyph_h_advance (glyph);
 709 }
 710 
 711 /**
 712  * hb_font_get_glyph_v_advance:
 713  * @font: a font.
 714  * @glyph:
 715  *
 716  *
 717  *
 718  * Return value:
 719  *
 720  * Since: 0.9.2
 721  **/
 722 hb_position_t
 723 hb_font_get_glyph_v_advance (hb_font_t *font,
 724                              hb_codepoint_t glyph)
 725 {
 726   return font->get_glyph_v_advance (glyph);
 727 }
 728 
 729 /**
 730  * hb_font_get_glyph_h_origin:
 731  * @font: a font.
 732  * @glyph:
 733  * @x: (out):
 734  * @y: (out):
 735  *
 736  *
 737  *
 738  * Return value:
 739  *
 740  * Since: 0.9.2
 741  **/
 742 hb_bool_t
 743 hb_font_get_glyph_h_origin (hb_font_t *font,
 744                             hb_codepoint_t glyph,
 745                             hb_position_t *x, hb_position_t *y)
 746 {
 747   return font->get_glyph_h_origin (glyph, x, y);
 748 }
 749 
 750 /**
 751  * hb_font_get_glyph_v_origin:
 752  * @font: a font.
 753  * @glyph:
 754  * @x: (out):
 755  * @y: (out):
 756  *
 757  *
 758  *
 759  * Return value:
 760  *
 761  * Since: 0.9.2
 762  **/
 763 hb_bool_t
 764 hb_font_get_glyph_v_origin (hb_font_t *font,
 765                             hb_codepoint_t glyph,
 766                             hb_position_t *x, hb_position_t *y)
 767 {
 768   return font->get_glyph_v_origin (glyph, x, y);
 769 }
 770 
 771 /**
 772  * hb_font_get_glyph_h_kerning:
 773  * @font: a font.
 774  * @left_glyph:
 775  * @right_glyph:
 776  *
 777  *
 778  *
 779  * Return value:
 780  *
 781  * Since: 0.9.2
 782  **/
 783 hb_position_t
 784 hb_font_get_glyph_h_kerning (hb_font_t *font,
 785                              hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
 786 {
 787   return font->get_glyph_h_kerning (left_glyph, right_glyph);
 788 }
 789 
 790 /**
 791  * hb_font_get_glyph_v_kerning:
 792  * @font: a font.
 793  * @top_glyph:
 794  * @bottom_glyph:
 795  *
 796  *
 797  *
 798  * Return value:
 799  *
 800  * Since: 0.9.2
 801  **/
 802 hb_position_t
 803 hb_font_get_glyph_v_kerning (hb_font_t *font,
 804                              hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
 805 {
 806   return font->get_glyph_v_kerning (top_glyph, bottom_glyph);
 807 }
 808 
 809 /**
 810  * hb_font_get_glyph_extents:
 811  * @font: a font.
 812  * @glyph:
 813  * @extents: (out):
 814  *
 815  *
 816  *
 817  * Return value:
 818  *
 819  * Since: 0.9.2
 820  **/
 821 hb_bool_t
 822 hb_font_get_glyph_extents (hb_font_t *font,
 823                            hb_codepoint_t glyph,
 824                            hb_glyph_extents_t *extents)
 825 {
 826   return font->get_glyph_extents (glyph, extents);
 827 }
 828 
 829 /**
 830  * hb_font_get_glyph_contour_point:
 831  * @font: a font.
 832  * @glyph:
 833  * @point_index:
 834  * @x: (out):
 835  * @y: (out):
 836  *
 837  *
 838  *
 839  * Return value:
 840  *
 841  * Since: 0.9.2
 842  **/
 843 hb_bool_t
 844 hb_font_get_glyph_contour_point (hb_font_t *font,
 845                                  hb_codepoint_t glyph, unsigned int point_index,
 846                                  hb_position_t *x, hb_position_t *y)
 847 {
 848   return font->get_glyph_contour_point (glyph, point_index, x, y);
 849 }
 850 
 851 /**
 852  * hb_font_get_glyph_name:
 853  * @font: a font.
 854  * @glyph:
 855  * @name: (array length=size):
 856  * @size:
 857  *
 858  *
 859  *
 860  * Return value:
 861  *
 862  * Since: 0.9.2
 863  **/
 864 hb_bool_t
 865 hb_font_get_glyph_name (hb_font_t *font,
 866                         hb_codepoint_t glyph,
 867                         char *name, unsigned int size)
 868 {
 869   return font->get_glyph_name (glyph, name, size);
 870 }
 871 
 872 /**
 873  * hb_font_get_glyph_from_name:
 874  * @font: a font.
 875  * @name: (array length=len):
 876  * @len:
 877  * @glyph: (out):
 878  *
 879  *
 880  *
 881  * Return value:
 882  *
 883  * Since: 0.9.2
 884  **/
 885 hb_bool_t
 886 hb_font_get_glyph_from_name (hb_font_t *font,
 887                              const char *name, int len, /* -1 means nul-terminated */
 888                              hb_codepoint_t *glyph)
 889 {
 890   return font->get_glyph_from_name (name, len, glyph);
 891 }
 892 
 893 
 894 /* A bit higher-level, and with fallback */
 895 
 896 /**
 897  * hb_font_get_extents_for_direction:
 898  * @font: a font.
 899  * @direction:
 900  * @extents:
 901  *
 902  *
 903  *
 904  * Since: 1.1.3
 905  **/
 906 void
 907 hb_font_get_extents_for_direction (hb_font_t *font,
 908                                    hb_direction_t direction,
 909                                    hb_font_extents_t *extents)
 910 {
 911   return font->get_extents_for_direction (direction, extents);
 912 }
 913 /**
 914  * hb_font_get_glyph_advance_for_direction:
 915  * @font: a font.
 916  * @glyph:
 917  * @direction:
 918  * @x: (out):
 919  * @y: (out):
 920  *
 921  *
 922  *
 923  * Since: 0.9.2
 924  **/
 925 void
 926 hb_font_get_glyph_advance_for_direction (hb_font_t *font,
 927                                          hb_codepoint_t glyph,
 928                                          hb_direction_t direction,
 929                                          hb_position_t *x, hb_position_t *y)
 930 {
 931   return font->get_glyph_advance_for_direction (glyph, direction, x, y);
 932 }
 933 
 934 /**
 935  * hb_font_get_glyph_origin_for_direction:
 936  * @font: a font.
 937  * @glyph:
 938  * @direction:
 939  * @x: (out):
 940  * @y: (out):
 941  *
 942  *
 943  *
 944  * Since: 0.9.2
 945  **/
 946 void
 947 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
 948                                         hb_codepoint_t glyph,
 949                                         hb_direction_t direction,
 950                                         hb_position_t *x, hb_position_t *y)
 951 {
 952   return font->get_glyph_origin_for_direction (glyph, direction, x, y);
 953 }
 954 
 955 /**
 956  * hb_font_add_glyph_origin_for_direction:
 957  * @font: a font.
 958  * @glyph:
 959  * @direction:
 960  * @x: (out):
 961  * @y: (out):
 962  *
 963  *
 964  *
 965  * Since: 0.9.2
 966  **/
 967 void
 968 hb_font_add_glyph_origin_for_direction (hb_font_t *font,
 969                                         hb_codepoint_t glyph,
 970                                         hb_direction_t direction,
 971                                         hb_position_t *x, hb_position_t *y)
 972 {
 973   return font->add_glyph_origin_for_direction (glyph, direction, x, y);
 974 }
 975 
 976 /**
 977  * hb_font_subtract_glyph_origin_for_direction:
 978  * @font: a font.
 979  * @glyph:
 980  * @direction:
 981  * @x: (out):
 982  * @y: (out):
 983  *
 984  *
 985  *
 986  * Since: 0.9.2
 987  **/
 988 void
 989 hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
 990                                              hb_codepoint_t glyph,
 991                                              hb_direction_t direction,
 992                                              hb_position_t *x, hb_position_t *y)
 993 {
 994   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
 995 }
 996 
 997 /**
 998  * hb_font_get_glyph_kerning_for_direction:
 999  * @font: a font.
1000  * @first_glyph:
1001  * @second_glyph:
1002  * @direction:
1003  * @x: (out):
1004  * @y: (out):
1005  *
1006  *
1007  *
1008  * Since: 0.9.2
1009  **/
1010 void
1011 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
1012                                          hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
1013                                          hb_direction_t direction,
1014                                          hb_position_t *x, hb_position_t *y)
1015 {
1016   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
1017 }
1018 
1019 /**
1020  * hb_font_get_glyph_extents_for_origin:
1021  * @font: a font.
1022  * @glyph:
1023  * @direction:
1024  * @extents: (out):
1025  *
1026  *
1027  *
1028  * Return value:
1029  *
1030  * Since: 0.9.2
1031  **/
1032 hb_bool_t
1033 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
1034                                       hb_codepoint_t glyph,
1035                                       hb_direction_t direction,
1036                                       hb_glyph_extents_t *extents)
1037 {
1038   return font->get_glyph_extents_for_origin (glyph, direction, extents);
1039 }
1040 
1041 /**
1042  * hb_font_get_glyph_contour_point_for_origin:
1043  * @font: a font.
1044  * @glyph:
1045  * @point_index:
1046  * @direction:
1047  * @x: (out):
1048  * @y: (out):
1049  *
1050  *
1051  *
1052  * Return value:
1053  *
1054  * Since: 0.9.2
1055  **/
1056 hb_bool_t
1057 hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
1058                                             hb_codepoint_t glyph, unsigned int point_index,
1059                                             hb_direction_t direction,
1060                                             hb_position_t *x, hb_position_t *y)
1061 {
1062   return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
1063 }
1064 
1065 /* Generates gidDDD if glyph has no name. */
1066 /**
1067  * hb_font_glyph_to_string:
1068  * @font: a font.
1069  * @glyph:
1070  * @s: (array length=size):
1071  * @size:
1072  *
1073  *
1074  *
1075  * Since: 0.9.2
1076  **/
1077 void
1078 hb_font_glyph_to_string (hb_font_t *font,
1079                          hb_codepoint_t glyph,
1080                          char *s, unsigned int size)
1081 {
1082   font->glyph_to_string (glyph, s, size);
1083 }
1084 
1085 /* Parses gidDDD and uniUUUU strings automatically. */
1086 /**
1087  * hb_font_glyph_from_string:
1088  * @font: a font.
1089  * @s: (array length=len) (element-type uint8_t):
1090  * @len:
1091  * @glyph: (out):
1092  *
1093  *
1094  *
1095  * Return value:
1096  *
1097  * Since: 0.9.2
1098  **/
1099 hb_bool_t
1100 hb_font_glyph_from_string (hb_font_t *font,
1101                            const char *s, int len, /* -1 means nul-terminated */
1102                            hb_codepoint_t *glyph)
1103 {
1104   return font->glyph_from_string (s, len, glyph);
1105 }
1106 
1107 
1108 /*
1109  * hb_font_t
1110  */
1111 
1112 /**
1113  * hb_font_create: (Xconstructor)
1114  * @face: a face.
1115  *
1116  *
1117  *
1118  * Return value: (transfer full):
1119  *
1120  * Since: 0.9.2
1121  **/
1122 hb_font_t *
1123 hb_font_create (hb_face_t *face)
1124 {
1125   hb_font_t *font;
1126 
1127   if (unlikely (!face))
1128     face = hb_face_get_empty ();
1129   if (!(font = hb_object_create<hb_font_t> ()))
1130     return hb_font_get_empty ();
1131 
1132   hb_face_make_immutable (face);
1133   font->parent = hb_font_get_empty ();
1134   font->face = hb_face_reference (face);
1135   font->klass = hb_font_funcs_get_empty ();
1136 
1137   font->x_scale = font->y_scale = hb_face_get_upem (face);
1138 
1139   return font;
1140 }
1141 
1142 /**
1143  * hb_font_create_sub_font:
1144  * @parent: parent font.
1145  *
1146  *
1147  *
1148  * Return value: (transfer full):
1149  *
1150  * Since: 0.9.2
1151  **/
1152 hb_font_t *
1153 hb_font_create_sub_font (hb_font_t *parent)
1154 {
1155   if (unlikely (!parent))
1156     parent = hb_font_get_empty ();
1157 
1158   hb_font_t *font = hb_font_create (parent->face);
1159 
1160   if (unlikely (hb_object_is_inert (font)))
1161     return font;
1162 
1163   font->parent = hb_font_reference (parent);
1164 
1165   font->x_scale = parent->x_scale;
1166   font->y_scale = parent->y_scale;
1167   font->x_ppem = parent->x_ppem;
1168   font->y_ppem = parent->y_ppem;
1169 
1170   return font;
1171 }
1172 
1173 /**
1174  * hb_font_get_empty:
1175  *
1176  *
1177  *
1178  * Return value: (transfer full)
1179  *
1180  * Since: 0.9.2
1181  **/
1182 hb_font_t *
1183 hb_font_get_empty (void)
1184 {
1185   static const hb_font_t _hb_font_nil = {
1186     HB_OBJECT_HEADER_STATIC,
1187 
1188     true, /* immutable */
1189 
1190     NULL, /* parent */
1191     const_cast<hb_face_t *> (&_hb_face_nil),
1192 
1193     1000, /* x_scale */
1194     1000, /* y_scale */
1195 
1196     0, /* x_ppem */
1197     0, /* y_ppem */
1198 
1199     const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
1200     NULL, /* user_data */
1201     NULL, /* destroy */
1202 
1203     {
1204 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
1205 #include "hb-shaper-list.hh"
1206 #undef HB_SHAPER_IMPLEMENT
1207     }
1208   };
1209 
1210   return const_cast<hb_font_t *> (&_hb_font_nil);
1211 }
1212 
1213 /**
1214  * hb_font_reference: (skip)
1215  * @font: a font.
1216  *
1217  *
1218  *
1219  * Return value: (transfer full):
1220  *
1221  * Since: 0.9.2
1222  **/
1223 hb_font_t *
1224 hb_font_reference (hb_font_t *font)
1225 {
1226   return hb_object_reference (font);
1227 }
1228 
1229 /**
1230  * hb_font_destroy: (skip)
1231  * @font: a font.
1232  *
1233  *
1234  *
1235  * Since: 0.9.2
1236  **/
1237 void
1238 hb_font_destroy (hb_font_t *font)
1239 {
1240   if (!hb_object_destroy (font)) return;
1241 
1242 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
1243 #include "hb-shaper-list.hh"
1244 #undef HB_SHAPER_IMPLEMENT
1245 
1246   if (font->destroy)
1247     font->destroy (font->user_data);
1248 
1249   hb_font_destroy (font->parent);
1250   hb_face_destroy (font->face);
1251   hb_font_funcs_destroy (font->klass);
1252 
1253   free (font);
1254 }
1255 
1256 /**
1257  * hb_font_set_user_data: (skip)
1258  * @font: a font.
1259  * @key:
1260  * @data:
1261  * @destroy:
1262  * @replace:
1263  *
1264  *
1265  *
1266  * Return value:
1267  *
1268  * Since: 0.9.2
1269  **/
1270 hb_bool_t
1271 hb_font_set_user_data (hb_font_t          *font,
1272                        hb_user_data_key_t *key,
1273                        void *              data,
1274                        hb_destroy_func_t   destroy,
1275                        hb_bool_t           replace)
1276 {
1277   return hb_object_set_user_data (font, key, data, destroy, replace);
1278 }
1279 
1280 /**
1281  * hb_font_get_user_data: (skip)
1282  * @font: a font.
1283  * @key:
1284  *
1285  *
1286  *
1287  * Return value: (transfer none):
1288  *
1289  * Since: 0.9.2
1290  **/
1291 void *
1292 hb_font_get_user_data (hb_font_t          *font,
1293                        hb_user_data_key_t *key)
1294 {
1295   return hb_object_get_user_data (font, key);
1296 }
1297 
1298 /**
1299  * hb_font_make_immutable:
1300  * @font: a font.
1301  *
1302  *
1303  *
1304  * Since: 0.9.2
1305  **/
1306 void
1307 hb_font_make_immutable (hb_font_t *font)
1308 {
1309   if (unlikely (hb_object_is_inert (font)))
1310     return;
1311 
1312   if (font->parent)
1313     hb_font_make_immutable (font->parent);
1314 
1315   font->immutable = true;
1316 }
1317 
1318 /**
1319  * hb_font_is_immutable:
1320  * @font: a font.
1321  *
1322  *
1323  *
1324  * Return value:
1325  *
1326  * Since: 0.9.2
1327  **/
1328 hb_bool_t
1329 hb_font_is_immutable (hb_font_t *font)
1330 {
1331   return font->immutable;
1332 }
1333 
1334 /**
1335  * hb_font_set_parent:
1336  * @font: a font.
1337  * @parent: new parent.
1338  *
1339  * Sets parent font of @font.
1340  *
1341  * Since: 1.0.5
1342  **/
1343 void
1344 hb_font_set_parent (hb_font_t *font,
1345                     hb_font_t *parent)
1346 {
1347   if (font->immutable)
1348     return;
1349 
1350   if (!parent)
1351     parent = hb_font_get_empty ();
1352 
1353   hb_font_t *old = font->parent;
1354 
1355   font->parent = hb_font_reference (parent);
1356 
1357   hb_font_destroy (old);
1358 }
1359 
1360 /**
1361  * hb_font_get_parent:
1362  * @font: a font.
1363  *
1364  *
1365  *
1366  * Return value: (transfer none):
1367  *
1368  * Since: 0.9.2
1369  **/
1370 hb_font_t *
1371 hb_font_get_parent (hb_font_t *font)
1372 {
1373   return font->parent;
1374 }
1375 
1376 /**
1377  * hb_font_get_face:
1378  * @font: a font.
1379  *
1380  *
1381  *
1382  * Return value: (transfer none):
1383  *
1384  * Since: 0.9.2
1385  **/
1386 hb_face_t *
1387 hb_font_get_face (hb_font_t *font)
1388 {
1389   return font->face;
1390 }
1391 
1392 
1393 /**
1394  * hb_font_set_funcs:
1395  * @font: a font.
1396  * @klass: (closure font_data) (destroy destroy) (scope notified):
1397  * @font_data:
1398  * @destroy:
1399  *
1400  *
1401  *
1402  * Since: 0.9.2
1403  **/
1404 void
1405 hb_font_set_funcs (hb_font_t         *font,
1406                    hb_font_funcs_t   *klass,
1407                    void              *font_data,
1408                    hb_destroy_func_t  destroy)
1409 {
1410   if (font->immutable) {
1411     if (destroy)
1412       destroy (font_data);
1413     return;
1414   }
1415 
1416   if (font->destroy)
1417     font->destroy (font->user_data);
1418 
1419   if (!klass)
1420     klass = hb_font_funcs_get_empty ();
1421 
1422   hb_font_funcs_reference (klass);
1423   hb_font_funcs_destroy (font->klass);
1424   font->klass = klass;
1425   font->user_data = font_data;
1426   font->destroy = destroy;
1427 }
1428 
1429 /**
1430  * hb_font_set_funcs_data:
1431  * @font: a font.
1432  * @font_data: (destroy destroy) (scope notified):
1433  * @destroy:
1434  *
1435  *
1436  *
1437  * Since: 0.9.2
1438  **/
1439 void
1440 hb_font_set_funcs_data (hb_font_t         *font,
1441                         void              *font_data,
1442                         hb_destroy_func_t  destroy)
1443 {
1444   /* Destroy user_data? */
1445   if (font->immutable) {
1446     if (destroy)
1447       destroy (font_data);
1448     return;
1449   }
1450 
1451   if (font->destroy)
1452     font->destroy (font->user_data);
1453 
1454   font->user_data = font_data;
1455   font->destroy = destroy;
1456 }
1457 
1458 
1459 /**
1460  * hb_font_set_scale:
1461  * @font: a font.
1462  * @x_scale:
1463  * @y_scale:
1464  *
1465  *
1466  *
1467  * Since: 0.9.2
1468  **/
1469 void
1470 hb_font_set_scale (hb_font_t *font,
1471                    int x_scale,
1472                    int y_scale)
1473 {
1474   if (font->immutable)
1475     return;
1476 
1477   font->x_scale = x_scale;
1478   font->y_scale = y_scale;
1479 }
1480 
1481 /**
1482  * hb_font_get_scale:
1483  * @font: a font.
1484  * @x_scale: (out):
1485  * @y_scale: (out):
1486  *
1487  *
1488  *
1489  * Since: 0.9.2
1490  **/
1491 void
1492 hb_font_get_scale (hb_font_t *font,
1493                    int *x_scale,
1494                    int *y_scale)
1495 {
1496   if (x_scale) *x_scale = font->x_scale;
1497   if (y_scale) *y_scale = font->y_scale;
1498 }
1499 
1500 /**
1501  * hb_font_set_ppem:
1502  * @font: a font.
1503  * @x_ppem:
1504  * @y_ppem:
1505  *
1506  *
1507  *
1508  * Since: 0.9.2
1509  **/
1510 void
1511 hb_font_set_ppem (hb_font_t *font,
1512                   unsigned int x_ppem,
1513                   unsigned int y_ppem)
1514 {
1515   if (font->immutable)
1516     return;
1517 
1518   font->x_ppem = x_ppem;
1519   font->y_ppem = y_ppem;
1520 }
1521 
1522 /**
1523  * hb_font_get_ppem:
1524  * @font: a font.
1525  * @x_ppem: (out):
1526  * @y_ppem: (out):
1527  *
1528  *
1529  *
1530  * Since: 0.9.2
1531  **/
1532 void
1533 hb_font_get_ppem (hb_font_t *font,
1534                   unsigned int *x_ppem,
1535                   unsigned int *y_ppem)
1536 {
1537   if (x_ppem) *x_ppem = font->x_ppem;
1538   if (y_ppem) *y_ppem = font->y_ppem;
1539 }
1540 
1541 
1542 #ifndef HB_DISABLE_DEPRECATED
1543 
1544 /*
1545  * Deprecated get_glyph_func():
1546  */
1547 
1548 struct hb_trampoline_closure_t
1549 {
1550   void *user_data;
1551   hb_destroy_func_t destroy;
1552   unsigned int ref_count;
1553 };
1554 
1555 template <typename FuncType>
1556 struct hb_trampoline_t
1557 {
1558   hb_trampoline_closure_t closure; /* Must be first. */
1559   FuncType func;
1560 };
1561 
1562 template <typename FuncType>
1563 static hb_trampoline_t<FuncType> *
1564 trampoline_create (FuncType           func,
1565                    void              *user_data,
1566                    hb_destroy_func_t  destroy)
1567 {
1568   typedef hb_trampoline_t<FuncType> trampoline_t;
1569 
1570   trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
1571 
1572   if (unlikely (!trampoline))
1573     return NULL;
1574 
1575   trampoline->closure.user_data = user_data;
1576   trampoline->closure.destroy = destroy;
1577   trampoline->closure.ref_count = 1;
1578   trampoline->func = func;
1579 
1580   return trampoline;
1581 }
1582 
1583 static void
1584 trampoline_reference (hb_trampoline_closure_t *closure)
1585 {
1586   closure->ref_count++;
1587 }
1588 
1589 static void
1590 trampoline_destroy (void *user_data)
1591 {
1592   hb_trampoline_closure_t *closure = (hb_trampoline_closure_t *) user_data;
1593 
1594   if (--closure->ref_count)
1595     return;
1596 
1597   if (closure->destroy)
1598     closure->destroy (closure->user_data);
1599   free (closure);
1600 }
1601 
1602 typedef hb_trampoline_t<hb_font_get_glyph_func_t> hb_font_get_glyph_trampoline_t;
1603 
1604 static hb_bool_t
1605 hb_font_get_nominal_glyph_trampoline (hb_font_t *font,
1606                                       void *font_data,
1607                                       hb_codepoint_t unicode,
1608                                       hb_codepoint_t *glyph,
1609                                       void *user_data)
1610 {
1611   hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
1612   return trampoline->func (font, font_data, unicode, 0, glyph, trampoline->closure.user_data);
1613 }
1614 
1615 static hb_bool_t
1616 hb_font_get_variation_glyph_trampoline (hb_font_t *font,
1617                                         void *font_data,
1618                                         hb_codepoint_t unicode,
1619                                         hb_codepoint_t variation_selector,
1620                                         hb_codepoint_t *glyph,
1621                                         void *user_data)
1622 {
1623   hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
1624   return trampoline->func (font, font_data, unicode, variation_selector, glyph, trampoline->closure.user_data);
1625 }
1626 
1627 /**
1628  * hb_font_funcs_set_glyph_func:
1629  * @ffuncs: font functions.
1630  * @func: (closure user_data) (destroy destroy) (scope notified):
1631  * @user_data:
1632  * @destroy:
1633  *
1634  * Deprecated.  Use hb_font_funcs_set_nominal_glyph_func() and
1635  * hb_font_funcs_set_variation_glyph_func() instead.
1636  *
1637  * Since: 0.9.2
1638  * Deprecated: 1.2.3
1639  **/
1640 void
1641 hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
1642                               hb_font_get_glyph_func_t func,
1643                               void *user_data, hb_destroy_func_t destroy)
1644 {
1645   hb_font_get_glyph_trampoline_t *trampoline;
1646 
1647   trampoline = trampoline_create (func, user_data, destroy);
1648   if (unlikely (!trampoline))
1649   {
1650     if (destroy)
1651       destroy (user_data);
1652     return;
1653   }
1654 
1655   hb_font_funcs_set_nominal_glyph_func (ffuncs,
1656                                         hb_font_get_nominal_glyph_trampoline,
1657                                         trampoline,
1658                                         trampoline_destroy);
1659 
1660   trampoline_reference (&trampoline->closure);
1661   hb_font_funcs_set_variation_glyph_func (ffuncs,
1662                                           hb_font_get_variation_glyph_trampoline,
1663                                           trampoline,
1664                                           trampoline_destroy);
1665 }
1666 
1667 #endif /* HB_DISABLE_DEPRECATED */