Coverage Report

Created: 2026-01-10 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/hb-ot-font.cc
Line
Count
Source
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-var-gvar-table.hh"
41
#include "hb-ot-cff2-table.hh"
42
#include "hb-ot-cff1-table.hh"
43
#include "hb-ot-hmtx-table.hh"
44
#include "hb-ot-post-table.hh"
45
#include "hb-ot-stat-table.hh"
46
#include "hb-ot-var-varc-table.hh"
47
#include "hb-ot-vorg-table.hh"
48
#include "OT/Color/CBDT/CBDT.hh"
49
#include "OT/Color/COLR/COLR.hh"
50
#include "OT/Color/sbix/sbix.hh"
51
#include "OT/Color/svg/svg.hh"
52
53
54
/**
55
 * SECTION:hb-ot-font
56
 * @title: hb-ot-font
57
 * @short_description: OpenType font implementation
58
 * @include: hb-ot.h
59
 *
60
 * Functions for using OpenType fonts with hb_shape().  Note that fonts returned
61
 * by hb_font_create() default to using these functions, so most clients would
62
 * never need to call these functions directly.
63
 **/
64
65
using hb_ot_font_advance_cache_t = hb_cache_t<24, 16>;
66
static_assert (sizeof (hb_ot_font_advance_cache_t) == 1024, "");
67
68
using hb_ot_font_origin_cache_t = hb_cache_t<20, 20>;
69
static_assert (sizeof (hb_ot_font_origin_cache_t) == 1024, "");
70
71
struct hb_ot_font_t
72
{
73
  const hb_ot_face_t *ot_face;
74
75
  mutable hb_atomic_t<int> cached_serial;
76
  mutable hb_atomic_t<int> cached_coords_serial;
77
78
  struct direction_cache_t
79
  {
80
    mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache;
81
    mutable hb_atomic_t<OT::hb_scalar_cache_t *> varStore_cache;
82
83
    ~direction_cache_t ()
84
85.5k
    {
85
85.5k
      clear ();
86
85.5k
    }
87
88
    hb_ot_font_advance_cache_t *acquire_advance_cache () const
89
6.54k
    {
90
6.54k
    retry:
91
6.54k
      auto *cache = advance_cache.get_acquire ();
92
6.54k
      if (!cache)
93
1.39k
      {
94
1.39k
        cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
95
1.39k
  if (!cache)
96
86
    return nullptr;
97
1.30k
  new (cache) hb_ot_font_advance_cache_t;
98
1.30k
  return cache;
99
1.39k
      }
100
5.15k
      if (advance_cache.cmpexch (cache, nullptr))
101
5.15k
        return cache;
102
0
      else
103
0
        goto retry;
104
5.15k
    }
105
    void release_advance_cache (hb_ot_font_advance_cache_t *cache) const
106
6.45k
    {
107
6.45k
      if (!cache)
108
0
        return;
109
6.45k
      if (!advance_cache.cmpexch (nullptr, cache))
110
0
        hb_free (cache);
111
6.45k
    }
112
    void clear_advance_cache () const
113
91.1k
    {
114
91.1k
    retry:
115
91.1k
      auto *cache = advance_cache.get_acquire ();
116
91.1k
      if (!cache)
117
89.8k
  return;
118
1.30k
      if (advance_cache.cmpexch (cache, nullptr))
119
1.30k
  hb_free (cache);
120
0
      else
121
0
        goto retry;
122
1.30k
    }
123
124
    OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
125
945
    {
126
945
    retry:
127
945
      auto *cache = varStore_cache.get_acquire ();
128
945
      if (!cache)
129
221
  return varStore.create_cache ();
130
724
      if (varStore_cache.cmpexch (cache, nullptr))
131
724
  return cache;
132
0
      else
133
0
  goto retry;
134
724
    }
135
    void release_varStore_cache (OT::hb_scalar_cache_t *cache) const
136
945
    {
137
945
      if (!cache)
138
0
  return;
139
945
      if (!varStore_cache.cmpexch (nullptr, cache))
140
0
  OT::ItemVariationStore::destroy_cache (cache);
141
945
    }
142
    void clear_varStore_cache () const
143
91.1k
    {
144
91.1k
    retry:
145
91.1k
      auto *cache = varStore_cache.get_acquire ();
146
91.1k
      if (!cache)
147
90.8k
  return;
148
221
      if (varStore_cache.cmpexch (cache, nullptr))
149
221
  OT::ItemVariationStore::destroy_cache (cache);
150
0
      else
151
0
  goto retry;
152
221
    }
153
154
    void clear () const
155
91.1k
    {
156
91.1k
      clear_advance_cache ();
157
91.1k
      clear_varStore_cache ();
158
91.1k
    }
159
160
  } h, v;
161
162
  struct origin_cache_t
163
  {
164
    mutable hb_atomic_t<hb_ot_font_origin_cache_t *> origin_cache;
165
    mutable hb_atomic_t<OT::hb_scalar_cache_t *> varStore_cache;
166
167
    ~origin_cache_t ()
168
42.7k
    {
169
42.7k
      clear ();
170
42.7k
    }
171
172
    hb_ot_font_origin_cache_t *acquire_origin_cache () const
173
42.7k
    {
174
42.7k
    retry:
175
42.7k
      auto *cache = origin_cache.get_acquire ();
176
42.7k
      if (!cache)
177
42.7k
      {
178
42.7k
        cache = (hb_ot_font_origin_cache_t *) hb_malloc (sizeof (hb_ot_font_origin_cache_t));
179
42.7k
  if (!cache)
180
528
    return nullptr;
181
42.2k
  new (cache) hb_ot_font_origin_cache_t;
182
42.2k
  return cache;
183
42.7k
      }
184
0
      if (origin_cache.cmpexch (cache, nullptr))
185
0
        return cache;
186
0
      else
187
0
        goto retry;
188
0
    }
189
    void release_origin_cache (hb_ot_font_origin_cache_t *cache) const
190
42.7k
    {
191
42.7k
      if (!cache)
192
528
        return;
193
42.2k
      if (!origin_cache.cmpexch (nullptr, cache))
194
0
        hb_free (cache);
195
42.2k
    }
196
    void clear_origin_cache () const
197
45.5k
    {
198
45.5k
    retry:
199
45.5k
      auto *cache = origin_cache.get_acquire ();
200
45.5k
      if (!cache)
201
3.29k
  return;
202
42.2k
      if (origin_cache.cmpexch (cache, nullptr))
203
42.2k
  hb_free (cache);
204
0
      else
205
0
        goto retry;
206
42.2k
    }
207
208
    OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
209
91
    {
210
91
    retry:
211
91
      auto *cache = varStore_cache.get_acquire ();
212
91
      if (!cache)
213
91
  return varStore.create_cache ();
214
0
      if (varStore_cache.cmpexch (cache, nullptr))
215
0
  return cache;
216
0
      else
217
0
  goto retry;
218
0
    }
219
    void release_varStore_cache (OT::hb_scalar_cache_t *cache) const
220
91
    {
221
91
      if (!cache)
222
0
  return;
223
91
      if (!varStore_cache.cmpexch (nullptr, cache))
224
0
  OT::ItemVariationStore::destroy_cache (cache);
225
91
    }
226
    void clear_varStore_cache () const
227
45.5k
    {
228
45.5k
    retry:
229
45.5k
      auto *cache = varStore_cache.get_acquire ();
230
45.5k
      if (!cache)
231
45.4k
  return;
232
91
      if (varStore_cache.cmpexch (cache, nullptr))
233
91
  OT::ItemVariationStore::destroy_cache (cache);
234
0
      else
235
0
  goto retry;
236
91
    }
237
238
    void clear () const
239
45.5k
    {
240
45.5k
      clear_origin_cache ();
241
45.5k
      clear_varStore_cache ();
242
45.5k
    }
243
  } v_origin;
244
245
  struct draw_cache_t
246
  {
247
    mutable hb_atomic_t<OT::hb_scalar_cache_t *> gvar_cache;
248
249
    ~draw_cache_t ()
250
42.7k
    {
251
42.7k
      clear ();
252
42.7k
    }
253
254
    OT::hb_scalar_cache_t *acquire_gvar_cache (const OT::gvar_accelerator_t &gvar) const
255
18.2k
    {
256
18.2k
    retry:
257
18.2k
      auto *cache = gvar_cache.get_acquire ();
258
18.2k
      if (!cache)
259
2.76k
  return gvar.create_cache ();
260
15.5k
      if (gvar_cache.cmpexch (cache, nullptr))
261
15.5k
  return cache;
262
0
      else
263
0
  goto retry;
264
15.5k
    }
265
    void release_gvar_cache (OT::hb_scalar_cache_t *cache) const
266
742k
    {
267
742k
      if (!cache)
268
724k
  return;
269
18.2k
      if (!gvar_cache.cmpexch (nullptr, cache))
270
0
  OT::gvar_accelerator_t::destroy_cache (cache);
271
18.2k
    }
272
    void clear_gvar_cache () const
273
45.5k
    {
274
45.5k
    retry:
275
45.5k
      auto *cache = gvar_cache.get_acquire ();
276
45.5k
      if (!cache)
277
42.7k
  return;
278
2.76k
      if (gvar_cache.cmpexch (cache, nullptr))
279
2.76k
  OT::gvar_accelerator_t::destroy_cache (cache);
280
0
      else
281
0
  goto retry;
282
2.76k
    }
283
284
    void clear () const
285
45.5k
    {
286
45.5k
      clear_gvar_cache ();
287
45.5k
    }
288
  } draw;
289
290
  void check_serial (hb_font_t *font) const
291
21.5k
  {
292
21.5k
    int font_serial = font->serial_coords.get_acquire ();
293
21.5k
    if (cached_serial.get_acquire () != font_serial)
294
2.76k
    {
295
      /* These caches are dependent on scale and synthetic settings.
296
       * Any change to the font invalidates them. */
297
2.76k
      v_origin.clear ();
298
299
2.76k
      cached_serial.set_release (font_serial);
300
2.76k
    }
301
302
21.5k
    int font_serial_coords = font->serial_coords.get_acquire ();
303
21.5k
    if (cached_coords_serial.get_acquire () != font_serial_coords)
304
2.76k
    {
305
      /* These caches are independent of scale or synthetic settings.
306
       * Just variation changes will invalidate them. */
307
2.76k
      h.clear ();
308
2.76k
      v.clear ();
309
2.76k
      draw.clear ();
310
311
2.76k
      cached_coords_serial.set_release (font_serial_coords);
312
2.76k
    }
313
21.5k
  }
314
};
315
316
static hb_ot_font_t *
317
_hb_ot_font_create (hb_font_t *font)
318
43.3k
{
319
43.3k
  hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
320
43.3k
  if (unlikely (!ot_font))
321
578
    return nullptr;
322
323
42.7k
  ot_font->ot_face = &font->face->table;
324
325
42.7k
  return ot_font;
326
43.3k
}
327
328
static void
329
_hb_ot_font_destroy (void *font_data)
330
42.7k
{
331
42.7k
  hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
332
333
42.7k
  ot_font->~hb_ot_font_t ();
334
335
42.7k
  hb_free (ot_font);
336
42.7k
}
337
338
static hb_bool_t
339
hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
340
       void *font_data,
