Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/harfbuzz/src/hb-font.hh
Line
Count
Source
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_origins) \
59
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origins) \
60
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_kerning) \
61
0
  HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_kerning)) \
62
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_extents) \
63
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \
64
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \
65
0
  HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \
66
0
  HB_FONT_FUNC_IMPLEMENT (,draw_glyph_or_fail) \
67
0
  HB_FONT_FUNC_IMPLEMENT (,paint_glyph_or_fail) \
68
  /* ^--- Add new callbacks here */
69
70
struct hb_font_funcs_t
71
{
72
  hb_object_header_t header;
73
74
  struct {
75
#define HB_FONT_FUNC_IMPLEMENT(get_,name) void *name;
76
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
77
#undef HB_FONT_FUNC_IMPLEMENT
78
  } *user_data;
79
80
  struct {
81
#define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_destroy_func_t name;
82
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
83
#undef HB_FONT_FUNC_IMPLEMENT
84
  } *destroy;
85
86
  /* Don't access these directly.  Call font->get_*() instead. */
87
  union get_t {
88
    struct get_funcs_t {
89
#define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_font_##get_##name##_func_t name;
90
      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
91
#undef HB_FONT_FUNC_IMPLEMENT
92
    } f;
93
    void (*array[0
94
#define HB_FONT_FUNC_IMPLEMENT(get_,name) +1
95
      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
96
#undef HB_FONT_FUNC_IMPLEMENT
97
    ]) ();
98
  } get;
99
};
100
DECLARE_NULL_INSTANCE (hb_font_funcs_t);
101
102
103
/*
104
 * hb_font_t
105
 */
106
107
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font);
108
#include "hb-shaper-list.hh"
109
#undef HB_SHAPER_IMPLEMENT
110
111
struct hb_font_t
112
{
113
  hb_object_header_t header;
114
  hb_atomic_t<unsigned> serial;
115
  hb_atomic_t<unsigned> serial_coords;
116
117
  hb_font_t *parent;
118
  hb_face_t *face;
119
120
  int32_t x_scale;
121
  int32_t y_scale;
122
123
  bool is_synthetic;
124
125
  float x_embolden;
126
  float y_embolden;
127
  bool embolden_in_place;
128
  int32_t x_strength; /* x_embolden, in scaled units. */
129
  int32_t y_strength; /* y_embolden, in scaled units. */
130
131
  float slant;
132
  float slant_xy;
133
134
  float x_multf;
135
  float y_multf;
136
  int64_t x_mult;
137
  int64_t y_mult;
138
139
  unsigned int x_ppem;
140
  unsigned int y_ppem;
141
142
  float ptem;
143
144
  /* Font variation coordinates. */
145
  unsigned int instance_index;
146
  bool has_nonzero_coords;
147
  unsigned int num_coords;
148
  int *coords;
149
  float *design_coords;
150
151
  hb_font_funcs_t   *klass;
152
  void              *user_data;
153
  hb_destroy_func_t  destroy;
154
155
  hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */
156
157
158
  /* Convert from font-space to user-space */
159
  int64_t dir_mult (hb_direction_t direction)
160
0
  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
161
254M
  hb_position_t em_scale_x (int32_t v) { return em_mult (v, x_mult); }
162
0
  hb_position_t em_scale_y (int32_t v) { return em_mult (v, y_mult); }
163
0
  hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); }
164
4.30M
  hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
165
1.45M
  float em_fscale_x (int32_t v) { return em_fmult (v, x_multf); }
166
1.45M
  float em_fscale_y (int32_t v) { return em_fmult (v, y_multf); }
167
280k
  float em_fscalef_x (float v) { return em_fmultf (v, x_multf); }
168
280k
  float em_fscalef_y (float v) { return em_fmultf (v, y_multf); }
169
  hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
170
0
  { return em_mult (v, dir_mult (direction)); }
171
172
  /* Convert from parent-font user-space to our user-space */
173
  hb_position_t parent_scale_x_distance (hb_position_t v)
174
253M
  {
175
253M
    if (unlikely (parent && parent->x_scale && parent->x_scale != x_scale))
176
0
      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
177
253M
    return v;
178
253M
  }
179
  hb_position_t parent_scale_y_distance (hb_position_t v)
180
3.03M
  {
181
3.03M
    if (unlikely (parent && parent->y_scale && parent->y_scale != y_scale))
182
0
      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
183
3.03M
    return v;
184
3.03M
  }
185
  hb_position_t parent_scale_x_position (hb_position_t v)
186
1.15M
  { return parent_scale_x_distance (v); }
187
  hb_position_t parent_scale_y_position (hb_position_t v)
188
1.15M
  { return parent_scale_y_distance (v); }
189
190
  void parent_scale_distance (hb_position_t *x, hb_position_t *y)
191
534k
  {
192
534k
    *x = parent_scale_x_distance (*x);
193
534k
    *y = parent_scale_y_distance (*y);
194
534k
  }
195
  void parent_scale_position (hb_position_t *x, hb_position_t *y)
196
1.15M
  {
197
1.15M
    *x = parent_scale_x_position (*x);
198
1.15M
    *y = parent_scale_y_position (*y);
199
1.15M
  }
200
201
  void scale_glyph_extents (hb_glyph_extents_t *extents)
