Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/harfbuzz/src/hb-font.hh
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2009  Red Hat, Inc.
3
 * Copyright © 2011  Google, Inc.
4
 *
5
 *  This is part of HarfBuzz, a text shaping library.
6
 *
7
 * Permission is hereby granted, without written agreement and without
8
 * license or royalty fees, to use, copy, modify, and distribute this
9
 * software and its documentation for any purpose, provided that the
10
 * above copyright notice and the following two paragraphs appear in
11
 * all copies of this software.
12
 *
13
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17
 * DAMAGE.
18
 *
19
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24
 *
25
 * Red Hat Author(s): Behdad Esfahbod
26
 * Google Author(s): Behdad Esfahbod
27
 */
28
29
#ifndef HB_FONT_HH
30
#define HB_FONT_HH
31
32
#include "hb.hh"
33
34
#include "hb-face.hh"
35
#include "hb-atomic.hh"
36
#include "hb-draw.hh"
37
#include "hb-paint-extents.hh"
38
#include "hb-shaper.hh"
39
#include "hb-outline.hh"
40
41
42
/*
43
 * hb_font_funcs_t
44
 */
45
46
#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
47
0
  HB_FONT_FUNC_IMPLEMENT (get_,font_h_extents) \
48
0
  HB_FONT_FUNC_IMPLEMENT (get_,font_v_extents) \
49
0
  HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyph) \
50
0
  HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyphs) \
51
0
  HB_FONT_FUNC_IMPLEMENT (get_,variation_glyph) \
52
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advance) \
53
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advance) \
54
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advances) \
55
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advances) \
56
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origin) \
57
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origin) \
58
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_kerning) \
59
0
  HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_kerning)) \
60
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_extents) \
61
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \
62
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \
63
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \
64
0
  HB_FONT_FUNC_IMPLEMENT (,draw_glyph_or_fail) \
65
0
  HB_FONT_FUNC_IMPLEMENT (,paint_glyph_or_fail) \
66
  /* ^--- Add new callbacks here */
67
68
struct hb_font_funcs_t
69
{
70
  hb_object_header_t header;
71
72
  struct {
73
#define HB_FONT_FUNC_IMPLEMENT(get_,name) void *name;
74
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
75
#undef HB_FONT_FUNC_IMPLEMENT
76
  } *user_data;
77
78
  struct {
79
#define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_destroy_func_t name;
80
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
81
#undef HB_FONT_FUNC_IMPLEMENT
82
  } *destroy;
83
84
  /* Don't access these directly.  Call font->get_*() instead. */
85
  union get_t {
86
    struct get_funcs_t {
87
#define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_font_##get_##name##_func_t name;
88
      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
89
#undef HB_FONT_FUNC_IMPLEMENT
90
    } f;
91
    void (*array[0
92
#define HB_FONT_FUNC_IMPLEMENT(get_,name) +1
93
      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
94
#undef HB_FONT_FUNC_IMPLEMENT
95
    ]) ();
96
  } get;
97
};
98
DECLARE_NULL_INSTANCE (hb_font_funcs_t);
99
100
101
/*
102
 * hb_font_t
103
 */
104
105
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font);
106
#include "hb-shaper-list.hh"
107
#undef HB_SHAPER_IMPLEMENT
108
109
struct hb_font_t
110
{
111
  hb_object_header_t header;
112
  hb_atomic_t<unsigned> serial;
113
  hb_atomic_t<unsigned> serial_coords;
114
115
  hb_font_t *parent;
116
  hb_face_t *face;
117
118
  int32_t x_scale;
119
  int32_t y_scale;
120
121
  float x_embolden;
122
  float y_embolden;
123
  bool embolden_in_place;
124
  int32_t x_strength; /* x_embolden, in scaled units. */
125
  int32_t y_strength; /* y_embolden, in scaled units. */
126
127
  float slant;
128
  float slant_xy;
129
130
  float x_multf;
131
  float y_multf;
132
  int64_t x_mult;
133
  int64_t y_mult;
134
135
  unsigned int x_ppem;
136
  unsigned int y_ppem;
137
138
  float ptem;
139
140
  /* Font variation coordinates. */
141
  unsigned int instance_index;
142
  unsigned int num_coords;
143
  int *coords;
144
  float *design_coords;
145
146
  hb_font_funcs_t   *klass;
147
  void              *user_data;
148
  hb_destroy_func_t  destroy;
149
150
  hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */
151
152
153
  /* Convert from font-space to user-space */
154
  int64_t dir_mult (hb_direction_t direction)
155
0
  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
156
522M
  hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
157
9.67M
  hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
158
0
  hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); }