341
       hb_codepoint_t unicode,
342
       hb_codepoint_t *glyph,
343
       void *user_data HB_UNUSED)
344
2.26M
{
345
2.26M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
346
2.26M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
347
2.26M
  return ot_face->cmap->get_nominal_glyph (unicode, glyph);
348
2.26M
}
349
350
static unsigned int
351
hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
352
        void *font_data,
353
        unsigned int count,
354
        const hb_codepoint_t *first_unicode,
355
        unsigned int unicode_stride,
356
        hb_codepoint_t *first_glyph,
357
        unsigned int glyph_stride,
358
        void *user_data HB_UNUSED)
359
130k
{
360
130k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
361
130k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
362
130k
  return ot_face->cmap->get_nominal_glyphs (count,
363
130k
              first_unicode, unicode_stride,
364
130k
              first_glyph, glyph_stride);
365
130k
}
366
367
static hb_bool_t
368
hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
369
         void *font_data,
370
         hb_codepoint_t unicode,
371
         hb_codepoint_t variation_selector,
372
         hb_codepoint_t *glyph,
373
         void *user_data HB_UNUSED)
374
44.8k
{
375
44.8k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
376
44.8k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
377
44.8k
  return ot_face->cmap->get_variation_glyph (unicode,
378
44.8k
                                             variation_selector, glyph);
379
44.8k
}
380
381
static void
382
hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
383
          unsigned count,