202
520k
  {
203
520k
    float x1 = em_fscale_x (extents->x_bearing);
204
520k
    float y1 = em_fscale_y (extents->y_bearing);
205
520k
    float x2 = x1 + em_fscale_x (extents->width);
206
520k
    float y2 = y1 + em_fscale_y (extents->height);
207
208
520k
    extents->x_bearing = floorf (x1);
209
520k
    extents->y_bearing = floorf (y1);
210
520k
    extents->width = ceilf (x2) - extents->x_bearing;
211
520k
    extents->height = ceilf (y2) - extents->y_bearing;
212
520k
  }
213
214
  void synthetic_glyph_extents (hb_glyph_extents_t *extents)
215
0
  {
216
    /* Slant. */
217
0
    if (slant_xy)
218
0
    {
219
      /* x_bearing/width and y_bearing/height are each clamped to the full
220
       * hb_position_t range independently by the extent producers, so their
221
       * sums and differences can overflow int32.  Accumulate in int64. */
222
0
      int64_t y1 = extents->y_bearing;
223
0
      int64_t y2 = (int64_t) extents->y_bearing + extents->height;
224
225
0
      int64_t x1 = (int64_t) extents->x_bearing + (int64_t) floorf (hb_min (y1 * slant_xy, y2 * slant_xy));
226
0
      int64_t x2 = (int64_t) extents->x_bearing + extents->width + (int64_t) ceilf (hb_max (y1 * slant_xy, y2 * slant_xy));
227
228
0
      extents->x_bearing = hb_clamp_to<hb_position_t> (x1);
229
0
      extents->width = hb_clamp_to<hb_position_t> (x2 - x1);
230
0
    }
231
232
    /* Embolden. */
233
0
    if (x_strength || y_strength)
234
0
    {
235
      /* Y */
236
0
      int y_shift = y_strength;
237
0
      if (y_scale < 0) y_shift = -y_shift;
238
0
      extents->y_bearing = hb_clamp_to<hb_position_t> ((int64_t) extents->y_bearing + y_shift);
239
0
      extents->height = hb_clamp_to<hb_position_t> ((int64_t) extents->height - y_shift);
240
241
      /* X */
242
0
      int x_shift = x_strength;
243
0
      if (x_scale < 0) x_shift = -x_shift;
244
0
      if (embolden_in_place)
245
0
  extents->x_bearing = hb_clamp_to<hb_position_t> ((int64_t) extents->x_bearing - x_shift / 2);
246
0
      extents->width = hb_clamp_to<hb_position_t> ((int64_t) extents->width + x_shift);
247
0
    }
248
0
  }
249
250
251
  /* Public getters */
252
253
  HB_INTERNAL bool has_func (unsigned int i);
254
  HB_INTERNAL bool has_func_set (unsigned int i);
255
256
  /* has_* ... */
257
#define HB_FONT_FUNC_IMPLEMENT(get_,name) \
258
  bool \
259
  has_##name##_func () \
260
105M
  { \
261
105M
    hb_font_funcs_t *funcs = this->klass; \
262
105M
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
263
105M
    return has_func (i); \
264
105M
  } \
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()
Unexecuted instantiation: hb_font_t::has_glyph_v_origin_func()
Unexecuted instantiation: hb_font_t::has_glyph_v_origins_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()
265
  bool \
266
  has_##name##_func_set () \
267
44.3M
  { \
268
44.3M
    hb_font_funcs_t *funcs = this->klass; \
269
44.3M
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
270
44.3M
    return has_func_set (i); \
271
44.3M
  }
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_variation_glyph_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()
272
149M
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
Unexecuted instantiation: hb_font_t::has_nominal_glyph_func_set()
Unexecuted instantiation: hb_font_t::has_nominal_glyphs_func_set()
hb_font_t::has_glyph_h_advance_func_set()
Line
Count
Source
272
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
hb_font_t::has_glyph_v_advance_func_set()
Line
Count
Source
272
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
hb_font_t::has_glyph_h_advances_func_set()
Line
Count
Source
272
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
Unexecuted instantiation: hb_font_t::has_glyph_v_advances_func_set()
hb_font_t::has_glyph_h_origin_func()
Line
Count
Source
272
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
Unexecuted instantiation: hb_font_t::has_glyph_h_origin_func_set()
hb_font_t::has_glyph_v_origin_func_set()
Line
Count
Source
272
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
hb_font_t::has_glyph_h_origins_func()
Line
Count
Source
272
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
Unexecuted instantiation: hb_font_t::has_glyph_h_origins_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_v_origins_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_h_kerning_func()
hb_font_t::has_glyph_extents_func()
Line
Count
Source
272
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
273
149M
#undef HB_FONT_FUNC_IMPLEMENT
274
149M
275
149M
  hb_bool_t get_font_h_extents (hb_font_extents_t *extents,
276
149M
        bool synthetic = true)
277
149M
  {
278
793k
    hb_memset (extents, 0, sizeof (*extents));
279
793k
    bool ret = klass->get.f.font_h_extents (this, user_data,
280
793k
              extents,
281
793k
              !klass->user_data ? nullptr : klass->user_data->font_h_extents);
282
283
793k
    if (synthetic && ret)
284
555k
    {
285
      /* Embolden */
286
555k
      int y_shift = y_scale < 0 ? -y_strength : y_strength;
287
555k
      extents->ascender += y_shift;
288
555k
    }
289
290
793k
    return ret;
291
793k
  }
292
  hb_bool_t get_font_v_extents (hb_font_extents_t *extents,
293
        bool synthetic = true)
