Coverage Report

Created: 2025-12-31 06:47

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
137k
    {
85
137k
      clear ();
86
137k
    }
87
88
    hb_ot_font_advance_cache_t *acquire_advance_cache () const
89
48.3k
    {
90
48.3k
    retry:
91
48.3k
      auto *cache = advance_cache.get_acquire ();
92
48.3k
      if (!cache)
93
2.80k
      {
94
2.80k
        cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
95
2.80k
  if (!cache)
96
155
    return nullptr;
97
2.65k
  new (cache) hb_ot_font_advance_cache_t;
98
2.65k
  return cache;
99
2.80k
      }
100
45.5k
      if (advance_cache.cmpexch (cache, nullptr))
101
45.5k
        return cache;
102
0
      else
103
0
        goto retry;
104
45.5k
    }
105
    void release_advance_cache (hb_ot_font_advance_cache_t *cache) const
106
48.1k
    {
107
48.1k
      if (!cache)
108
0
        return;
109
48.1k
      if (!advance_cache.cmpexch (nullptr, cache))
110
0
        hb_free (cache);
111
48.1k
    }
112
    void clear_advance_cache () const
113
150k
    {
114
150k
    retry:
115
150k
      auto *cache = advance_cache.get_acquire ();
116
150k
      if (!cache)
117
147k
  return;
118
2.65k
      if (advance_cache.cmpexch (cache, nullptr))
119
2.65k
  hb_free (cache);
120
0
      else
121
0
        goto retry;
122
2.65k
    }
123
124
    OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
125
8.89k
    {
126
8.89k
    retry:
127
8.89k
      auto *cache = varStore_cache.get_acquire ();
128
8.89k
      if (!cache)
129
495
  return varStore.create_cache ();
130
8.40k
      if (varStore_cache.cmpexch (cache, nullptr))
131
8.40k
  return cache;
132
0
      else
133
0
  goto retry;
134
8.40k
    }
135
    void release_varStore_cache (OT::hb_scalar_cache_t *cache) const
136
8.89k
    {
137
8.89k
      if (!cache)
138
0
  return;
139
8.89k
      if (!varStore_cache.cmpexch (nullptr, cache))
140
0
  OT::ItemVariationStore::destroy_cache (cache);
141
8.89k
    }
142
    void clear_varStore_cache () const
143
150k
    {
144
150k
    retry:
145
150k
      auto *cache = varStore_cache.get_acquire ();
146
150k
      if (!cache)
147
149k
  return;
148
495
      if (varStore_cache.cmpexch (cache, nullptr))
149
495
  OT::ItemVariationStore::destroy_cache (cache);
150
0
      else
151
0
  goto retry;
152
495
    }
153
154
    void clear () const
155
150k
    {
156
150k
      clear_advance_cache ();
157
150k
      clear_varStore_cache ();
158
150k
    }
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
68.9k
    {
169
68.9k
      clear ();
170
68.9k
    }
171
172
    hb_ot_font_origin_cache_t *acquire_origin_cache () const
173
245k
    {
174
245k
    retry:
175
245k
      auto *cache = origin_cache.get_acquire ();
176
245k
      if (!cache)
177
67.5k
      {
178
67.5k
        cache = (hb_ot_font_origin_cache_t *) hb_malloc (sizeof (hb_ot_font_origin_cache_t));
179
67.5k
  if (!cache)
180
1.52k
    return nullptr;
181
65.9k
  new (cache) hb_ot_font_origin_cache_t;
182
65.9k
  return cache;
183
67.5k
      }
184
178k
      if (origin_cache.cmpexch (cache, nullptr))
185
178k
        return cache;
186
0
      else
187
0
        goto retry;
188
178k
    }
189
    void release_origin_cache (hb_ot_font_origin_cache_t *cache) const
190
245k
    {
191
245k
      if (!cache)
192
1.52k
        return;
193
244k
      if (!origin_cache.cmpexch (nullptr, cache))
194
0
        hb_free (cache);
195
244k
    }
196
    void clear_origin_cache () const