159
17.4M
  hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
160
158k
  float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); }
161
158k
  float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); }
162
0
  float em_fscalef_x (float v) { return em_fmultf (v, x_multf); }
163
0
  float em_fscalef_y (float v) { return em_fmultf (v, y_multf); }
164
  hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
165
0
  { return em_mult (v, dir_mult (direction)); }
166
167
  /* Convert from parent-font user-space to our user-space */
168
  hb_position_t parent_scale_x_distance (hb_position_t v)
169
0
  {
170
0
    if (unlikely (parent && parent->x_scale != x_scale))
171
0
      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
172
0
    return v;
173
0
  }
174
  hb_position_t parent_scale_y_distance (hb_position_t v)
175
0
  {
176
0
    if (unlikely (parent && parent->y_scale != y_scale))
177
0
      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
178
0
    return v;
179
0
  }
180
  hb_position_t parent_scale_x_position (hb_position_t v)
181
0
  { return parent_scale_x_distance (v); }
182
  hb_position_t parent_scale_y_position (hb_position_t v)
183
0
  { return parent_scale_y_distance (v); }
184
185
  void parent_scale_distance (hb_position_t *x, hb_position_t *y)
186
0
  {
187
0
    *x = parent_scale_x_distance (*x);
188
0
    *y = parent_scale_y_distance (*y);
189
0
  }
190
  void parent_scale_position (hb_position_t *x, hb_position_t *y)
191
0
  {
192
0
    *x = parent_scale_x_position (*x);
193
0
    *y = parent_scale_y_position (*y);
194
0
  }
195
196
  void scale_glyph_extents (hb_glyph_extents_t *extents)
197
4.83M
  {
198
4.83M
    float x1 = em_scale_x (extents->x_bearing);
199
4.83M
    float y1 = em_scale_y (extents->y_bearing);
200
4.83M
    float x2 = em_scale_x (extents->x_bearing + extents->width);
201
4.83M
    float y2 = em_scale_y (extents->y_bearing + extents->height);
202
203
4.83M
    extents->x_bearing = roundf (x1);
204
4.83M
    extents->y_bearing = roundf (y1);
205
4.83M
    extents->width = roundf (x2) - extents->x_bearing;
206
4.83M
    extents->height = roundf (y2) - extents->y_bearing;
207
4.83M
  }
208
209
  void synthetic_glyph_extents (hb_glyph_extents_t *extents)
210
0
  {
211
    /* Slant. */
212
0
    if (slant_xy)
213
0
    {
214
0
      hb_position_t x1 = extents->x_bearing;
215
0
      hb_position_t y1 = extents->y_bearing;
216
0
      hb_position_t x2 = extents->x_bearing + extents->width;
217
0
      hb_position_t y2 = extents->y_bearing + extents->height;
218
219
0
      x1 += floorf (hb_min (y1 * slant_xy, y2 * slant_xy));
220
0
      x2 += ceilf (hb_max (y1 * slant_xy, y2 * slant_xy));
221
222
0
      extents->x_bearing = x1;
223
0
      extents->width = x2 - extents->x_bearing;
224
0
    }
225
226
    /* Embolden. */
227
0
    if (x_strength || y_strength)
228
0
    {
229
      /* Y */
230
0
      int y_shift = y_strength;
231
0
      if (y_scale < 0) y_shift = -y_shift;
232
0
      extents->y_bearing += y_shift;
233
0
      extents->height -= y_shift;
234
235
      /* X */
236
0
      int x_shift = x_strength;
237
0
      if (x_scale < 0) x_shift = -x_shift;
238
0
      if (embolden_in_place)
239
0
  extents->x_bearing -= x_shift / 2;
240
0
      extents->width += x_shift;
241
0
    }
242
0
  }
243
244
245
  /* Public getters */
246
247
  HB_INTERNAL bool has_func (unsigned int i);
248
  HB_INTERNAL bool has_func_set (unsigned int i);
249
250
  /* has_* ... */
251
#define HB_FONT_FUNC_IMPLEMENT(get_,name) \
252
  bool \
253
  has_##name##_func () \
254
97.0M
  { \
255
97.0M
    hb_font_funcs_t *funcs = this->klass; \
256
97.0M
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
257
97.0M
    return has_func (i); \
258
97.0M
  } \