294
0
  {
295
0
    hb_memset (extents, 0, sizeof (*extents));
296
0
    bool ret = klass->get.f.font_v_extents (this, user_data,
297
0
              extents,
298
0
              !klass->user_data ? nullptr : klass->user_data->font_v_extents);
299
300
0
    if (synthetic && ret)
301
0
    {
302
      /* Embolden */
303
0
      int x_shift = x_scale < 0 ? -x_strength : x_strength;
304
0
      if (embolden_in_place)
305
0
      {
306
0
  extents->ascender += x_shift / 2;
307
0
  extents->descender -= x_shift - x_shift / 2;
308
0
      }
309
0
      else
310
0
  extents->ascender += x_shift;
311
0
    }
312
313
0
    return ret;
314
0
  }
315
316
  bool has_glyph (hb_codepoint_t unicode)
317
2.44M
  {
318
2.44M
    hb_codepoint_t glyph;
319
2.44M
    return get_nominal_glyph (unicode, &glyph);
320
2.44M
  }
321
322
  hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
323
             hb_codepoint_t *glyph,
324
             hb_codepoint_t not_found = 0)
325
98.8M
  {
326
98.8M
    *glyph = not_found;
327
98.8M
    return klass->get.f.nominal_glyph (this, user_data,
328
98.8M
               unicode, glyph,
329
98.8M
               !klass->user_data ? nullptr : klass->user_data->nominal_glyph);
330
98.8M
  }
331
  unsigned int get_nominal_glyphs (unsigned int count,
332
           const hb_codepoint_t *first_unicode,
333
           unsigned int unicode_stride,
334
           hb_codepoint_t *first_glyph,
335
           unsigned int glyph_stride)
336
35.7M
  {
337
35.7M
    return klass->get.f.nominal_glyphs (this, user_data,
338
35.7M
          count,
339
35.7M
          first_unicode, unicode_stride,
340
35.7M
          first_glyph, glyph_stride,
341
35.7M
          !klass->user_data ? nullptr : klass->user_data->nominal_glyphs);
342
35.7M
  }
343
344
  hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
345
         hb_codepoint_t *glyph,
346
         hb_codepoint_t not_found = 0)
347
37.9k
  {
348
37.9k
    *glyph = not_found;
349
37.9k
    return klass->get.f.variation_glyph (this, user_data,
350
37.9k
           unicode, variation_selector, glyph,
351
37.9k
           !klass->user_data ? nullptr : klass->user_data->variation_glyph);
352
37.9k
  }
353
354
  hb_position_t get_glyph_h_advance (hb_codepoint_t glyph,
355
             bool synthetic = true)
356
26.5M
  {
357
26.5M
    hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data,
358
26.5M
                glyph,
359
26.5M
                !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
360
361
26.5M
    if (synthetic && x_strength && !embolden_in_place)
362
0
    {
363
      /* Embolden */
364
0
      hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
365
0
      advance += advance ? strength : 0;
366
0
    }
367
368
26.5M
    return advance;
369
26.5M
  }
370
371
  hb_position_t get_glyph_v_advance (hb_codepoint_t glyph,
372
             bool synthetic = true)
373
0
  {
374
0
    hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data,
375
0
                glyph,
376
0
                !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
377
378
0
    if (synthetic && y_strength && !embolden_in_place)
379
0
    {
380
      /* Embolden */
381
0
      hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
382
0
      advance += advance ? strength : 0;
383
0
    }
384
385
0
    return advance;
386
0
  }
387
388
  void get_glyph_h_advances (unsigned int count,
389
           const hb_codepoint_t *first_glyph,
390
           unsigned int glyph_stride,
391
           hb_position_t *first_advance,
392
           unsigned int advance_stride,
393
           bool synthetic = true)