384
          const hb_codepoint_t *first_glyph,
385
          unsigned glyph_stride,
386
          hb_position_t *first_advance,
387
          unsigned advance_stride,
388
          void *user_data HB_UNUSED)
389
260k
{
390
  // Duplicated in v_advances. Ugly. Keep in sync'ish.
391
392
260k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
393
260k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
394
260k
  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
395
396
260k
  if (unlikely (!hmtx.has_data ()))
397
247k
  {
398
247k
    hb_position_t advance = font->face->get_upem () / 2;
399
247k
    advance = font->em_scale_x (advance);
400
60.6M
    for (unsigned int i = 0; i < count; i++)
401
60.3M
    {
402
60.3M
      *first_advance = advance;
403
60.3M
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
404
60.3M
    }
405
247k
    return;
406
247k
  }
407
408
12.5k
#ifndef HB_NO_VAR
409
12.5k
  if (!font->has_nonzero_coords)
410
6.29k
  {
411
8.73k
  fallback:
412
#else
413
  {
414
#endif
415
    // Just plain htmx data. No need to cache.
416
1.35M
    for (unsigned int i = 0; i < count; i++)
417
1.34M
    {
418
1.34M
      *first_advance = font->em_scale_x (hmtx.get_advance_without_var_unscaled (*first_glyph));
419
1.34M
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
420
1.34M
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
421
1.34M
    }
422
8.73k
    return;
423
6.29k
  }
424
425
6.23k
#ifndef HB_NO_VAR
426
  /* has_nonzero_coords. */
427
428
6.23k
  ot_font->check_serial (font);
429
6.23k
  hb_ot_font_advance_cache_t *advance_cache = ot_font->h.acquire_advance_cache ();
430
6.23k
  if (!advance_cache)
431
82
  {
432
    // malloc failure. Just use the fallback non-variable path.
433
82
    goto fallback;
434
82
  }
435
436
  /* If HVAR is present, use it.*/
437
6.15k
  const OT::HVAR &HVAR = *hmtx.var_table;
438
6.15k
  if (HVAR.has_data ())
439
879
  {
440
879
    const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
441
879
    OT::hb_scalar_cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore);
442
443
6.34k
    for (unsigned int i = 0; i < count; i++)
444
5.46k
    {
445
5.46k
      hb_position_t v;
446
5.46k
      unsigned cv;
447
5.46k
      if (advance_cache->get (*first_glyph, &cv))
448
3.60k
  v = cv;
449
1.86k
      else
450
1.86k
      {
451
1.86k
        v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
452
1.86k
  advance_cache->set (*first_glyph, v);
453
1.86k
      }
454
5.46k
      *first_advance = font->em_scale_x (v);
455
5.46k
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
456
5.46k
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
457
5.46k
    }
458
459
879
    ot_font->h.release_varStore_cache (varStore_cache);
460
879
    ot_font->h.release_advance_cache (advance_cache);
461
879
    return;
462
879
  }
463
464
5.27k
  const auto &gvar = *ot_face->gvar;
465
5.27k
  if (gvar.has_data ())
466
2.98k
  {
467
2.98k
    const auto &glyf = *ot_face->glyf;
468
2.98k
    auto *scratch = glyf.acquire_scratch ();
469
2.98k
    if (unlikely (!scratch))
470
65
    {
471
65
      ot_font->h.release_advance_cache (advance_cache);
472
65
      goto fallback;
473
65
    }
474
2.91k
    OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
475
476
20.4k
    for (unsigned int i = 0; i < count; i++)
477
17.5k
    {
478
17.5k
      hb_position_t v;
479
17.5k
      unsigned cv;
480
17.5k
      if (advance_cache->get (*first_glyph, &cv))
481
11.6k
  v = cv;
482
5.94k
      else
483
5.94k
      {
484
5.94k
        v = glyf.get_advance_with_var_unscaled (*first_glyph, font, false, *scratch, gvar_cache);
485
5.94k
  advance_cache->set (*first_glyph, v);
486
5.94k
      }
487
17.5k
      *first_advance = font->em_scale_x (v);
488
17.5k
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
489
17.5k
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
490
17.5k
    }
491
492
2.91k
    ot_font->draw.release_gvar_cache (gvar_cache);
493
2.91k
    glyf.release_scratch (scratch);
494
2.91k
    ot_font->h.release_advance_cache (advance_cache);
495
2.91k
    return;
496
2.98k
  }
497
498
2.29k
  ot_font->h.release_advance_cache (advance_cache);
499
  // No HVAR or GVAR.  Just use the fallback non-variable path.
500
2.29k
  goto fallback;
501
5.27k
#endif
502
5.27k
}
503
504
#ifndef HB_NO_VERTICAL
505
static void
506
hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
507
          unsigned count,