Unexecuted instantiation: hb_font_t::has_font_h_extents_func()
Unexecuted instantiation: hb_font_t::has_font_v_extents_func()
Unexecuted instantiation: hb_font_t::has_nominal_glyph_func()
Unexecuted instantiation: hb_font_t::has_nominal_glyphs_func()
Unexecuted instantiation: hb_font_t::has_variation_glyph_func()
Unexecuted instantiation: hb_font_t::has_glyph_h_advance_func()
Unexecuted instantiation: hb_font_t::has_glyph_v_advance_func()
Unexecuted instantiation: hb_font_t::has_glyph_h_advances_func()
Unexecuted instantiation: hb_font_t::has_glyph_v_advances_func()
hb_font_t::has_glyph_h_origin_func()
Line
Count
Source
254
97.0M
  { \
255
97.0M
    hb_font_funcs_t *funcs = this->klass; \
256
97.0M
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
257
97.0M
    return has_func (i); \
258
97.0M
  } \
Unexecuted instantiation: hb_font_t::has_glyph_v_origin_func()
Unexecuted instantiation: hb_font_t::has_glyph_h_kerning_func()
Unexecuted instantiation: hb_font_t::has_glyph_extents_func()
Unexecuted instantiation: hb_font_t::has_glyph_contour_point_func()
Unexecuted instantiation: hb_font_t::has_glyph_name_func()
Unexecuted instantiation: hb_font_t::has_glyph_from_name_func()
Unexecuted instantiation: hb_font_t::has_draw_glyph_or_fail_func()
Unexecuted instantiation: hb_font_t::has_paint_glyph_or_fail_func()
259
  bool \
260
  has_##name##_func_set () \
261
11.2M
  { \
262
11.2M
    hb_font_funcs_t *funcs = this->klass; \
263
11.2M
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
264
11.2M
    return has_func_set (i); \
265
11.2M
  }
Unexecuted instantiation: hb_font_t::has_font_h_extents_func_set()
Unexecuted instantiation: hb_font_t::has_font_v_extents_func_set()
Unexecuted instantiation: hb_font_t::has_nominal_glyph_func_set()
Unexecuted instantiation: hb_font_t::has_nominal_glyphs_func_set()
Unexecuted instantiation: hb_font_t::has_variation_glyph_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_h_advance_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_v_advance_func_set()
hb_font_t::has_glyph_h_advances_func_set()
Line
Count
Source
261
11.2M
  { \
262
11.2M
    hb_font_funcs_t *funcs = this->klass; \
263
11.2M
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
264
11.2M
    return has_func_set (i); \
265
11.2M
  }
Unexecuted instantiation: hb_font_t::has_glyph_v_advances_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_h_origin_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_v_origin_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_h_kerning_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_extents_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_contour_point_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_name_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_from_name_func_set()
Unexecuted instantiation: hb_font_t::has_draw_glyph_or_fail_func_set()
Unexecuted instantiation: hb_font_t::has_paint_glyph_or_fail_func_set()
266
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
267
#undef HB_FONT_FUNC_IMPLEMENT
268
269
  hb_bool_t get_font_h_extents (hb_font_extents_t *extents,
270
        bool synthetic = true)
271
4.57M
  {
272
4.57M
    hb_memset (extents, 0, sizeof (*extents));
273
4.57M
    bool ret = klass->get.f.font_h_extents (this, user_data,
274
4.57M
              extents,
275
4.57M
              !klass->user_data ? nullptr : klass->user_data->font_h_extents);
276
277
4.57M
    if (synthetic && ret)
278
4.57M
    {
279
      /* Embolden */
280
4.57M
      int y_shift = y_scale < 0 ? -y_strength : y_strength;
281
4.57M
      extents->ascender += y_shift;
282
4.57M
    }
283
284
4.57M
    return ret;
285
4.57M
  }
286
  hb_bool_t get_font_v_extents (hb_font_extents_t *extents,
287
        bool synthetic = true)
288
0
  {
289
0
    hb_memset (extents, 0, sizeof (*extents));
290
0
    bool ret = klass->get.f.font_v_extents (this, user_data,
291
0
              extents,
292
0
              !klass->user_data ? nullptr : klass->user_data->font_v_extents);
293
294
0
    if (synthetic && ret)
295
0
    {
296
      /* Embolden */
297
0
      int x_shift = x_scale < 0 ? -x_strength : x_strength;
298
0
      if (embolden_in_place)
299
0
      {
300
0
  extents->ascender += x_shift / 2;
301
0
  extents->descender -= x_shift - x_shift / 2;
302
0
      }
303
0
      else
304
0
  extents->ascender += x_shift;
305
0
    }
306
307
0
    return ret;
308
0
  }