394
48.2M
  {
395
48.2M
    klass->get.f.glyph_h_advances (this, user_data,
396
48.2M
           count,
397
48.2M
           first_glyph, glyph_stride,
398
48.2M
           first_advance, advance_stride,
399
48.2M
           !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
400
401
48.2M
    if (synthetic && x_strength && !embolden_in_place)
402
0
    {
403
      /* Embolden */
404
0
      hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
405
0
      for (unsigned int i = 0; i < count; i++)
406
0
      {
407
0
  *first_advance += *first_advance ? strength : 0;
408
0
  first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
409
0
      }
410
0
    }
411
48.2M
  }
412
413
  void get_glyph_v_advances (unsigned int count,
414
           const hb_codepoint_t *first_glyph,
415
           unsigned int glyph_stride,
416
           hb_position_t *first_advance,
417
           unsigned int advance_stride,
418
           bool synthetic = true)
419
315k
  {
420
315k
    klass->get.f.glyph_v_advances (this, user_data,
421
315k
           count,
422
315k
           first_glyph, glyph_stride,
423
315k
           first_advance, advance_stride,
424
315k
           !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
425
426
315k
    if (synthetic && y_strength && !embolden_in_place)
427
0
    {
428
      /* Embolden */
429
0
      hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
430
0
      for (unsigned int i = 0; i < count; i++)
431
0
      {
432
0
  *first_advance += *first_advance ? strength : 0;
433
0
  first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
434
0
      }
435
0
    }
436
315k
  }
437
438
  hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
439
        hb_position_t *x, hb_position_t *y,
440
        bool synthetic = true)
441
0
  {
442
0
    *x = *y = 0;
443
0
    bool ret = klass->get.f.glyph_h_origin (this, user_data,
444
0
              glyph, x, y,
445
0
              !klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
446
447
0
    if (synthetic && ret)
448
0
    {
449
      /* Slant is ignored as it does not affect glyph origin */
450
451
      /* Embolden */
452
0
      if (!embolden_in_place)
453
0
      {
454
0
        *x += x_scale < 0 ? -x_strength : x_strength;
455
0
  *y += y_scale < 0 ? -y_strength : y_strength;
456
0
      }
457
0
    }
458
459
0
    return ret;
460
0
  }
461
462
  hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
463
        hb_position_t *x, hb_position_t *y,
464
        bool synthetic = true)
465
0
  {
466
0
    *x = *y = 0;
467
0
    bool ret = klass->get.f.glyph_v_origin (this, user_data,
468
0
              glyph, x, y,
469
0
              !klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
470
471
0
    if (synthetic && ret)
472
0
    {
473
      /* Slant is ignored as it does not affect glyph origin */
474
475
      /* Embolden */
476
0
      if (!embolden_in_place)
477
0
      {
478
0
        *x += x_scale < 0 ? -x_strength : x_strength;
479
0
  *y += y_scale < 0 ? -y_strength : y_strength;
480
0
      }
481
0
    }
482
483
0
    return ret;
484
0
  }
485
486
  hb_bool_t get_glyph_h_origins (unsigned int count,
487
         const hb_codepoint_t *first_glyph,
488
         unsigned int glyph_stride,
489
         hb_position_t *first_x,
490
         unsigned int x_stride,
491
         hb_position_t *first_y,
492
         unsigned int y_stride,
493
         bool synthetic = true)
494
495
0
  {
496
0
    bool ret = klass->get.f.glyph_h_origins (this, user_data,
497
0
               count,
498
0
               first_glyph, glyph_stride,
499
0
               first_x, x_stride, first_y, y_stride,
500
0
               !klass->user_data ? nullptr : klass->user_data->glyph_h_origins);
501
502
0
    if (synthetic && ret)
503
0
    {
504
0
      hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength;
505
0
      hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
506
0
      for (unsigned i = 0; i < count; i++)
507
0
      {
508
  /* Slant is ignored as it does not affect glyph origin */
509
510
  /* Embolden */
511
0
  if (!embolden_in_place)
512
0
  {
513
0
    *first_x += x_shift;
514
0
    *first_y += y_shift;
515
0
  }
516
0
  first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
517
0
  first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
518
0
      }
519
0
    }
520
521
0
    return ret;
522
0
  }
523
524
  hb_bool_t get_glyph_v_origins (unsigned int count,
525
         const hb_codepoint_t *first_glyph,
526
         unsigned int glyph_stride,
527
         hb_position_t *first_x,
528
         unsigned int x_stride,
529
         hb_position_t *first_y,
530
         unsigned int y_stride,
531
         bool synthetic = true)
532
533
320k
  {
534
320k
    bool ret = klass->get.f.glyph_v_origins (this, user_data,
535
320k
               count,
536
320k
               first_glyph, glyph_stride,
537
320k
               first_x, x_stride, first_y, y_stride,
538
320k
               !klass->user_data ? nullptr : klass->user_data->glyph_v_origins);
539
540
320k
    if (synthetic && is_synthetic && ret)
541
0
    {
542
0
      hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength;
543
0
      hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
544
0
      for (unsigned i = 0; i < count; i++)
545
0
      {
546
  /* Slant is ignored as it does not affect glyph origin */
547
548
  /* Embolden */
549
0
  if (!embolden_in_place)
550
0
  {
551
0
    *first_x += x_shift;
552
0
    *first_y += y_shift;
553
0
  }
554
0
  first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
555
0
  first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
556
0
      }
557
0
    }
558
559
320k
    return ret;
560
320k
  }
561
562
  hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
563
             hb_codepoint_t right_glyph)
564
0
  {
565
#ifdef HB_DISABLE_DEPRECATED
566
    return 0;
567
#else
568
0
    return klass->get.f.glyph_h_kerning (this, user_data,
569
0
           left_glyph, right_glyph,
570
0
           !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning);
571
0
#endif
572
0
  }
573
574
  hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
575
             hb_codepoint_t bottom_glyph)
576
0
  {
577
#ifdef HB_DISABLE_DEPRECATED
578
    return 0;
579
#else
580
0
    return klass->get.f.glyph_v_kerning (this, user_data,
581
0
           top_glyph, bottom_glyph,
582
0
           !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning);
583
0
#endif
584
0
  }
585
586
  hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
587
             hb_glyph_extents_t *extents,
588
             bool synthetic = true)