508
          const hb_codepoint_t *first_glyph,
509
          unsigned glyph_stride,
510
          hb_position_t *first_advance,
511
          unsigned advance_stride,
512
          void *user_data HB_UNUSED)
513
42.7k
{
514
  // Duplicated from h_advances. Ugly. Keep in sync'ish.
515
516
42.7k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
517
42.7k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
518
42.7k
  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
519
520
42.7k
  if (unlikely (!vmtx.has_data ()))
521
42.3k
  {
522
42.3k
    hb_font_extents_t font_extents;
523
42.3k
    font->get_h_extents_with_fallback (&font_extents);
524
42.3k
    hb_position_t advance = font_extents.descender - font_extents.ascender;
525
84.7k
    for (unsigned int i = 0; i < count; i++)
526
42.3k
    {
527
42.3k
      *first_advance = advance;
528
42.3k
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
529
42.3k
    }
530
42.3k
    return;
531
42.3k
  }
532
533
388
#ifndef HB_NO_VAR
534
388
  if (!font->has_nonzero_coords)
535
83
  {
536
152
  fallback:
537
#else
538
  {
539
#endif
540
    // Just plain vtmx data. No need to cache.
541
304
    for (unsigned int i = 0; i < count; i++)
542
152
    {
543
152
      *first_advance = font->em_scale_y (- (int) vmtx.get_advance_without_var_unscaled (*first_glyph));
544
152
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
545
152
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
546
152
    }
547
152
    return;
548
83
  }
549
550
305
#ifndef HB_NO_VAR
551
  /* has_nonzero_coords. */
552
553
305
  ot_font->check_serial (font);
554
305
  hb_ot_font_advance_cache_t *advance_cache = ot_font->v.acquire_advance_cache ();
555
305
  if (!advance_cache)
556
4
  {
557
    // malloc failure. Just use the fallback non-variable path.
558
4
    goto fallback;
559
4
  }
560
561
  /* If VVAR is present, use it.*/
562
301
  const OT::VVAR &VVAR = *vmtx.var_table;
563
301
  if (VVAR.has_data ())
564
66
  {
565
66
    const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
566
66
    OT::hb_scalar_cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore);
567
568
132
    for (unsigned int i = 0; i < count; i++)
569
66
    {
570
66
      hb_position_t v;
571
66
      unsigned cv;
572
66
      if (advance_cache->get (*first_glyph, &cv))
573
0
  v = cv;
574
66
      else
575
66
      {
576
66
        v = vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
577
66
  advance_cache->set (*first_glyph, v);
578
66
      }
579
66
      *first_advance = font->em_scale_y (- (int) v);
580
66
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
581
66
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
582
66
    }
583
584
66
    ot_font->v.release_varStore_cache (varStore_cache);
585
66
    ot_font->v.release_advance_cache (advance_cache);
586
66
    return;
587
66
  }
588
589
235
  const auto &gvar = *ot_face->gvar;
590
235
  if (gvar.has_data ())
591
174
  {
592
174
    const auto &glyf = *ot_face->glyf;
593
174
    auto *scratch = glyf.acquire_scratch ();
594
174
    if (unlikely (!scratch))
595
4
    {
596
4
      ot_font->v.release_advance_cache (advance_cache);
597
4
      goto fallback;
598
4
    }
599
170
    OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
600
601
340
    for (unsigned int i = 0; i < count; i++)
602
170
    {
603
170
      hb_position_t v;
604
170
      unsigned cv;
605
170
      if (advance_cache->get (*first_glyph, &cv))
606
0
  v = cv;
607
170
      else
608
170
      {
609
170
        v = glyf.get_advance_with_var_unscaled (*first_glyph, font, true, *scratch, gvar_cache);
610
170
  advance_cache->set (*first_glyph, v);
611
170
      }
612
170
      *first_advance = font->em_scale_y (- (int) v);
613
170
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
614
170
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
615
170
    }
616
617
170
    ot_font->draw.release_gvar_cache (gvar_cache);
618
170
    glyf.release_scratch (scratch);
619
170
    ot_font->v.release_advance_cache (advance_cache);
620
170
    return;
621
174
  }
622
623
61
  ot_font->v.release_advance_cache (advance_cache);
624
  // No VVAR or GVAR.  Just use the fallback non-variable path.
625
61
  goto fallback;
626
235
#endif
627
235
}
628
#endif
629
630
#ifndef HB_NO_VERTICAL
631
HB_HOT
632
static hb_bool_t
633
hb_ot_get_glyph_v_origins (hb_font_t *font,
634
         void *font_data,
635
         unsigned int count,
636
         const hb_codepoint_t *first_glyph,
637
         unsigned glyph_stride,
638
         hb_position_t *first_x,
639
         unsigned x_stride,
640
         hb_position_t *first_y,
641
         unsigned y_stride,
642
         void *user_data HB_UNUSED)
