Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/harfbuzz/src/hb-ot-font.cc
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2011,2014  Google, Inc.
3
 *
4
 *  This is part of HarfBuzz, a text shaping library.
5
 *
6
 * Permission is hereby granted, without written agreement and without
7
 * license or royalty fees, to use, copy, modify, and distribute this
8
 * software and its documentation for any purpose, provided that the
9
 * above copyright notice and the following two paragraphs appear in
10
 * all copies of this software.
11
 *
12
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16
 * DAMAGE.
17
 *
18
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23
 *
24
 * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
25
 */
26
27
#include "hb.hh"
28
29
#ifndef HB_NO_OT_FONT
30
31
#include "hb-ot.h"
32
33
#include "hb-cache.hh"
34
#include "hb-font.hh"
35
#include "hb-machinery.hh"
36
#include "hb-ot-face.hh"
37
38
#include "hb-ot-cmap-table.hh"
39
#include "hb-ot-glyf-table.hh"
40
#include "hb-ot-cff2-table.hh"
41
#include "hb-ot-cff1-table.hh"
42
#include "hb-ot-hmtx-table.hh"
43
#include "hb-ot-post-table.hh"
44
#include "hb-ot-stat-table.hh"
45
#include "hb-ot-var-varc-table.hh"
46
#include "hb-ot-vorg-table.hh"
47
#include "OT/Color/CBDT/CBDT.hh"
48
#include "OT/Color/COLR/COLR.hh"
49
#include "OT/Color/sbix/sbix.hh"
50
#include "OT/Color/svg/svg.hh"
51
52
53
/**
54
 * SECTION:hb-ot-font
55
 * @title: hb-ot-font
56
 * @short_description: OpenType font implementation
57
 * @include: hb-ot.h
58
 *
59
 * Functions for using OpenType fonts with hb_shape().  Note that fonts returned
60
 * by hb_font_create() default to using these functions, so most clients would
61
 * never need to call these functions directly.
62
 **/
63
64
using hb_ot_font_advance_cache_t = hb_cache_t<24, 16>;
65
static_assert (sizeof (hb_ot_font_advance_cache_t) == 1024, "");
66
67
struct hb_ot_font_t
68
{
69
  const hb_ot_face_t *ot_face;
70
71
  /* h_advance caching */
72
  mutable hb_atomic_t<int> cached_coords_serial;
73
  struct advance_cache_t
74
  {
75
    mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache;
76
    mutable hb_atomic_t<OT::ItemVariationStore::cache_t *> varStore_cache;
77
78
    ~advance_cache_t ()
79
936k
    {
80
936k
      clear ();
81
936k
    }
82
83
    hb_ot_font_advance_cache_t *acquire_advance_cache () const
84
0
    {
85
0
    retry:
86
0
      auto *cache = advance_cache.get_acquire ();
87
0
      if (!cache)
88
0
      {
89
0
        cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
90
0
  if (!cache)
91
0
    return nullptr;
92
0
  new (cache) hb_ot_font_advance_cache_t;
93
0
  return cache;
94
0
      }
95
0
      if (advance_cache.cmpexch (cache, nullptr))
96
0
        return cache;
97
0
      else
98
0
        goto retry;
99
0
    }
100
    void release_advance_cache (hb_ot_font_advance_cache_t *cache) const
101
0
    {
102
0
      if (!cache)
103
0
        return;
104
0
      if (!advance_cache.cmpexch (nullptr, cache))
105
0
        hb_free (cache);
106
0
    }
107
    void clear_advance_cache () const
108
936k
    {
109
936k
    retry:
110
936k
      auto *cache = advance_cache.get_acquire ();
111
936k
      if (!cache)
112
936k
  return;
113
0
      if (advance_cache.cmpexch (cache, nullptr))
114
0
  hb_free (cache);
115
0
      else
116
0
        goto retry;
117
0
    }
118
119
    OT::ItemVariationStore::cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
120
42.4M
    {
121
42.4M
    retry:
122
42.4M
      auto *cache = varStore_cache.get_acquire ();
123
42.4M
      if (!cache)
124
42.4M
  return varStore.create_cache ();
125
0
      if (varStore_cache.cmpexch (cache, nullptr))
126
0
  return cache;
127
0
      else
128
0
  goto retry;
129
0
    }
130
    void release_varStore_cache (OT::ItemVariationStore::cache_t *cache) const
131
42.4M
    {
132
42.4M
      if (!cache)
133
42.4M
  return;
134
0
      if (!varStore_cache.cmpexch (nullptr, cache))
135
0
  OT::ItemVariationStore::destroy_cache (cache);
136
0
    }
137
    void clear_varStore_cache () const
138
936k
    {
139
936k
    retry:
140
936k
      auto *cache = varStore_cache.get_acquire ();
141
936k
      if (!cache)
142
936k
  return;
143
0
      if (varStore_cache.cmpexch (cache, nullptr))
144
0
  OT::ItemVariationStore::destroy_cache (cache);
145
0
      else
146
0
  goto retry;
147
0
    }
148
149
    void clear () const
150
936k
    {
151
936k
      clear_advance_cache ();
152
936k
      clear_varStore_cache ();
153
936k
    }
154
155
  } h, v;
156
157
  void check_serial (hb_font_t *font) const
158
42.4M
  {
159
42.4M
    int font_serial = font->serial_coords.get_acquire ();
160
161
42.4M
    if (cached_coords_serial.get_acquire () == font_serial)
162
42.4M
      return;
163
164
0
    h.clear ();
165
0
    v.clear ();
166
167
0
    cached_coords_serial.set_release (font_serial);
168
0
  }
169
};
170
171
static hb_ot_font_t *
172
_hb_ot_font_create (hb_font_t *font)
173
469k
{
174
469k
  hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
175
469k
  if (unlikely (!ot_font))
176
0
    return nullptr;
177
178
469k
  ot_font->ot_face = &font->face->table;
179
180
469k
  return ot_font;
181
469k
}
182
183
static void
184
_hb_ot_font_destroy (void *font_data)
185
468k
{
186
468k
  hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
187
188
468k
  ot_font->~hb_ot_font_t ();
189
190
468k
  hb_free (ot_font);
191
468k
}
192
193
static hb_bool_t
194
hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
195
       void *font_data,
