Coverage Report

Created: 2025-11-16 09:57

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