643
42.7k
{
644
42.7k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
645
42.7k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
646
647
  /* First, set all the x values to half the advance width. */
648
42.7k
  font->get_glyph_h_advances (count,
649
42.7k
            first_glyph, glyph_stride,
650
42.7k
            first_x, x_stride);
651
85.5k
  for (unsigned i = 0; i < count; i++)
652
42.7k
  {
653
42.7k
    *first_x /= 2;
654
42.7k
    first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
655
42.7k
  }
656
657
  /* The vertical origin business is messy...
658
   *
659
   * We allocate the cache, then have various code paths that use the cache.
660
   * Each one is responsible to free it before returning.
661
   */
662
42.7k
  hb_ot_font_origin_cache_t *origin_cache = ot_font->v_origin.acquire_origin_cache ();
663
664
  /* If there is VORG, always use it. It uses VVAR for variations if necessary. */
665
42.7k
  const OT::VORG &VORG = *ot_face->VORG;
666
42.7k
  if (origin_cache && VORG.has_data ())
667
178
  {
668
178
#ifndef HB_NO_VAR
669
178
    if (!font->has_nonzero_coords)
670
87
#endif
671
87
    {
672
174
      for (unsigned i = 0; i < count; i++)
673
87
      {
674
87
  hb_position_t origin;
675
87
  unsigned cv;
676
87
  if (origin_cache->get (*first_glyph, &cv))
677
0
    origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
678
87
  else
679
87
  {
680
87
    origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph));
681
87
    origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
682
87
  }
683
684
87
  *first_y = origin;
685
686
87
  first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
687
87
  first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
688
87
      }
689
87
    }