309
310
  bool has_glyph (hb_codepoint_t unicode)
311
7.99M
  {
312
7.99M
    hb_codepoint_t glyph;
313
7.99M
    return get_nominal_glyph (unicode, &glyph);
314
7.99M
  }
315
316
  hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
317
             hb_codepoint_t *glyph,
318
             hb_codepoint_t not_found = 0)
319
152M
  {
320
152M
    *glyph = not_found;
321
152M
    return klass->get.f.nominal_glyph (this, user_data,
322
152M
               unicode, glyph,
323
152M
               !klass->user_data ? nullptr : klass->user_data->nominal_glyph);
324
152M
  }
325
  unsigned int get_nominal_glyphs (unsigned int count,
326
           const hb_codepoint_t *first_unicode,
327
           unsigned int unicode_stride,
328
           hb_codepoint_t *first_glyph,
329
           unsigned int glyph_stride)
330
33.1M
  {
331
33.1M
    return klass->get.f.nominal_glyphs (this, user_data,
332
33.1M
          count,
333
33.1M
          first_unicode, unicode_stride,
334
33.1M
          first_glyph, glyph_stride,
335
33.1M
          !klass->user_data ? nullptr : klass->user_data->nominal_glyphs);
336
33.1M
  }
337
338
  hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
339
         hb_codepoint_t *glyph,
340
         hb_codepoint_t not_found = 0)
341
25.4k
  {
342
25.4k
    *glyph = not_found;
343
25.4k
    return klass->get.f.variation_glyph (this, user_data,
344
25.4k
           unicode, variation_selector, glyph,
345
25.4k
           !klass->user_data ? nullptr : klass->user_data->variation_glyph);
346
25.4k
  }
347
348
  hb_position_t get_glyph_h_advance (hb_codepoint_t glyph,
349
             bool synthetic = true)
350
11.2M
  {
351
11.2M
    hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data,
352
11.2M
                glyph,
353
11.2M
                !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
354
355
11.2M
    if (synthetic && x_strength && !embolden_in_place)
356
0
    {
357
      /* Embolden */
358
0
      hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
359
0
      advance += advance ? strength : 0;
360
0
    }
361
362
11.2M
    return advance;
363
11.2M
  }
364
365
  hb_position_t get_glyph_v_advance (hb_codepoint_t glyph,
366
             bool synthetic = true)
367
0
  {
368
0
    hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data,
369
0
                glyph,
370
0
                !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
371
372
0
    if (synthetic && y_strength && !embolden_in_place)
373
0
    {
374
      /* Embolden */
375
0
      hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
376
0
      advance += advance ? strength : 0;
377
0
    }
378
379
0
    return advance;
380
0
  }
381
382
  void get_glyph_h_advances (unsigned int count,
383
           const hb_codepoint_t *first_glyph,
384
           unsigned int glyph_stride,
385
           hb_position_t *first_advance,
386
           unsigned int advance_stride,
387
           bool synthetic = true)