196
       hb_codepoint_t unicode,
197
       hb_codepoint_t *glyph,
198
       void *user_data HB_UNUSED)
199
152M
{
200
152M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
201
152M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
202
152M
  return ot_face->cmap->get_nominal_glyph (unicode, glyph);
203
152M
}
204
205
static unsigned int
206
hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
207
        void *font_data,
208
        unsigned int count,
209
        const hb_codepoint_t *first_unicode,
210
        unsigned int unicode_stride,
211
        hb_codepoint_t *first_glyph,
212
        unsigned int glyph_stride,
213
        void *user_data HB_UNUSED)
214
33.1M
{
215
33.1M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
216
33.1M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
217
33.1M
  return ot_face->cmap->get_nominal_glyphs (count,
218
33.1M
              first_unicode, unicode_stride,
219
33.1M
              first_glyph, glyph_stride);
220
33.1M
}
221
222
static hb_bool_t
223
hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
224
         void *font_data,
225
         hb_codepoint_t unicode,
226
         hb_codepoint_t variation_selector,
227
         hb_codepoint_t *glyph,
228
         void *user_data HB_UNUSED)
229
25.4k
{
230
25.4k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
231
25.4k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
232
25.4k
  return ot_face->cmap->get_variation_glyph (unicode,
233
25.4k
                                             variation_selector, glyph);
234
25.4k
}
235
236
static void
237
hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
238
          unsigned count,
239
          const hb_codepoint_t *first_glyph,
240
          unsigned glyph_stride,
241
          hb_position_t *first_advance,
242
          unsigned advance_stride,
243
          void *user_data HB_UNUSED)
244
42.4M
{
245
246
42.4M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
247
42.4M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
248
42.4M
  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
249
250
42.4M
  ot_font->check_serial (font);
251
42.4M
  const OT::HVAR &HVAR = *hmtx.var_table;
252
42.4M
  const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
253
42.4M
  OT::ItemVariationStore::cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore);
254
255
42.4M
  hb_ot_font_advance_cache_t *advance_cache = nullptr;
256
257
42.4M
  bool use_cache = font->num_coords;
258
42.4M
  if (use_cache)