690
91
#ifndef HB_NO_VAR
691
91
    else
692
91
    {
693
91
      const OT::VVAR &VVAR = *ot_face->vmtx->var_table;
694
91
      const auto &varStore = &VVAR + VVAR.varStore;
695
91
      auto *varStore_cache = ot_font->v_origin.acquire_varStore_cache (varStore);
696
182
      for (unsigned i = 0; i < count; i++)
697
91
      {
698
91
  hb_position_t origin;
699
91
  unsigned cv;
700
91
  if (origin_cache->get (*first_glyph, &cv))
701
0
    origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
702
91
  else
703
91
  {
704
91
    origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph) +
705
91
              VVAR.get_vorg_delta_unscaled (*first_glyph,
706
91
                    font->coords, font->num_coords,
707
91
                    varStore_cache));
708
91
    origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
709
91
  }
710
711
91
  *first_y = origin;
712
713
91
  first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
714
91
  first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
715
91
      }
716
91
      ot_font->v_origin.release_varStore_cache (varStore_cache);
717
91
    }
718
178
#endif
719
178
    ot_font->v_origin.release_origin_cache (origin_cache);
720
178
    return true;
721
178
  }
722
723
  /* If and only if `vmtx` is present and it's a `glyf` font,
724
   * we use the top phantom point, deduced from vmtx,glyf[,gvar]. */
725
42.6k
  const auto &vmtx = *ot_face->vmtx;
726
42.6k
  const auto &glyf = *ot_face->glyf;
727
42.6k
  if (origin_cache && vmtx.has_data() && glyf.has_data ())
728
244
  {
729
244
    auto *scratch = glyf.acquire_scratch ();
730
244
    if (unlikely (!scratch))
731
3
    {
732
3
      ot_font->v_origin.release_origin_cache (origin_cache);
733
3
      return false;
734
3
    }
735
241
    OT::hb_scalar_cache_t *gvar_cache = font->has_nonzero_coords ?
736
203
          ot_font->draw.acquire_gvar_cache (*ot_face->gvar) :
737
241
          nullptr;
738
739
482
    for (unsigned i = 0; i < count; i++)
740
241
    {
741
241
      hb_position_t origin;
742
241
      unsigned cv;
743
241
      if (origin_cache->get (*first_glyph, &cv))
744
0
  origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
745
241
      else
746
241
      {
747
241
  origin = font->em_scalef_y (glyf.get_v_origin_with_var_unscaled (*first_glyph, font, *scratch, gvar_cache));
748
241
  origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
749
241
      }
750
751
241
      *first_y = origin;
752
753
241
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
754
241
      first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
755
241
    }
756
757
241
    if (gvar_cache)
758
203
      ot_font->draw.release_gvar_cache (gvar_cache);
759
241
    glyf.release_scratch (scratch);
760
241
    ot_font->v_origin.release_origin_cache (origin_cache);
761
241
    return true;
762
244
  }
763
764
  /* Otherwise, use glyph extents to center the glyph vertically.
765
   * If getting glyph extents failed, just use the font ascender. */