589
1.06M
  {
590
1.06M
    hb_memset (extents, 0, sizeof (*extents));
591
592
    /* This is rather messy, but necessary. */
593
594
1.06M
    if (!synthetic)
595
534k
    {
596
534k
      return klass->get.f.glyph_extents (this, user_data,
597
534k
           glyph,
598
534k
           extents,
599
534k
           !klass->user_data ? nullptr : klass->user_data->glyph_extents);
600
534k
    }
601
535k
    if (!is_synthetic &&
602
535k
  klass->get.f.glyph_extents (this, user_data,
603
535k
            glyph,
604
535k
            extents,
605
535k
            !klass->user_data ? nullptr : klass->user_data->glyph_extents))
606
535k
      return true;
607
608
    /* Try getting extents from paint(), then draw(), *then* get_extents()
609
     * and apply synthetic settings in the last case. */
610
611
0
#ifndef HB_NO_PAINT
612
0
    hb_paint_extents_context_t paint_extents;
613
0
    if (paint_glyph_or_fail (glyph,
614
0
           hb_paint_extents_get_funcs (), &paint_extents,
615
0
           0, 0))
616
0
    {
617
0
      *extents = paint_extents.get_extents ().to_glyph_extents ();
618
0
      return true;
619
0
    }
620
0
#endif
621
622
0
#ifndef HB_NO_DRAW
623
0
    hb_extents_t<> draw_extents;
624
0
    if (draw_glyph_or_fail (glyph,
625
0
          hb_draw_extents_get_funcs (), &draw_extents))
626
0
    {
627
0
      *extents = draw_extents.to_glyph_extents ();
628
0
      return true;
629
0
    }
630
0
#endif
631
632
0
    bool ret = klass->get.f.glyph_extents (this, user_data,
633
0
             glyph,
634
0
             extents,
635
0
             !klass->user_data ? nullptr : klass->user_data->glyph_extents);
636
0
    if (ret)
637
0
      synthetic_glyph_extents (extents);
638
639
0
    return ret;
640
0
  }
641
642
  hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
643
             hb_position_t *x, hb_position_t *y,
644
             bool synthetic = true)
645
0
  {
646
0
    *x = *y = 0;
647
0
    bool ret = klass->get.f.glyph_contour_point (this, user_data,
648
0
             glyph, point_index,
649
0
             x, y,
650
0
             !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
651
652
0
    if (synthetic && ret)
653
0
    {
654
      /* Slant */
655
0
      if (slant_xy)
656
0
        *x += roundf (*y * slant_xy);
657
658
      /* Embolden */
659
0
      if (!embolden_in_place)
660
0
      {
661
0
  int x_shift = x_scale < 0 ? -x_strength : x_strength;
662
0
  *x += x_shift;
663
0
      }
664
0
    }
665
666
0
    return ret;
667
0
  }
668
669
  hb_bool_t get_glyph_name (hb_codepoint_t glyph,
670
          char *name, unsigned int size)
671
0
  {
672
0
    if (size) *name = '\0';
673
0
    return klass->get.f.glyph_name (this, user_data,
674
0
            glyph,
675
0
            name, size,
676
0
            !klass->user_data ? nullptr : klass->user_data->glyph_name);
677
0
  }
678
679
  hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
680
         hb_codepoint_t *glyph)
681
0
  {
682
0
    *glyph = 0;
683
0
    if (len == -1) len = strlen (name);
684
0
    return klass->get.f.glyph_from_name (this, user_data,
685
0
           name, len,
686
0
           glyph,
687
0
           !klass->user_data ? nullptr : klass->user_data->glyph_from_name);
688
0
  }
689
690
  bool draw_glyph_or_fail (hb_codepoint_t glyph,
691
         hb_draw_funcs_t *draw_funcs, void *draw_data,
692
         bool synthetic = true)
693
52.5k
  {
694
52.5k
#ifndef HB_NO_DRAW
695
52.5k
#ifndef HB_NO_OUTLINE
696
52.5k
    bool embolden = x_strength || y_strength;
697
52.5k
    bool slanted = slant_xy;
698
52.5k
    synthetic = synthetic && (embolden || slanted);
699
#else
700
    synthetic = false;
701
#endif
702
703
52.5k
    if (!synthetic)
704
52.5k
    {
705
52.5k
      return klass->get.f.draw_glyph_or_fail (this, user_data,
706
52.5k
                glyph,
707
52.5k
                draw_funcs, draw_data,
708
52.5k
                !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail);
709
52.5k
    }
710
711
0
#ifndef HB_NO_OUTLINE
712
713
0
    hb_outline_t outline;
714
0
    outline.budget_remaining = draw_funcs->get_budget_remaining_ptr (draw_data);
715
0
    if (!klass->get.f.draw_glyph_or_fail (this, user_data,
716
0
            glyph,
717
0
            hb_outline_recording_pen_get_funcs (), &outline,
718
0
            !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail))
719
0
      return false;
720
721
    // Slant before embolden; produces nicer results.
722
723
0
    if (slanted)
724
0
    {
725
0
      hb_position_t xo = 0, yo = 0;
726
0
      get_glyph_h_origin (glyph, &xo, &yo, false);
727
0
      outline.translate (-xo, -yo);
728
0
      outline.slant (slant_xy);
729
0
      outline.translate (xo, yo);
730
0
    }
731
732
0
    if (embolden)
733
0
    {
734
0
      float x_shift = embolden_in_place ? 0 : (float) x_strength / 2;
735
0
      float y_shift = (float) y_strength / 2;
736
0
      if (x_scale < 0) x_shift = -x_shift;
737
0
      if (y_scale < 0) y_shift = -y_shift;
738
0
      outline.embolden (x_strength, y_strength, x_shift, y_shift);
739
0
    }
740
741
0
    outline.replay (draw_funcs, draw_data);
742
743
0
    return true;
744
0
#endif
745
0
#endif
746
0
    return false;
747
0
  }