259
0
  {
260
0
    advance_cache = ot_font->h.acquire_advance_cache ();
261
0
    if (!advance_cache)
262
0
      use_cache = false;
263
0
  }
264
265
42.4M
  if (!use_cache)
266
42.4M
  {
267
553M
    for (unsigned int i = 0; i < count; i++)
268
510M
    {
269
510M
      *first_advance = font->em_scale_x (hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
270
510M
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
271
510M
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
272
510M
    }
273
42.4M
  }
274
0
  else
275
0
  { /* Use cache. */
276
0
    for (unsigned int i = 0; i < count; i++)
277
0
    {
278
0
      hb_position_t v;
279
0
      unsigned cv;
280
0
      if (advance_cache->get (*first_glyph, &cv))
281
0
  v = cv;
282
0
      else
283
0
      {
284
0
        v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
285
0
  advance_cache->set (*first_glyph, v);
286
0
      }
287
0
      *first_advance = font->em_scale_x (v);
288
0
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
289
0
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
290
0
    }
291
292
0
    ot_font->h.release_advance_cache (advance_cache);
293
0
  }
294
295
42.4M
  ot_font->h.release_varStore_cache (varStore_cache);
296
42.4M
}
297
298
#ifndef HB_NO_VERTICAL
299
static void
300
hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
301
          unsigned count,
302
          const hb_codepoint_t *first_glyph,
303
          unsigned glyph_stride,
304
          hb_position_t *first_advance,
305
          unsigned advance_stride,
306
          void *user_data HB_UNUSED)
307
1.74M
{
308
1.74M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
309
1.74M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
310
1.74M
  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
311
312
1.74M
  if (vmtx.has_data ())
313
0
  {
314
0
    ot_font->check_serial (font);
315
0
    const OT::VVAR &VVAR = *vmtx.var_table;
316
0
    const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
317
0
    OT::ItemVariationStore::cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore);
318
    // TODO Use advance_cache.
319
320
0
    for (unsigned int i = 0; i < count; i++)
321
0
    {
322
0
      *first_advance = font->em_scale_y (-(int) vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
323
0
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
324
0
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
325
0
    }
326
327
0
    ot_font->v.release_varStore_cache (varStore_cache);
328
0
  }
329
1.74M
  else
330
1.74M
  {
331
1.74M
    hb_font_extents_t font_extents;
332
1.74M
    font->get_h_extents_with_fallback (&font_extents);
333
1.74M
    hb_position_t advance = -(font_extents.ascender - font_extents.descender);
334
335
4.47M
    for (unsigned int i = 0; i < count; i++)
336
2.72M
    {
337
2.72M
      *first_advance = advance;
338
2.72M
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
339
2.72M
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
340
2.72M
    }
341
1.74M
  }
342
1.74M
}
343
#endif
344
345
#ifndef HB_NO_VERTICAL
346
static hb_bool_t
347
hb_ot_get_glyph_v_origin (hb_font_t *font,
348
        void *font_data,
349
        hb_codepoint_t glyph,
350
        hb_position_t *x,
351
        hb_position_t *y,
352
        void *user_data HB_UNUSED)