766
42.3k
  if (origin_cache && font->has_glyph_extents_func ())
767
41.8k
  {
768
41.8k
    hb_font_extents_t font_extents;
769
41.8k
    font->get_h_extents_with_fallback (&font_extents);
770
41.8k
    hb_position_t font_advance = font_extents.ascender - font_extents.descender;
771
772
83.6k
    for (unsigned i = 0; i < count; i++)
773
41.8k
    {
774
41.8k
      hb_position_t origin;
775
41.8k
      unsigned cv;
776
777
41.8k
      if (origin_cache->get (*first_glyph, &cv))
778
0
  origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
779
41.8k
      else
780
41.8k
      {
781
41.8k
  hb_glyph_extents_t extents = {0};
782
41.8k
  if (likely (font->get_glyph_extents (*first_glyph, &extents)))
783
2.36k
    origin = extents.y_bearing + ((font_advance - -extents.height) >> 1);
784
39.4k
  else
785
39.4k
    origin = font_extents.ascender;
786
787
41.8k
  origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
788
41.8k
      }
789
790
41.8k
      *first_y = origin;
791
792
41.8k
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
793
41.8k
      first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
794
41.8k
    }
795
41.8k
  }
796
797
42.3k
  ot_font->v_origin.release_origin_cache (origin_cache);
798
42.3k
  return true;
799
42.6k
}
800
#endif
801
802
static hb_bool_t
803
hb_ot_get_glyph_extents (hb_font_t *font,
804
       void *font_data,
805
       hb_codepoint_t glyph,
806
       hb_glyph_extents_t *extents,
807
       void *user_data HB_UNUSED)
808
1.22M
{
809
1.22M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
810
1.22M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
811
812
1.22M
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
813
1.22M
  if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
814
1.22M
  if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
815
1.22M
#endif
816
1.22M
#if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
817
1.22M
  if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
818
1.21M
#endif
819
1.21M
#ifndef HB_NO_VAR_COMPOSITES
820
1.21M
  if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
821
1.21M
#endif
822
1.21M
  if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
823
1.15M
#ifndef HB_NO_OT_FONT_CFF
824
1.15M
  if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
825
1.15M
  if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
826
1.15M
#endif
827
828
1.15M
  return false;
829
1.15M
}
830
831
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
832
static hb_bool_t
833
hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
834
          void *font_data,
835
          hb_codepoint_t glyph,
836
          char *name, unsigned int size,
837
          void *user_data HB_UNUSED)
838
42.7k
{
839
42.7k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
840
42.7k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
841
842
42.7k
  if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
843
42.4k
#ifndef HB_NO_OT_FONT_CFF
844
42.4k
  if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
845
41.4k
#endif
846
41.4k
  return false;
847
42.4k
}
848
static hb_bool_t
849
hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
850
         void *font_data,
851
         const char *name, int len,
852
         hb_codepoint_t *glyph,
853
         void *user_data HB_UNUSED)
854
42.7k
{
855
42.7k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
856
42.7k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
857
858
42.7k
  if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
859
42.7k
#ifndef HB_NO_OT_FONT_CFF
860
42.7k
    if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
861
42.6k
#endif
862
42.6k
  return false;
863
42.7k
}
864
#endif
865
866
static hb_bool_t
867
hb_ot_get_font_h_extents (hb_font_t *font,
868
        void *font_data HB_UNUSED,
869
        hb_font_extents_t *metrics,
870
        void *user_data HB_UNUSED)
871
84.2k
{
872
84.2k
  return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
873
4.36k
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
874
4.36k
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
875
84.2k
}
876
877
#ifndef HB_NO_VERTICAL
878
static hb_bool_t
879
hb_ot_get_font_v_extents (hb_font_t *font,
880
        void *font_data HB_UNUSED,
881
        hb_font_extents_t *metrics,
882
        void *user_data HB_UNUSED)
883
0
{
884
0
  return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_ASCENDER, &metrics->ascender) &&
885
0
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) &&
886
0
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
887
0
}
888
#endif
889
890
#ifndef HB_NO_DRAW
891
static hb_bool_t
892
hb_ot_draw_glyph_or_fail (hb_font_t *font,
893
        void *font_data HB_UNUSED,
894
        hb_codepoint_t glyph,
895
        hb_draw_funcs_t *draw_funcs, void *draw_data,
896
        void *user_data)