748
749
  bool paint_glyph_or_fail (hb_codepoint_t glyph,
750
          hb_paint_funcs_t *paint_funcs, void *paint_data,
751
          unsigned int palette,
752
          hb_color_t foreground,
753
          bool synthetic = true)
754
0
  {
755
0
#ifndef HB_NO_PAINT
756
    /* Slant */
757
0
    if (synthetic && slant_xy)
758
0
      hb_paint_push_transform (paint_funcs, paint_data,
759
0
             1.f, 0.f,
760
0
             slant_xy, 1.f,
761
0
             0.f, 0.f);
762
763
0
    bool ret = klass->get.f.paint_glyph_or_fail (this, user_data,
764
0
             glyph,
765
0
             paint_funcs, paint_data,
766
0
             palette, foreground,
767
0
             !klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail);
768
769
0
    if (synthetic && slant_xy)
770
0
      hb_paint_pop_transform (paint_funcs, paint_data);
771
772
0
    return ret;
773
0
#endif
774
0
    return false;
775
0
  }
776
777
  /* A bit higher-level, and with fallback */
778
779
  HB_INTERNAL
780
  void paint_glyph (hb_codepoint_t glyph,
781
        hb_paint_funcs_t *paint_funcs, void *paint_data,
782
        unsigned int palette,
783
        hb_color_t foreground);
784
785
  void get_h_extents_with_fallback (hb_font_extents_t *extents)
786
318k
  {
787
318k
    if (!get_font_h_extents (extents))
788
0
    {
789
0
      extents->ascender = y_scale * .8;
790
0
      extents->descender = extents->ascender - y_scale;
791
0
      extents->line_gap = 0;
792
0
    }
793
318k
  }
794
  void get_v_extents_with_fallback (hb_font_extents_t *extents)
795
0
  {
796
0
    if (!get_font_v_extents (extents))
797
0
    {
798
0
      extents->ascender = x_scale / 2;
799
0
      extents->descender = extents->ascender - x_scale;
800
0
      extents->line_gap = 0;
801
0
    }
802
0
  }
803
804
  void get_extents_for_direction (hb_direction_t direction,
805
          hb_font_extents_t *extents)
806
0
  {
807
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
808
0
      get_h_extents_with_fallback (extents);
809
0
    else
810
0
      get_v_extents_with_fallback (extents);
811
0
  }
812
813
  void get_glyph_advance_for_direction (hb_codepoint_t glyph,
814
          hb_direction_t direction,
815
          hb_position_t *x, hb_position_t *y)
816
0
  {
817
0
    *x = *y = 0;
818
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
819
0
      *x = get_glyph_h_advance (glyph);
820
0
    else
821
0
      *y = get_glyph_v_advance (glyph);
822
0
  }
823
  void get_glyph_advances_for_direction (hb_direction_t direction,
824
           unsigned int count,
825
           const hb_codepoint_t *first_glyph,
826
           unsigned glyph_stride,
827
           hb_position_t *first_advance,
828
           unsigned advance_stride)
829
0
  {
830
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
831
0
      get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
832
0
    else
833
0
      get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
834
0
  }
835
836
  void apply_offset (hb_position_t *x, hb_position_t *y,
837
         hb_position_t dx, hb_position_t dy,
838
         signed mult)
839
0
  {
840
0
    assert (mult == -1 || mult == +1);
841
0
842
0
    *x += dx * mult;
843
0
    *y += dy * mult;
844
0
  }
845
  void add_offset (hb_position_t *x, hb_position_t *y,
846
       hb_position_t dx, hb_position_t dy)
847
0
  {
848
0
    *x += dx;
849
0
    *y += dy;
850
0
  }
851
  void subtract_offset (hb_position_t *x, hb_position_t *y,
852
      hb_position_t dx, hb_position_t dy)
853
624k
  {
854
624k
    *x -= dx;
855
624k
    *y -= dy;
856
624k
  }
857
858
  void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
859
              hb_position_t *x, hb_position_t *y)
860
0
  {
861
0
    *x = get_glyph_h_advance (glyph) / 2;
862
863
0
    hb_font_extents_t extents;
864
0
    get_h_extents_with_fallback (&extents);
865
0
    *y = extents.ascender;
866
0
  }
867
868
  void apply_glyph_h_origins_with_fallback (hb_buffer_t *buf, int mult)