197
75.0k
    {
198
75.0k
    retry:
199
75.0k
      auto *cache = origin_cache.get_acquire ();
200
75.0k
      if (!cache)
201
9.02k
  return;
202
65.9k
      if (origin_cache.cmpexch (cache, nullptr))
203
65.9k
  hb_free (cache);
204
0
      else
205
0
        goto retry;
206
65.9k
    }
207
208
    OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
209
1.21k
    {
210
1.21k
    retry:
211
1.21k
      auto *cache = varStore_cache.get_acquire ();
212
1.21k
      if (!cache)
213
229
  return varStore.create_cache ();
214
990
      if (varStore_cache.cmpexch (cache, nullptr))
215
990
  return cache;
216
0
      else
217
0
  goto retry;
218
990
    }
219
    void release_varStore_cache (OT::hb_scalar_cache_t *cache) const
220
1.21k
    {
221
1.21k
      if (!cache)
222
0
  return;
223
1.21k
      if (!varStore_cache.cmpexch (nullptr, cache))
224
0
  OT::ItemVariationStore::destroy_cache (cache);
225
1.21k
    }
226
    void clear_varStore_cache () const
227
75.0k
    {
228
75.0k
    retry:
229
75.0k
      auto *cache = varStore_cache.get_acquire ();
230
75.0k
      if (!cache)
231
74.7k
  return;
232
229
      if (varStore_cache.cmpexch (cache, nullptr))
233
229
  OT::ItemVariationStore::destroy_cache (cache);
234
0
      else
235
0
  goto retry;
236
229
    }
237
238
    void clear () const
239
75.0k
    {
240
75.0k
      clear_origin_cache ();
241
75.0k
      clear_varStore_cache ();
242
75.0k
    }
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
68.9k
    {
251
68.9k
      clear ();
252
68.9k
    }
253
254
    OT::hb_scalar_cache_t *acquire_gvar_cache (const OT::gvar_accelerator_t &gvar) const
255
162k
    {
256
162k
    retry:
257
162k
      auto *cache = gvar_cache.get_acquire ();
258
162k
      if (!cache)
259
6.07k
  return gvar.create_cache ();
260
156k
      if (gvar_cache.cmpexch (cache, nullptr))
261
156k
  return cache;
262
0
      else
263
0
  goto retry;
264
156k
    }
265
    void release_gvar_cache (OT::hb_scalar_cache_t *cache) const
266
1.79M
    {
267
1.79M
      if (!cache)
268
1.63M
  return;
269
162k
      if (!gvar_cache.cmpexch (nullptr, cache))
270
0
  OT::gvar_accelerator_t::destroy_cache (cache);
271
162k
    }
272
    void clear_gvar_cache () const
273
75.0k
    {
274
75.0k
    retry:
275
75.0k
      auto *cache = gvar_cache.get_acquire ();
276
75.0k
      if (!cache)
277
68.9k
  return;
278
6.07k
      if (gvar_cache.cmpexch (cache, nullptr))
279
6.07k
  OT::gvar_accelerator_t::destroy_cache (cache);
280
0
      else
281
0
  goto retry;
282
6.07k
    }
283
284
    void clear () const
285
75.0k
    {
286
75.0k
      clear_gvar_cache ();
287
75.0k
    }
288
  } draw;
289
290
  void check_serial (hb_font_t *font) const
291
190k
  {
292
190k
    int font_serial = font->serial_coords.get_acquire ();
293
190k
    if (cached_serial.get_acquire () != font_serial)
294
6.07k
    {
295
      /* These caches are dependent on scale and synthetic settings.
296
       * Any change to the font invalidates them. */
297
6.07k
      v_origin.clear ();
298
299
6.07k
      cached_serial.set_release (font_serial);
300
6.07k
    }
301
302
190k
    int font_serial_coords = font->serial_coords.get_acquire ();
303
190k
    if (cached_coords_serial.get_acquire () != font_serial_coords)
304
6.07k
    {
305
      /* These caches are independent of scale or synthetic settings.
306
       * Just variation changes will invalidate them. */
307
6.07k
      h.clear ();
308
6.07k
      v.clear ();
309
6.07k
      draw.clear ();
310
311
6.07k
      cached_coords_serial.set_release (font_serial_coords);
312
6.07k
    }
313
190k
  }