388
42.4M
  {
389
42.4M
    klass->get.f.glyph_h_advances (this, user_data,
390
42.4M
           count,
391
42.4M
           first_glyph, glyph_stride,
392
42.4M
           first_advance, advance_stride,
393
42.4M
           !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
394
395
42.4M
    if (synthetic && x_strength && !embolden_in_place)
396
0
    {
397
      /* Embolden */
398
0
      hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
399
0
      for (unsigned int i = 0; i < count; i++)
400
0
      {
401
0
  *first_advance += *first_advance ? strength : 0;
402
0
  first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
403
0
      }
404
0
    }
405
42.4M
  }
406
407
  void get_glyph_v_advances (unsigned int count,
408
           const hb_codepoint_t *first_glyph,
409
           unsigned int glyph_stride,
410
           hb_position_t *first_advance,
411
           unsigned int advance_stride,
412
           bool synthetic = true)
413
1.74M
  {
414
1.74M
    klass->get.f.glyph_v_advances (this, user_data,
415
1.74M
           count,
416
1.74M
           first_glyph, glyph_stride,
417
1.74M
           first_advance, advance_stride,
418
1.74M
           !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
419
420
1.74M
    if (synthetic && y_strength && !embolden_in_place)
421
0
    {
422
      /* Embolden */
423
0
      hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
424
0
      for (unsigned int i = 0; i < count; i++)
425
0
      {
426
0
  *first_advance += *first_advance ? strength : 0;
427
0
  first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
428
0
      }
429
0
    }
430
1.74M
  }
431
432
  hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
433
        hb_position_t *x, hb_position_t *y)
434
0
  {
435
0
    *x = *y = 0;
436
0
    return klass->get.f.glyph_h_origin (this, user_data,
437
0
          glyph, x, y,
438
0
          !klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
439
0
  }
440
441
  hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
442
        hb_position_t *x, hb_position_t *y)
443
2.72M
  {
444
2.72M
    *x = *y = 0;
445
2.72M
    return klass->get.f.glyph_v_origin (this, user_data,
446
2.72M
          glyph, x, y,
447
2.72M
          !klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
448
2.72M
  }
449
450
  hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
451
             hb_codepoint_t right_glyph)
452
0
  {
453
#ifdef HB_DISABLE_DEPRECATED
454
    return 0;
455
#else
456
0
    return klass->get.f.glyph_h_kerning (this, user_data,
457
0
           left_glyph, right_glyph,
458
0
           !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning);
459
0
#endif
460
0
  }
461
462
  hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
463
             hb_codepoint_t bottom_glyph)
464
0
  {
465
#ifdef HB_DISABLE_DEPRECATED
466
    return 0;
467
#else
468
0
    return klass->get.f.glyph_v_kerning (this, user_data,
469
0
           top_glyph, bottom_glyph,
470
0
           !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning);
471
0
#endif
472
0
  }
473
474
  hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
475
             hb_glyph_extents_t *extents,
476
             bool synthetic = true)
477
6.71M
  {
478
6.71M
    hb_memset (extents, 0, sizeof (*extents));
479
480
    /* This is rather messy, but necessary. */
481
482
6.71M
    if (!synthetic)
483
0
    {
484
0
      return klass->get.f.glyph_extents (this, user_data,
485
0
           glyph,
486
0
           extents,
487
0
           !klass->user_data ? nullptr : klass->user_data->glyph_extents);
488
0
    }
489
6.71M
    if (!is_synthetic () &&
490
6.71M
  klass->get.f.glyph_extents (this, user_data,
491
6.71M
            glyph,
492
6.71M
            extents,
493
6.71M
            !klass->user_data ? nullptr : klass->user_data->glyph_extents))
494
6.71M
      return true;
495
496
    /* Try getting extents from paint(), then draw(), *then* get_extents()
497
     * and apply synthetic settings in the last case. */
498
499
0
#ifndef HB_NO_PAINT
500
0
    hb_paint_extents_context_t paint_extents;
501
0
    if (paint_glyph_or_fail (glyph,
502
0
           hb_paint_extents_get_funcs (), &paint_extents,
503
0
           0, 0))
504
0
    {
505
0
      *extents = paint_extents.get_extents ().to_glyph_extents ();
506
0
      return true;
507
0
    }
508
0
#endif
509
510
0
#ifndef HB_NO_DRAW
511
0
    hb_extents_t draw_extents;
512
0
    if (draw_glyph_or_fail (glyph,
513
0
          hb_draw_extents_get_funcs (), &draw_extents))
514
0
    {
515
0
      *extents = draw_extents.to_glyph_extents ();
516
0
      return true;
517
0
    }
518
0
#endif
519
520
0
    bool ret = klass->get.f.glyph_extents (this, user_data,
521
0
             glyph,
522
0
             extents,
523
0
             !klass->user_data ? nullptr : klass->user_data->glyph_extents);
524
0
    if (ret)
525
0
      synthetic_glyph_extents (extents);
526
527
0
    return ret;
528
0
  }
529
530
  hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
531
             hb_position_t *x, hb_position_t *y,
532
             bool synthetic = true)