869
0
  {
870
0
    bool has_ascender = false;
871
0
    hb_position_t ascender = 0;
872
873
0
    struct { hb_position_t x, y; } origins[32];
874
875
0
    unsigned int offset = 0;
876
0
    unsigned int count = buf->len;
877
0
    while (offset < count)
878
0
    {
879
0
      unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
880
0
      if (!get_glyph_h_origins (n,
881
0
        &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
882
0
        &origins[0].x, sizeof (origins[0]),
883
0
        &origins[0].y, sizeof (origins[0])))
884
0
      {
885
0
        if (get_glyph_v_origins (n,
886
0
          &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
887
0
          &origins[0].x, sizeof (origins[0]),
888
0
          &origins[0].y, sizeof (origins[0])))
889
0
  {
890
0
    if (!has_ascender)
891
0
    {
892
0
      hb_font_extents_t extents;
893
0
      get_h_extents_with_fallback (&extents);
894
0
      ascender = extents.ascender;
895
0
      has_ascender = true;
896
0
    }
897
898
    /* We got the v_origins, adjust them to h_origins. */
899
0
    for (unsigned j = 0; j < n; j++)
900
0
    {
901
0
      hb_codepoint_t glyph = buf->info[offset + j].codepoint;
902
0
      origins[j].x -= get_glyph_h_advance (glyph) / 2;
903
0
      origins[j].y -= ascender;
904
0
    }
905
0
  }
906
0
  else
907
0
  {
908
0
    mult = 0; /* Indicates all origins[].x and origins[].y values are 0, therefore we can skip adjusting offsets below */
909
0
  }
910
0
      }
911
912
0
      assert (mult == -1 || mult == +1 || mult == 0);
913
0
      if (mult == +1)
914
0
        for (unsigned j = 0; j < n; j++)
915
0
  {
916
0
    hb_glyph_position_t *pos = &buf->pos[offset + j];
917
0
    add_offset (&pos->x_offset, &pos->y_offset,
918
0
          origins[j].x, origins[j].y);
919
0
  }
920
0
      else if (mult == -1)
921
0
  for (unsigned j = 0; j < n; j++)
922
0
  {
923
0
    hb_glyph_position_t *pos = &buf->pos[offset + j];
924
0
    subtract_offset (&pos->x_offset, &pos->y_offset,
925
0
         origins[j].x, origins[j].y);
926
0
  }
927
      /* else if (mult == 0) --> Do nothing */
928
929
0
      offset += n;
930
0
    }
931
0
  }
932
  void apply_glyph_v_origins_with_fallback (hb_buffer_t *buf, int mult)
933
157k
  {
934
157k
    bool has_ascender = false;
935
157k
    hb_position_t ascender = 0;
936
937
157k
    struct { hb_position_t x, y; } origins[32];
938
939
157k
    unsigned int offset = 0;
940
157k
    unsigned int count = buf->len;
941
318k
    while (offset < count)
942
160k
    {
943
160k
      unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
944
160k
      if (!get_glyph_v_origins (n,
945
160k
        &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
946
160k
        &origins[0].x, sizeof (origins[0]),
947
160k
        &origins[0].y, sizeof (origins[0])))
948
0
      {
949
0
  if (get_glyph_h_origins (n,
950
0
         &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
951
0
         &origins[0].x, sizeof (origins[0]),
952
0
         &origins[0].y, sizeof (origins[0])))
953
0
  {
954
0
    if (!has_ascender)
955
0
    {
956
0
      hb_font_extents_t extents;
957
0
      get_h_extents_with_fallback (&extents);
958
0
      ascender = extents.ascender;
959
0
      has_ascender = true;
960
0
    }
961
962
    /* We got the h_origins, adjust them to v_origins. */
963
0
    for (unsigned j = 0; j < n; j++)
964
0
    {
965
0
      hb_codepoint_t glyph = buf->info[offset + j].codepoint;
966
0
      origins[j].x += get_glyph_h_advance (glyph) / 2;
967
0
      origins[j].y += ascender;
968
0
    }
969
0
  }
970
0
  else
971
0
  {
972
0
    mult = 0; /* Indicates all origins[].x and origins[].y values are 0, therefore we can skip adjusting offsets below */
973
0
  }
974
0
      }
975
976
160k
      assert (mult == -1 || mult == +1 || mult == 0);
977
160k
      if (mult == +1)
978
0
        for (unsigned j = 0; j < n; j++)
979
0
  {
980
0
    hb_glyph_position_t *pos = &buf->pos[offset + j];
981
0
    add_offset (&pos->x_offset, &pos->y_offset,
982
0
          origins[j].x, origins[j].y);
983
0
  }
984
160k
      else if (mult == -1)
985
785k
  for (unsigned j = 0; j < n; j++)
986
624k
  {
987
624k
    hb_glyph_position_t *pos = &buf->pos[offset + j];
988
624k
    subtract_offset (&pos->x_offset, &pos->y_offset,
989
624k
         origins[j].x, origins[j].y);
990
624k
  }
991
      /* else if (mult == 0) --> Do nothing */
992
993
160k
      offset += n;
994
160k
    }
995
157k
  }
996
997
  void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
998
           hb_position_t *x, hb_position_t *y)
999
0
  {
1000
0
    if (!get_glyph_h_origin (glyph, x, y) &&
1001
0
   get_glyph_v_origin (glyph, x, y))
1002
0
    {
1003
0
      hb_position_t dx, dy;
1004
0
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
1005
0
      subtract_offset (x, y, dx, dy);
1006
0
    }
1007
0
  }
1008
  void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
1009
           hb_position_t *x, hb_position_t *y)
1010
0
  {
1011
0
    if (!get_glyph_v_origin (glyph, x, y) &&
1012
0
   get_glyph_h_origin (glyph, x, y))
1013
0
    {
1014
0
      hb_position_t dx, dy;
1015
0
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
1016
0
      add_offset (x, y, dx, dy);
1017
0
    }
1018
0
  }
1019
1020
  void get_glyph_origin_for_direction (hb_codepoint_t glyph,
1021
               hb_direction_t direction,
1022
               hb_position_t *x, hb_position_t *y)
1023
0
  {
1024
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
1025
0
      get_glyph_h_origin_with_fallback (glyph, x, y);
1026
0
    else
1027
0
      get_glyph_v_origin_with_fallback (glyph, x, y);
1028
0
  }
1029
1030
  void add_glyph_h_origins (hb_buffer_t *buf)
1031
0
  {
1032
0
    apply_glyph_h_origins_with_fallback (buf, +1);
1033
0
  }