314
};
315
316
static hb_ot_font_t *
317
_hb_ot_font_create (hb_font_t *font)
318
69.8k
{
319
69.8k
  hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
320
69.8k
  if (unlikely (!ot_font))
321
954
    return nullptr;
322
323
68.9k
  ot_font->ot_face = &font->face->table;
324
325
68.9k
  return ot_font;
326
69.8k
}
327
328
static void
329
_hb_ot_font_destroy (void *font_data)
330
68.9k
{
331
68.9k
  hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
332
333
68.9k
  ot_font->~hb_ot_font_t ();
334
335
68.9k
  hb_free (ot_font);
336
68.9k
}
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.39M
{
345
2.39M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
346
2.39M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
347
2.39M
  return ot_face->cmap->get_nominal_glyph (unicode, glyph);
348
2.39M
}
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
128k
{
360
128k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
361
128k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
362
128k
  return ot_face->cmap->get_nominal_glyphs (count,
363
128k
              first_unicode, unicode_stride,
364
128k
              first_glyph, glyph_stride);
365
128k
}
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
247k
{
375
247k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
376
247k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
377
247k
  return ot_face->cmap->get_variation_glyph (unicode,
378
247k
                                             variation_selector, glyph);
379
247k
}
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
867k
{
390
  // Duplicated in v_advances. Ugly. Keep in sync'ish.
391
392
867k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
393
867k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
394
867k
  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
395
396
867k
  if (unlikely (!hmtx.has_data ()))
397
789k
  {
398
789k
    hb_position_t advance = font->face->get_upem () / 2;
399
789k
    advance = font->em_scale_x (advance);
400
64.8M
    for (unsigned int i = 0; i < count; i++)
401
64.0M
    {
402
64.0M
      *first_advance = advance;
403
64.0M
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
404
64.0M
    }
405
789k
    return;
406
789k
  }
407
408
78.1k
#ifndef HB_NO_VAR
409
78.1k
  if (!font->has_nonzero_coords)
410
33.0k
  {
411
53.6k
  fallback:
412
#else
413
  {
414
#endif
415
    // Just plain htmx data. No need to cache.
416
1.51M
    for (unsigned int i = 0; i < count; i++)
417
1.46M
    {
418
1.46M
      *first_advance = font->em_scale_x (hmtx.get_advance_without_var_unscaled (*first_glyph));
419
1.46M
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
420
1.46M
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
421
1.46M
    }
422
53.6k
    return;
423
33.0k
  }
424
425
45.0k
#ifndef HB_NO_VAR
426
  /* has_nonzero_coords. */
427
428
45.0k
  ot_font->check_serial (font);
429
45.0k
  hb_ot_font_advance_cache_t *advance_cache = ot_font->h.acquire_advance_cache ();
430
45.0k
  if (!advance_cache)
431
123
  {
432
    // malloc failure. Just use the fallback non-variable path.
433
123
    goto fallback;
434
123
  }
435
436
  /* If HVAR is present, use it.*/
437
44.9k
  const OT::HVAR &HVAR = *hmtx.var_table;
438
44.9k
  if (HVAR.has_data ())
439
8.21k
  {
440
8.21k
    const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
441
8.21k
    OT::hb_scalar_cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore);
442
443
20.8k
    for (unsigned int i = 0; i < count; i++)
444
12.6k
    {
445
12.6k
      hb_position_t v;
446
12.6k
      unsigned cv;
447
12.6k
      if (advance_cache->get (*first_glyph, &cv))
448
8.11k
  v = cv;
449
4.55k
      else
450
4.55k
      {
451
4.55k
        v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
452
4.55k
  advance_cache->set (*first_glyph, v);
453
4.55k
      }
454
12.6k
      *first_advance = font->em_scale_x (v);
455
12.6k
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
456
12.6k
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
457
12.6k
    }
458
459
8.21k
    ot_font->h.release_varStore_cache (varStore_cache);
460
8.21k
    ot_font->h.release_advance_cache (advance_cache);
461
8.21k
    return;
462
8.21k
  }
463
464
36.7k
  const auto &gvar = *ot_face->gvar;
465
36.7k
  if (gvar.has_data ())
466
16.5k
  {
467
16.5k
    const auto &glyf = *ot_face->glyf;
468
16.5k
    auto *scratch = glyf.acquire_scratch ();
469
16.5k
    if (unlikely (!scratch))
470
328
    {
471
328
      ot_font->h.release_advance_cache (advance_cache);
472
328
      goto fallback;
473
328
    }
474
16.2k
    OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
475
476
47.0k
    for (unsigned int i = 0; i < count; i++)
477
30.8k
    {
478
30.8k
      hb_position_t v;
479
30.8k
      unsigned cv;
480
30.8k
      if (advance_cache->get (*first_glyph, &cv))
481
19.9k
  v = cv;
482
10.8k
      else
483
10.8k
      {
484
10.8k
        v = glyf.get_advance_with_var_unscaled (*first_glyph, font, false, *scratch, gvar_cache);
485
10.8k
  advance_cache->set (*first_glyph, v);
486
10.8k
      }
487
30.8k
      *first_advance = font->em_scale_x (v);
488
30.8k
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
489
30.8k
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
490
30.8k
    }
491
492
16.2k
    ot_font->draw.release_gvar_cache (gvar_cache);
493
16.2k
    glyf.release_scratch (scratch);
494
16.2k
    ot_font->h.release_advance_cache (advance_cache);
495
16.2k
    return;
496
16.5k
  }
497
498
20.1k
  ot_font->h.release_advance_cache (advance_cache);
499
  // No HVAR or GVAR.  Just use the fallback non-variable path.
500
20.1k
  goto fallback;
501
36.7k
#endif
502
36.7k
}
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
245k
{
514
  // Duplicated from h_advances. Ugly. Keep in sync'ish.
515
516
245k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
517
245k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
518
245k
  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
519
520
245k
  if (unlikely (!vmtx.has_data ()))
521
239k
  {
522
239k
    hb_font_extents_t font_extents;
523
239k
    font->get_h_extents_with_fallback (&font_extents);
524
239k
    hb_position_t advance = font_extents.descender - font_extents.ascender;
525
479k
    for (unsigned int i = 0; i < count; i++)
526
239k
    {
527
239k
      *first_advance = advance;
528
239k
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
529
239k
    }
530
239k
    return;
531
239k
  }
532
533
6.29k
#ifndef HB_NO_VAR
534
6.29k
  if (!font->has_nonzero_coords)
535
3.04k
  {
536
4.21k
  fallback:
537
#else
538
  {
539
#endif
540
    // Just plain vtmx data. No need to cache.
541
8.43k
    for (unsigned int i = 0; i < count; i++)
542
4.21k
    {
543
4.21k
      *first_advance = font->em_scale_y (- (int) vmtx.get_advance_without_var_unscaled (*first_glyph));
544
4.21k
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
545
4.21k
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
546
4.21k
    }
547
4.21k
    return;
548
3.04k
  }
549
550
3.25k
#ifndef HB_NO_VAR
551
  /* has_nonzero_coords. */
552
553
3.25k
  ot_font->check_serial (font);
554
3.25k
  hb_ot_font_advance_cache_t *advance_cache = ot_font->v.acquire_advance_cache ();
555
3.25k
  if (!advance_cache)
556
32
  {
557
    // malloc failure. Just use the fallback non-variable path.
558
32
    goto fallback;
559
32
  }
560
561
  /* If VVAR is present, use it.*/
562
3.22k
  const OT::VVAR &VVAR = *vmtx.var_table;
563
3.22k
  if (VVAR.has_data ())
564
686
  {
565
686
    const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
566
686
    OT::hb_scalar_cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore);
567
568
1.37k
    for (unsigned int i = 0; i < count; i++)
569
686
    {
570
686
      hb_position_t v;
571
686
      unsigned cv;
572
686
      if (advance_cache->get (*first_glyph, &cv))
573
0
  v = cv;
574
686
      else
575
686
      {
576
686
        v = vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
577
686
  advance_cache->set (*first_glyph, v);
578
686
      }
579
686
      *first_advance = font->em_scale_y (- (int) v);
580
686
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
581
686
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
582
686
    }
583
584
686
    ot_font->v.release_varStore_cache (varStore_cache);
585
686
    ot_font->v.release_advance_cache (advance_cache);
586
686
    return;
587
686
  }
588
589
2.53k
  const auto &gvar = *ot_face->gvar;
590
2.53k
  if (gvar.has_data ())
591
1.43k
  {
592
1.43k
    const auto &glyf = *ot_face->glyf;
593
1.43k
    auto *scratch = glyf.acquire_scratch ();
594
1.43k
    if (unlikely (!scratch))
595
48
    {
596
48
      ot_font->v.release_advance_cache (advance_cache);
597
48
      goto fallback;
598
48
    }
599
1.39k
    OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
600
601
2.78k
    for (unsigned int i = 0; i < count; i++)
602
1.39k
    {
603
1.39k
      hb_position_t v;
604
1.39k
      unsigned cv;
605
1.39k
      if (advance_cache->get (*first_glyph, &cv))
606
0
  v = cv;
607
1.39k
      else
608
1.39k
      {
609
1.39k
        v = glyf.get_advance_with_var_unscaled (*first_glyph, font, true, *scratch, gvar_cache);
610
1.39k
  advance_cache->set (*first_glyph, v);
611
1.39k
      }
612
1.39k
      *first_advance = font->em_scale_y (- (int) v);
613
1.39k
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
614
1.39k
      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
615
1.39k
    }
616
617
1.39k
    ot_font->draw.release_gvar_cache (gvar_cache);
618
1.39k
    glyf.release_scratch (scratch);
619
1.39k
    ot_font->v.release_advance_cache (advance_cache);
620
1.39k
    return;
621
1.43k
  }
622
623
1.09k
  ot_font->v.release_advance_cache (advance_cache);
624
  // No VVAR or GVAR.  Just use the fallback non-variable path.
625
1.09k
  goto fallback;
626
2.53k
#endif
627
2.53k
}
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
245k
{
644
245k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
645
245k
  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
245k
  font->get_glyph_h_advances (count,
649
245k
            first_glyph, glyph_stride,
650
245k
            first_x, x_stride);
651
491k
  for (unsigned i = 0; i < count; i++)
652
245k
  {
653
245k
    *first_x /= 2;
654
245k
    first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
655
245k
  }
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
245k
  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
245k
  const OT::VORG &VORG = *ot_face->VORG;
666
245k
  if (origin_cache && VORG.has_data ())
667
3.21k
  {
668
3.21k
#ifndef HB_NO_VAR
669
3.21k
    if (!font->has_nonzero_coords)
670
2.00k
#endif
671
2.00k
    {
672
4.00k
      for (unsigned i = 0; i < count; i++)
673
2.00k
      {
674
2.00k
  hb_position_t origin;
675
2.00k
  unsigned cv;
676
2.00k
  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
2.00k
  else
679
2.00k
  {
680
2.00k
    origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph));
681
2.00k
    origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
682
2.00k
  }
683
684
2.00k
  *first_y = origin;
685
686
2.00k
  first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
687
2.00k
  first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
688
2.00k
      }
689
2.00k
    }