897
739k
{
898
739k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
899
739k
  hb_draw_session_t draw_session {draw_funcs, draw_data};
900
739k
  bool ret = false;
901
902
739k
  OT::hb_scalar_cache_t *gvar_cache = nullptr;
903
739k
  if (font->num_coords)
904
15.0k
  {
905
15.0k
    ot_font->check_serial (font);
906
15.0k
    gvar_cache = ot_font->draw.acquire_gvar_cache (*ot_font->ot_face->gvar);
907
15.0k
  }
908
909
739k
#ifndef HB_NO_VAR_COMPOSITES
910
739k
  if (font->face->table.VARC->get_path (font, glyph, draw_session)) { ret = true; goto done; }
911
738k
#endif
912
  // Keep the following in synch with VARC::get_path_at()
913
738k
  if (font->face->table.glyf->get_path (font, glyph, draw_session, gvar_cache)) { ret = true; goto done; }
914
915
734k
#ifndef HB_NO_CFF
916
734k
  if (font->face->table.cff2->get_path (font, glyph, draw_session)) { ret = true; goto done; }
917
734k
  if (font->face->table.cff1->get_path (font, glyph, draw_session)) { ret = true; goto done; }
918
734k
#endif
919
920
739k
done:
921
922
739k
  ot_font->draw.release_gvar_cache (gvar_cache);
923
924
739k
  return ret;
925
734k
}
926
#endif
927
928
#ifndef HB_NO_PAINT
929
static hb_bool_t
930
hb_ot_paint_glyph_or_fail (hb_font_t *font,
931
         void *font_data,
932
         hb_codepoint_t glyph,
933
         hb_paint_funcs_t *paint_funcs, void *paint_data,
934
         unsigned int palette,
935
         hb_color_t foreground,
936
         void *user_data)
937
550k
{
938
550k
#ifndef HB_NO_COLOR
939
550k
  if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true;
940
550k
  if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
941
550k
#ifndef HB_NO_OT_FONT_BITMAP
942
550k
  if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
943
550k
  if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
944
550k
#endif
945
550k
#endif
946
550k
  return false;
947
550k
}
948
#endif
949
950
static inline void free_static_ot_funcs ();
951
952
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
953
{
954
  static hb_font_funcs_t *create ()
955
1
  {
956
1
    hb_font_funcs_t *funcs = hb_font_funcs_create ();
957
958
1
    hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
959
1
    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
960
1
    hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
961
962
1
    hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
963
1
    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
964
965
1
#ifndef HB_NO_VERTICAL
966
1
    hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
967
1
    hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
968
1
    hb_font_funcs_set_glyph_v_origins_func (funcs, hb_ot_get_glyph_v_origins, nullptr, nullptr);
969
1
#endif
970
971
1
#ifndef HB_NO_DRAW
972
1
    hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ot_draw_glyph_or_fail, nullptr, nullptr);
973
1
#endif
974
975
1
#ifndef HB_NO_PAINT
976
1
    hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ot_paint_glyph_or_fail, nullptr, nullptr);
977
1
#endif
978
979
1
    hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
980
    //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
981
982
1
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
983
1
    hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
984
1
    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
985
1
#endif
986
987
1
    hb_font_funcs_make_immutable (funcs);
988
989
1
    hb_atexit (free_static_ot_funcs);
990
991
1
    return funcs;
992
1
  }
993
} static_ot_funcs;
994
995
static inline
996
void free_static_ot_funcs ()
997
1
{
998
1
  static_ot_funcs.free_instance ();
999
1
}
1000
1001
static hb_font_funcs_t *
1002
_hb_ot_get_font_funcs ()
1003
42.7k
{
1004
42.7k
  return static_ot_funcs.get_unconst ();
1005
42.7k
}
1006
1007
1008
/**
1009
 * hb_ot_font_set_funcs:
1010
 * @font: #hb_font_t to work upon
1011
 *
1012
 * Sets the font functions to use when working with @font to
1013
 * the HarfBuzz's native implementation. This is the default
1014
 * for fonts newly created.
1015
 *
1016
 * Since: 0.9.28
1017
 **/
1018
void
1019
hb_ot_font_set_funcs (hb_font_t *font)
1020
43.3k
{
1021
43.3k
  hb_ot_font_t *ot_font = _hb_ot_font_create (font);
1022
43.3k
  if (unlikely (!ot_font))
1023
578
    return;
1024
1025
42.7k
  hb_font_set_funcs (font,
1026
42.7k
         _hb_ot_get_font_funcs (),
1027
42.7k
         ot_font,
1028
42.7k
         _hb_ot_font_destroy);
1029
42.7k
}
1030
1031
#endif