1034
  void add_glyph_v_origins (hb_buffer_t *buf)
1035
0
  {
1036
0
    apply_glyph_v_origins_with_fallback (buf, +1);
1037
0
  }
1038
  void add_glyph_origin_for_direction (hb_codepoint_t glyph,
1039
               hb_direction_t direction,
1040
               hb_position_t *x, hb_position_t *y)
1041
0
  {
1042
0
    hb_position_t origin_x, origin_y;
1043
0
    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
1044
0
    add_offset (x, y, origin_x, origin_y);
1045
0
  }
1046
1047
  void subtract_glyph_h_origins (hb_buffer_t *buf)
1048
0
  {
1049
0
    apply_glyph_h_origins_with_fallback (buf, -1);
1050
0
  }
1051
  void subtract_glyph_v_origins (hb_buffer_t *buf)
1052
157k
  {
1053
157k
    apply_glyph_v_origins_with_fallback (buf, -1);
1054
157k
  }
1055
  void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
1056
              hb_direction_t direction,
1057
              hb_position_t *x, hb_position_t *y)
1058
0
  {
1059
0
    hb_position_t origin_x, origin_y;
1060
0
    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
1061
0
    subtract_offset (x, y, origin_x, origin_y);
1062
0
  }
1063
1064
  void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
1065
          hb_direction_t direction,
1066
          hb_position_t *x, hb_position_t *y)
1067
0
  {
1068
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
1069
0
      *y = 0;
1070
0
      *x = get_glyph_h_kerning (first_glyph, second_glyph);
1071
0
    } else {
1072
0
      *x = 0;
1073
0
      *y = get_glyph_v_kerning (first_glyph, second_glyph);
1074
0
    }
1075
0
  }
1076
1077
  hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
1078
            hb_direction_t direction,
1079
            hb_glyph_extents_t *extents)
1080
0
  {
1081
0
    hb_bool_t ret = get_glyph_extents (glyph, extents);
1082
1083
0
    if (ret)
1084
0
      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
1085
1086
0
    return ret;
1087
0
  }
1088
1089
  hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
1090
            hb_direction_t direction,
1091
            hb_position_t *x, hb_position_t *y)
1092
0
  {
1093
0
    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
1094
1095
0
    if (ret)
1096
0
      subtract_glyph_origin_for_direction (glyph, direction, x, y);
1097
1098
0
    return ret;
1099
0
  }
1100
1101
  /* Generates gidDDD if glyph has no name. */
1102
  void
1103
  glyph_to_string (hb_codepoint_t glyph,
1104
       char *s, unsigned int size)
1105
0
  {
1106
0
    if (get_glyph_name (glyph, s, size)) return;
1107
1108
0
    if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0)
1109
0
      *s = '\0';
1110
0
  }
1111
1112
  /* Parses gidDDD and uniUUUU strings automatically. */
1113
  hb_bool_t
1114
  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
1115
         hb_codepoint_t *glyph)
1116
0
  {
1117
0
    if (get_glyph_from_name (s, len, glyph)) return true;
1118
1119
0
    if (len == -1) len = strlen (s);
1120
1121
    /* Straight glyph index. */
1122
0
    if (hb_codepoint_parse (s, len, 10, glyph))
1123
0
      return true;
1124
1125
0
    if (len > 3)
1126
0
    {
1127
      /* gidDDD syntax for glyph indices. */
1128
0
      if (0 == strncmp (s, "gid", 3) &&
1129
0
    hb_codepoint_parse (s + 3, len - 3, 10, glyph))
1130
0
  return true;
1131
1132
      /* uniUUUU and other Unicode character indices. */
1133
0
      hb_codepoint_t unichar;
1134
0
      if (0 == strncmp (s, "uni", 3) &&
1135
0
    hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
1136
0
    get_nominal_glyph (unichar, glyph))
1137
0
  return true;
1138
0
    }
1139
1140
0
    return false;
1141
0
  }
1142
1143
  void changed ()
1144
882k
  {
1145
882k
    float upem = face->get_upem ();
1146
1147
882k
    x_multf = x_scale / upem;
1148
882k
    y_multf = y_scale / upem;
1149
882k
    x_mult = (int64_t) x_scale * 0x10000 / upem;
1150
882k
    y_mult = (int64_t) y_scale * 0x10000 / upem;
1151
1152
882k
    is_synthetic =  x_embolden || y_embolden || slant;
1153
1154
882k
    x_strength = roundf (abs (x_scale) * x_embolden);
1155
882k
    y_strength = roundf (abs (y_scale) * y_embolden);
1156
1157
882k
    slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
1158
1159
882k
    data.fini ();
1160
1161
882k
    serial++;
1162
882k
  }
1163
1164
  hb_position_t em_mult (int32_t v, int64_t mult)
1165
254M
  { return (hb_position_t) ((v * mult + 32768) >> 16); }
1166
  hb_position_t em_multf (float v, float mult)
1167
4.30M
  { return (hb_position_t) roundf (em_fmultf (v, mult)); }
1168
  float em_fmultf (float v, float mult)
1169
4.86M
  { return v * mult; }
1170
  float em_fmult (int32_t v, float mult)
1171
2.90M
  { return (float) v * mult; }
1172
};
1173
DECLARE_NULL_INSTANCE (hb_font_t);
1174
1175
1176
#endif /* HB_FONT_HH */