353
2.72M
{
354
2.72M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
355
2.72M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
356
357
2.72M
  *x = font->get_glyph_h_advance (glyph) / 2;
358
359
2.72M
  const OT::VORG &VORG = *ot_face->VORG;
360
2.72M
  if (VORG.has_data ())
361
0
  {
362
0
    float delta = 0;
363
364
0
#ifndef HB_NO_VAR
365
0
    const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
366
0
    const OT::VVAR &VVAR = *vmtx.var_table;
367
0
    if (font->num_coords)
368
0
      VVAR.get_vorg_delta_unscaled (glyph,
369
0
            font->coords, font->num_coords,
370
0
            &delta);
371
0
#endif
372
373
0
    *y = font->em_scalef_y (VORG.get_y_origin (glyph) + delta);
374
0
    return true;
375
0
  }
376
377
2.72M
  hb_glyph_extents_t extents = {0};
378
379
2.72M
  if (hb_font_get_glyph_extents (font, glyph, &extents))
380
2.72M
  {
381
2.72M
    const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
382
2.72M
    int tsb = 0;
383
2.72M
    if (vmtx.get_leading_bearing_with_var_unscaled (font, glyph, &tsb))
384
0
    {
385
0
      *y = extents.y_bearing + font->em_scale_y (tsb);
386
0
      return true;
387
0
    }
388
389
2.72M
    hb_font_extents_t font_extents;
390
2.72M
    font->get_h_extents_with_fallback (&font_extents);
391
2.72M
    hb_position_t advance = font_extents.ascender - font_extents.descender;
392
2.72M
    hb_position_t diff = advance - -extents.height;
393
2.72M
    *y = extents.y_bearing + (diff >> 1);
394
2.72M
    return true;
395
2.72M
  }
396
397
0
  hb_font_extents_t font_extents;
398
0
  font->get_h_extents_with_fallback (&font_extents);
399
0
  *y = font_extents.ascender;
400
401
0
  return true;
402
2.72M
}
403
#endif
404
405
static hb_bool_t
406
hb_ot_get_glyph_extents (hb_font_t *font,
407
       void *font_data,
408
       hb_codepoint_t glyph,
409
       hb_glyph_extents_t *extents,
410
       void *user_data HB_UNUSED)
411
6.71M
{
412
6.71M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
413
6.71M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
414
415
6.71M
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
416
  /* tdf#159529 clear the hb_ot_face_t's data after fetching 'sbix' table
417
   * The 'sbix' table can be very large for color emoji fonts so clear any
418
   * cached data in hb_ot_face_t after fetching that table's extents. */
419
6.71M
  bool sbixResult = ot_face->sbix->get_extents (font, glyph, extents);
420
6.71M
  const_cast<hb_ot_face_t*>(ot_face)->sbix.fini ();
421
6.71M
  if (sbixResult) return true;
422
6.71M
  if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
423
6.71M
#endif
424
6.71M
#if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
425
6.71M
  if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
426
6.71M
#endif
427
#ifndef HB_NO_VAR_COMPOSITES
428
  if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
429
#endif
430
  /* tdf#159529 clear the hb_ot_face_t's data after fetching 'glyf' table
431
   * The 'glyf' table can be very large for color emoji fonts so clear any
432
   * cached data in hb_ot_face_t after fetching that table's extents. */
433
6.71M
  bool glyfResult = ot_face->glyf->get_extents (font, glyph, extents);
434
6.71M
  const_cast<hb_ot_face_t*>(ot_face)->glyf.fini ();
435
6.71M
  if (glyfResult) return true;
436
0
#ifndef HB_NO_OT_FONT_CFF
437
0
  if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
438
0
  if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
439
0
#endif
440
441
0
  return false;
442
0
}
443
444
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
445
static hb_bool_t
446
hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
447
          void *font_data,
448
          hb_codepoint_t glyph,
449
          char *name, unsigned int size,
450
          void *user_data HB_UNUSED)
451
0
{
452
0
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
453
0
  const hb_ot_face_t *ot_face = ot_font->ot_face;
454
455
0
  if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
456
0
#ifndef HB_NO_OT_FONT_CFF
457
0
  if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
458
0
#endif
459
0
  return false;
460
0
}
461
static hb_bool_t
462
hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
463
         void *font_data,
464
         const char *name, int len,
465
         hb_codepoint_t *glyph,
466
         void *user_data HB_UNUSED)
467
0
{
468
0
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
469
0
  const hb_ot_face_t *ot_face = ot_font->ot_face;
470
471
0
  if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
472
0
#ifndef HB_NO_OT_FONT_CFF
473
0
    if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
474
0
#endif
475
0
  return false;
476
0
}
477
#endif
478
479
static hb_bool_t
480
hb_ot_get_font_h_extents (hb_font_t *font,
481
        void *font_data HB_UNUSED,
482
        hb_font_extents_t *metrics,
483
        void *user_data HB_UNUSED)
484
4.57M
{
485
4.57M
  return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
486
4.57M
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
487
4.57M
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
488
4.57M
}
489
490
#ifndef HB_NO_VERTICAL
491
static hb_bool_t
492
hb_ot_get_font_v_extents (hb_font_t *font,
493
        void *font_data HB_UNUSED,
494
        hb_font_extents_t *metrics,
495
        void *user_data HB_UNUSED)