533
0
  {
534
0
    *x = *y = 0;
535
0
    bool ret = klass->get.f.glyph_contour_point (this, user_data,
536
0
             glyph, point_index,
537
0
             x, y,
538
0
             !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
539
540
0
    if (synthetic && ret)
541
0
    {
542
      /* Slant */
543
0
      if (slant_xy)
544
0
        *x += roundf (*y * slant_xy);
545
546
      /* Embolden */
547
0
      if (!embolden_in_place)
548
0
      {
549
0
  int x_shift = x_scale < 0 ? -x_strength : x_strength;
550
0
  *x += x_shift;
551
0
      }
552
0
    }
553
554
0
    return ret;
555
0
  }
556
557
  hb_bool_t get_glyph_name (hb_codepoint_t glyph,
558
          char *name, unsigned int size)
559
0
  {
560
0
    if (size) *name = '\0';
561
0
    return klass->get.f.glyph_name (this, user_data,
562
0
            glyph,
563
0
            name, size,
564
0
            !klass->user_data ? nullptr : klass->user_data->glyph_name);
565
0
  }
566
567
  hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
568
         hb_codepoint_t *glyph)
569
0
  {
570
0
    *glyph = 0;
571
0
    if (len == -1) len = strlen (name);
572
0
    return klass->get.f.glyph_from_name (this, user_data,
573
0
           name, len,
574
0
           glyph,
575
0
           !klass->user_data ? nullptr : klass->user_data->glyph_from_name);
576
0
  }
577
578
  bool draw_glyph_or_fail (hb_codepoint_t glyph,
579
         hb_draw_funcs_t *draw_funcs, void *draw_data,
580
         bool synthetic = true)
581
0
  {
582
0
#ifndef HB_NO_DRAW
583
0
#ifndef HB_NO_OUTLINE
584
0
    bool embolden = x_strength || y_strength;
585
0
    bool slanted = slant_xy;
586
0
    synthetic = synthetic && (embolden || slanted);
587
#else
588
    synthetic = false;
589
#endif
590
591
0
    if (!synthetic)
592
0
    {
593
0
      return klass->get.f.draw_glyph_or_fail (this, user_data,
594
0
                glyph,
595
0
                draw_funcs, draw_data,
596
0
                !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail);
597
0
    }
598
599
0
#ifndef HB_NO_OUTLINE
600
601
0
    hb_outline_t outline;
602
0
    if (!klass->get.f.draw_glyph_or_fail (this, user_data,
603
0
            glyph,
604
0
            hb_outline_recording_pen_get_funcs (), &outline,
605
0
            !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail))
606
0
      return false;
607
608
    // Slant before embolden; produces nicer results.
609
610
0
    if (slanted)
611
0
      outline.slant (slant_xy);
612
613
0
    if (embolden)
614
0
    {
615
0
      float x_shift = embolden_in_place ? 0 : (float) x_strength / 2;
616
0
      float y_shift = (float) y_strength / 2;
617
0
      if (x_scale < 0) x_shift = -x_shift;
618
0
      if (y_scale < 0) y_shift = -y_shift;
619
0
      outline.embolden (x_strength, y_strength, x_shift, y_shift);
620
0
    }
621
622
0
    outline.replay (draw_funcs, draw_data);
623
624
0
    return true;
625
0
#endif
626
0
#endif
627
0
    return false;
628
0
  }
629
630
  bool paint_glyph_or_fail (hb_codepoint_t glyph,
631
          hb_paint_funcs_t *paint_funcs, void *paint_data,
632
          unsigned int palette,
633
          hb_color_t foreground,
634
          bool synthetic = true)
635
0
  {
636
0
#ifndef HB_NO_PAINT
637
    /* Slant */
638
0
    if (synthetic && slant_xy)
639
0
      hb_paint_push_transform (paint_funcs, paint_data,
640
0
             1.f, 0.f,
641
0
             slant_xy, 1.f,
642
0
             0.f, 0.f);
643
644
0
    bool ret = klass->get.f.paint_glyph_or_fail (this, user_data,
645
0
             glyph,
646
0
             paint_funcs, paint_data,
647
0
             palette, foreground,
648
0
             !klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail);
649
650
0
    if (synthetic && slant_xy)
651
0
      hb_paint_pop_transform (paint_funcs, paint_data);
652
653
0
    return ret;
654
0
#endif
655
0
    return false;
656
0
  }
657
658
  /* A bit higher-level, and with fallback */
659
660
  HB_INTERNAL
661
  void paint_glyph (hb_codepoint_t glyph,
662
        hb_paint_funcs_t *paint_funcs, void *paint_data,
663
        unsigned int palette,
664
        hb_color_t foreground);
665
666
  void get_h_extents_with_fallback (hb_font_extents_t *extents)
667
4.47M
  {
668
4.47M
    if (!get_font_h_extents (extents))
669
0
    {
670
0
      extents->ascender = y_scale * .8;
671
0
      extents->descender = extents->ascender - y_scale;
672
0
      extents->line_gap = 0;
673
0
    }
674
4.47M
  }