690
1.21k
#ifndef HB_NO_VAR
691
1.21k
    else
692
1.21k
    {
693
1.21k
      const OT::VVAR &VVAR = *ot_face->vmtx->var_table;
694
1.21k
      const auto &varStore = &VVAR + VVAR.varStore;
695
1.21k
      auto *varStore_cache = ot_font->v_origin.acquire_varStore_cache (varStore);
696
2.43k
      for (unsigned i = 0; i < count; i++)
697
1.21k
      {
698
1.21k
  hb_position_t origin;
699
1.21k
  unsigned cv;
700
1.21k
  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
1.21k
  else
703
1.21k
  {
704
1.21k
    origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph) +
705
1.21k
              VVAR.get_vorg_delta_unscaled (*first_glyph,
706
1.21k
                    font->coords, font->num_coords,
707
1.21k
                    varStore_cache));
708
1.21k
    origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
709
1.21k
  }
710
711
1.21k
  *first_y = origin;
712
713
1.21k
  first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
714
1.21k
  first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
715
1.21k
      }
716
1.21k
      ot_font->v_origin.release_varStore_cache (varStore_cache);
717
1.21k
    }
718
3.21k
#endif
719
3.21k
    ot_font->v_origin.release_origin_cache (origin_cache);
720
3.21k
    return true;