496
0
{
497
0
  return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_ASCENDER, &metrics->ascender) &&
498
0
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) &&
499
0
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
500
0
}
501
#endif
502
503
#ifndef HB_NO_DRAW
504
static hb_bool_t
505
hb_ot_draw_glyph_or_fail (hb_font_t *font,
506
        void *font_data HB_UNUSED,
507
        hb_codepoint_t glyph,
508
        hb_draw_funcs_t *draw_funcs, void *draw_data,
509
        void *user_data)
510
0
{
511
0
  hb_draw_session_t draw_session {draw_funcs, draw_data};
512
#ifndef HB_NO_VAR_COMPOSITES
513
  if (font->face->table.VARC->get_path (font, glyph, draw_session)) return true;
514
#endif
515
  // Keep the following in synch with VARC::get_path_at()
516
0
  if (font->face->table.glyf->get_path (font, glyph, draw_session)) return true;
517
0
#ifndef HB_NO_CFF
518
0
  if (font->face->table.cff2->get_path (font, glyph, draw_session)) return true;
519
0
  if (font->face->table.cff1->get_path (font, glyph, draw_session)) return true;
520
0
#endif
521
0
  return false;
522
0
}
523
#endif
524
525
#ifndef HB_NO_PAINT
526
static hb_bool_t
527
hb_ot_paint_glyph_or_fail (hb_font_t *font,
528
         void *font_data,
529
         hb_codepoint_t glyph,
530
         hb_paint_funcs_t *paint_funcs, void *paint_data,
531
         unsigned int palette,
532
         hb_color_t foreground,
533
         void *user_data)
534
0
{
535
0
#ifndef HB_NO_COLOR
536
0
  if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true;
537
0
  if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
538
0
#ifndef HB_NO_OT_FONT_BITMAP
539
0
  if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
540
0
  if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
541
0
#endif
542
0
#endif
543
0
  return false;
544
0
}
545
#endif
546
547
static inline void free_static_ot_funcs ();
548
549
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
550
{
551
  static hb_font_funcs_t *create ()
552
28
  {
553
28
    hb_font_funcs_t *funcs = hb_font_funcs_create ();
554
555
28
    hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
556
28
    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
557
28
    hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
558
559
28
    hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
560
28
    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
561
    //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
562
563
28
#ifndef HB_NO_VERTICAL
564
28
    hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
565
28
    hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
566
28
    hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
567
28
#endif
568
569
28
#ifndef HB_NO_DRAW
570
28
    hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ot_draw_glyph_or_fail, nullptr, nullptr);
571
28
#endif
572
573
28
#ifndef HB_NO_PAINT
574
28
    hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ot_paint_glyph_or_fail, nullptr, nullptr);
575
28
#endif
576
577
28
    hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
578
    //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
579
580
28
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
581
28
    hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
582
28
    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
583
28
#endif
584
585
28
    hb_font_funcs_make_immutable (funcs);
586
587
28
    hb_atexit (free_static_ot_funcs);
588
589
28
    return funcs;
590
28
  }
591
} static_ot_funcs;
592
593
static inline
594
void free_static_ot_funcs ()
595
28
{
596
28
  static_ot_funcs.free_instance ();
597
28
}
598
599
static hb_font_funcs_t *
600
_hb_ot_get_font_funcs ()
601
469k
{
602
469k
  return static_ot_funcs.get_unconst ();
603
469k
}
604
605
606
/**
607
 * hb_ot_font_set_funcs:
608
 * @font: #hb_font_t to work upon
609
 *
610
 * Sets the font functions to use when working with @font to
611
 * the HarfBuzz's native implementation. This is the default
612
 * for fonts newly created.
613
 *
614
 * Since: 0.9.28
615
 **/
616
void
617
hb_ot_font_set_funcs (hb_font_t *font)
618
469k
{
619
469k
  hb_ot_font_t *ot_font = _hb_ot_font_create (font);
620
469k
  if (unlikely (!ot_font))
621
0
    return;
622
623
469k
  hb_font_set_funcs (font,
624
469k
         _hb_ot_get_font_funcs (),
625
469k
         ot_font,
626
469k
         _hb_ot_font_destroy);
627
469k
}
628
629
#endif