675
  void get_v_extents_with_fallback (hb_font_extents_t *extents)
676
0
  {
677
0
    if (!get_font_v_extents (extents))
678
0
    {
679
0
      extents->ascender = x_scale / 2;
680
0
      extents->descender = extents->ascender - x_scale;
681
0
      extents->line_gap = 0;
682
0
    }
683
0
  }
684
685
  void get_extents_for_direction (hb_direction_t direction,
686
          hb_font_extents_t *extents)
687
0
  {
688
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
689
0
      get_h_extents_with_fallback (extents);
690
0
    else
691
0
      get_v_extents_with_fallback (extents);
692
0
  }
693
694
  void get_glyph_advance_for_direction (hb_codepoint_t glyph,
695
          hb_direction_t direction,
696
          hb_position_t *x, hb_position_t *y)
697
0
  {
698
0
    *x = *y = 0;
699
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
700
0
      *x = get_glyph_h_advance (glyph);
701
0
    else
702
0
      *y = get_glyph_v_advance (glyph);
703
0
  }
704
  void get_glyph_advances_for_direction (hb_direction_t direction,
705
           unsigned int count,
706
           const hb_codepoint_t *first_glyph,
707
           unsigned glyph_stride,
708
           hb_position_t *first_advance,
709
           unsigned advance_stride)
710
0
  {
711
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
712
0
      get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
713
0
    else
714
0
      get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
715
0
  }
716
717
  void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
718
              hb_position_t *x, hb_position_t *y)
719
0
  {
720
0
    *x = get_glyph_h_advance (glyph) / 2;
721
722
0
    hb_font_extents_t extents;
723
0
    get_h_extents_with_fallback (&extents);
724
0
    *y = extents.ascender;
725
0
  }
726
727
  void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
728
           hb_position_t *x, hb_position_t *y)
729
0
  {
730
0
    if (!get_glyph_h_origin (glyph, x, y) &&
731
0
   get_glyph_v_origin (glyph, x, y))
732
0
    {
733
0
      hb_position_t dx, dy;
734
0
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
735
0
      *x -= dx; *y -= dy;
736
0
    }
737
0
  }
738
  void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
739
           hb_position_t *x, hb_position_t *y)
740
2.72M
  {
741
2.72M
    if (!get_glyph_v_origin (glyph, x, y) &&
742
2.72M
   get_glyph_h_origin (glyph, x, y))
743
0
    {
744
0
      hb_position_t dx, dy;
745
0
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
746
0
      *x += dx; *y += dy;
747
0
    }
748
2.72M
  }
749
750
  void get_glyph_origin_for_direction (hb_codepoint_t glyph,
751
               hb_direction_t direction,
752
               hb_position_t *x, hb_position_t *y)
753
0
  {
754
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
755
0
      get_glyph_h_origin_with_fallback (glyph, x, y);
756
0
    else
757
0
      get_glyph_v_origin_with_fallback (glyph, x, y);
758
0
  }
759
760
  void add_glyph_h_origin (hb_codepoint_t glyph,
761
         hb_position_t *x, hb_position_t *y)
762
0
  {
763
0
    hb_position_t origin_x, origin_y;
764
765
0
    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
766
767
0
    *x += origin_x;
768
0
    *y += origin_y;
769
0
  }
770
  void add_glyph_v_origin (hb_codepoint_t glyph,
771
         hb_position_t *x, hb_position_t *y)
772
0
  {
773
0
    hb_position_t origin_x, origin_y;
774
0
775
0
    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
776
0
777
0
    *x += origin_x;
778
0
    *y += origin_y;
779
0
  }
780
  void add_glyph_origin_for_direction (hb_codepoint_t glyph,
781
               hb_direction_t direction,
782
               hb_position_t *x, hb_position_t *y)
783
0
  {
784
0
    hb_position_t origin_x, origin_y;
785
786
0
    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
787
788
0
    *x += origin_x;
789
0
    *y += origin_y;
790
0
  }
791
792
  void subtract_glyph_h_origin (hb_codepoint_t glyph,
793
        hb_position_t *x, hb_position_t *y)
794
0
  {
795
0
    hb_position_t origin_x, origin_y;
796
797
0
    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
798
799
0
    *x -= origin_x;
800
0
    *y -= origin_y;
801
0
  }
802
  void subtract_glyph_v_origin (hb_codepoint_t glyph,
803
        hb_position_t *x, hb_position_t *y)