721
3.21k
  }
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
242k
  const auto &vmtx = *ot_face->vmtx;
726
242k
  const auto &glyf = *ot_face->glyf;
727
242k
  if (origin_cache && vmtx.has_data() && glyf.has_data ())
728
4.76k
  {
729
4.76k
    auto *scratch = glyf.acquire_scratch ();
730
4.76k
    if (unlikely (!scratch))
731
8
    {
732
8
      ot_font->v_origin.release_origin_cache (origin_cache);
733
8
      return false;
734
8
    }
735
4.76k
    OT::hb_scalar_cache_t *gvar_cache = font->has_nonzero_coords ?
736
2.42k
          ot_font->draw.acquire_gvar_cache (*ot_face->gvar) :
737
4.76k
          nullptr;
738
739
9.52k
    for (unsigned i = 0; i < count; i++)
740
4.76k
    {
741
4.76k
      hb_position_t origin;
742
4.76k
      unsigned cv;
743
4.76k
      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
4.76k
      else
746
4.76k
      {
747
4.76k
  origin = font->em_scalef_y (glyf.get_v_origin_with_var_unscaled (*first_glyph, font, *scratch, gvar_cache));
748
4.76k
  origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
749
4.76k
      }
750
751
4.76k
      *first_y = origin;
752
753
4.76k
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
754
4.76k
      first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
755
4.76k
    }
756
757
4.76k
    if (gvar_cache)
758
2.42k
      ot_font->draw.release_gvar_cache (gvar_cache);
759
4.76k
    glyf.release_scratch (scratch);
760
4.76k
    ot_font->v_origin.release_origin_cache (origin_cache);
761
4.76k
    return true;
762
4.76k
  }