804
2.72M
  {
805
2.72M
    hb_position_t origin_x, origin_y;
806
807
2.72M
    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
808
809
2.72M
    *x -= origin_x;
810
2.72M
    *y -= origin_y;
811
2.72M
  }
812
  void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
813
              hb_direction_t direction,
814
              hb_position_t *x, hb_position_t *y)
815
0
  {
816
0
    hb_position_t origin_x, origin_y;
817
818
0
    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
819
820
0
    *x -= origin_x;
821
0
    *y -= origin_y;
822
0
  }
823
824
  void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
825
          hb_direction_t direction,
826
          hb_position_t *x, hb_position_t *y)
827
0
  {
828
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
829
0
      *y = 0;
830
0
      *x = get_glyph_h_kerning (first_glyph, second_glyph);
831
0
    } else {
832
0
      *x = 0;
833
0
      *y = get_glyph_v_kerning (first_glyph, second_glyph);
834
0
    }
835
0
  }
836
837
  hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
838
            hb_direction_t direction,
839
            hb_glyph_extents_t *extents)
840
0
  {
841
0
    hb_bool_t ret = get_glyph_extents (glyph, extents);
842
843
0
    if (ret)
844
0
      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
845
846
0
    return ret;
847
0
  }
848
849
  hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
850
            hb_direction_t direction,
851
            hb_position_t *x, hb_position_t *y)
852
0
  {
853
0
    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
854
855
0
    if (ret)
856
0
      subtract_glyph_origin_for_direction (glyph, direction, x, y);
857
858
0
    return ret;
859
0
  }
860
861
  /* Generates gidDDD if glyph has no name. */
862
  void
863
  glyph_to_string (hb_codepoint_t glyph,
864
       char *s, unsigned int size)
865
0
  {
866
0
    if (get_glyph_name (glyph, s, size)) return;
867
868
0
    if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0)
869
0
      *s = '\0';
870
0
  }
871
872
  /* Parses gidDDD and uniUUUU strings automatically. */
873
  hb_bool_t
874
  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
875
         hb_codepoint_t *glyph)
876
0
  {
877
0
    if (get_glyph_from_name (s, len, glyph)) return true;
878
879
0
    if (len == -1) len = strlen (s);
880
881
    /* Straight glyph index. */
882
0
    if (hb_codepoint_parse (s, len, 10, glyph))
883
0
      return true;
884
885
0
    if (len > 3)
886
0
    {
887
      /* gidDDD syntax for glyph indices. */
888
0
      if (0 == strncmp (s, "gid", 3) &&
889
0
    hb_codepoint_parse (s + 3, len - 3, 10, glyph))
890
0
  return true;
891
892
      /* uniUUUU and other Unicode character indices. */
893
0
      hb_codepoint_t unichar;
894
0
      if (0 == strncmp (s, "uni", 3) &&
895
0
    hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
896
0
    get_nominal_glyph (unichar, glyph))
897
0
  return true;
898
0
    }
899
900
0
    return false;
901
0
  }
902
903
  bool is_synthetic () const
904
6.71M
  {
905
6.71M
    return x_embolden || y_embolden || slant;
906
6.71M
  }
907
908
  void changed ()
909
469k
  {
910
469k
    float upem = face->get_upem ();
911
912
469k
    x_multf = x_scale / upem;
913
469k
    y_multf = y_scale / upem;
914
469k
    bool x_neg = x_scale < 0;
915
469k
    x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem;
916
469k
    bool y_neg = y_scale < 0;
917
469k
    y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
918
919
469k
    x_strength = roundf (abs (x_scale) * x_embolden);
920
469k
    y_strength = roundf (abs (y_scale) * y_embolden);
921
922
469k
    slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
923
924
469k
    data.fini ();
925
926
469k
    serial++;
927
469k
  }
928
929
  hb_position_t em_mult (int16_t v, int64_t mult)
930
531M
  { return (hb_position_t) ((v * mult + 32768) >> 16); }
931
  hb_position_t em_multf (float v, float mult)
932
17.4M
  { return (hb_position_t) roundf (em_fmultf (v, mult)); }
933
  float em_fmultf (float v, float mult)
934
17.4M
  { return v * mult; }
935
  float em_fmult (int16_t v, float mult)
936
317k
  { return (float) v * mult; }
937
};
938
DECLARE_NULL_INSTANCE (hb_font_t);
939
940
941
#endif /* HB_FONT_HH */