763
764
  /* Otherwise, use glyph extents to center the glyph vertically.
765
   * If getting glyph extents failed, just use the font ascender. */
766
237k
  if (origin_cache && font->has_glyph_extents_func ())
767
236k
  {
768
236k
    hb_font_extents_t font_extents;
769
236k
    font->get_h_extents_with_fallback (&font_extents);
770
236k
    hb_position_t font_advance = font_extents.ascender - font_extents.descender;
771
772
472k
    for (unsigned i = 0; i < count; i++)
773
236k
    {
774
236k
      hb_position_t origin;
775
236k
      unsigned cv;
776
777
236k
      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
236k
      else
780
236k
      {
781
236k
  hb_glyph_extents_t extents = {0};
782
236k
  if (likely (font->get_glyph_extents (*first_glyph, &extents)))
783
117k
    origin = extents.y_bearing + ((font_advance - -extents.height) >> 1);
784
118k
  else
785
118k
    origin = font_extents.ascender;
786
787
236k
  origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
788
236k
      }
789
790
236k
      *first_y = origin;
791
792
236k
      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
793
236k
      first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
794
236k
    }
795
236k
  }
796
797
237k
  ot_font->v_origin.release_origin_cache (origin_cache);
798
237k
  return true;
799
242k
}
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
2.00M
{
809
2.00M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
810
2.00M
  const hb_ot_face_t *ot_face = ot_font->ot_face;
811
812
2.00M
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
813
2.00M
  if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
814
2.00M
  if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
815
2.00M
#endif
816
2.00M
#if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
817
2.00M
  if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
818
1.98M
#endif
819
1.98M
#ifndef HB_NO_VAR_COMPOSITES
820
1.98M
  if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
821
1.96M
#endif
822
1.96M
  if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
823
1.72M
#ifndef HB_NO_OT_FONT_CFF
824
1.72M
  if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
825
1.71M
  if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
826
1.70M
#endif
827
828
1.70M
  return false;
829
1.71M
}
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
245k
{
839
245k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
840
245k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
841
842
245k
  if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
843
237k
#ifndef HB_NO_OT_FONT_CFF
844
237k
  if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
845
227k
#endif
846
227k
  return false;
847
237k
}
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.3k
{
855
42.3k
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
856
42.3k
  const hb_ot_face_t *ot_face = ot_font->ot_face;
857
858
42.3k
  if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
859
42.3k
#ifndef HB_NO_OT_FONT_CFF
860
42.3k
    if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
861
42.3k
#endif
862
42.3k
  return false;
863
42.3k
}
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
475k
{
872
475k
  return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
873
54.4k
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
874
54.4k
   _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
875
475k
}
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
1.77M
{
898
1.77M
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
899
1.77M
  hb_draw_session_t draw_session {draw_funcs, draw_data};
900
1.77M
  bool ret = false;
901
902
1.77M
  OT::hb_scalar_cache_t *gvar_cache = nullptr;
903
1.77M
  if (font->num_coords)
904
142k
  {
905
142k
    ot_font->check_serial (font);
906
142k
    gvar_cache = ot_font->draw.acquire_gvar_cache (*ot_font->ot_face->gvar);
907
142k
  }
908
909
1.77M
#ifndef HB_NO_VAR_COMPOSITES
910
1.77M
  if (font->face->table.VARC->get_path (font, glyph, draw_session)) { ret = true; goto done; }
911
1.76M
#endif
912
  // Keep the following in synch with VARC::get_path_at()
913
1.76M
  if (font->face->table.glyf->get_path (font, glyph, draw_session, gvar_cache)) { ret = true; goto done; }
914
915
1.29M
#ifndef HB_NO_CFF
916
1.29M
  if (font->face->table.cff2->get_path (font, glyph, draw_session)) { ret = true; goto done; }
917
1.27M
  if (font->face->table.cff1->get_path (font, glyph, draw_session)) { ret = true; goto done; }
918
1.26M
#endif
919
920
1.77M
done:
921
922
1.77M
  ot_font->draw.release_gvar_cache (gvar_cache);
923
924
1.77M
  return ret;
925
1.27M
}
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
827k
{
938
827k
#ifndef HB_NO_COLOR
939
827k
  if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true;
940
827k
  if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
941
827k
#ifndef HB_NO_OT_FONT_BITMAP
942
827k
  if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
943
827k
  if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
944
827k
#endif
945
827k
#endif
946
827k
  return false;
947
827k
}
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
3
  {
956
3
    hb_font_funcs_t *funcs = hb_font_funcs_create ();
957
958
3
    hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
959
3
    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
960
3
    hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
961
962
3
    hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
963
3
    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
964
965
3
#ifndef HB_NO_VERTICAL
966
3
    hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
967
3
    hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
968
3
    hb_font_funcs_set_glyph_v_origins_func (funcs, hb_ot_get_glyph_v_origins, nullptr, nullptr);
969
3
#endif
970
971
3
#ifndef HB_NO_DRAW
972
3
    hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ot_draw_glyph_or_fail, nullptr, nullptr);
973
3
#endif
974
975
3
#ifndef HB_NO_PAINT
976
3
    hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ot_paint_glyph_or_fail, nullptr, nullptr);
977
3
#endif
978
979
3
    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
3
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
983
3
    hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
984
3
    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
985
3
#endif
986
987
3
    hb_font_funcs_make_immutable (funcs);
988
989
3
    hb_atexit (free_static_ot_funcs);
990
991
3
    return funcs;
992
3
  }
993
} static_ot_funcs;
994
995
static inline
996
void free_static_ot_funcs ()
997
3
{
998
3
  static_ot_funcs.free_instance ();
999
3
}
1000
1001
static hb_font_funcs_t *
1002
_hb_ot_get_font_funcs ()
1003
68.9k
{
1004
68.9k
  return static_ot_funcs.get_unconst ();
1005
68.9k
}
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
69.8k
{
1021
69.8k
  hb_ot_font_t *ot_font = _hb_ot_font_create (font);
1022
69.8k
  if (unlikely (!ot_font))
1023
954
    return;
1024
1025
68.9k
  hb_font_set_funcs (font,
1026
68.9k
         _hb_ot_get_font_funcs (),
1027
68.9k
         ot_font,
1028
68.9k
         _hb_ot_font_destroy);
1029
68.9k
}
1030
1031
#endif