Coverage Report

Created: 2025-08-29 06:20

/src/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_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
0
  hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
162
0
  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
0
  hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
165
0
  float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); }
166
0
  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
0
  {
203
0
    float x1 = em_scale_x (extents->x_bearing);
204
0
    float y1 = em_scale_y (extents->y_bearing);
205
0
    float x2 = em_scale_x (extents->x_bearing + extents->width);
206
0
    float y2 = em_scale_y (extents->y_bearing + extents->height);
207
208
0
    extents->x_bearing = roundf (x1);
209
0
    extents->y_bearing = roundf (y1);
210
0
    extents->width = roundf (x2) - extents->x_bearing;
211
0
    extents->height = roundf (y2) - extents->y_bearing;
212
0
  }
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
370k
  { \
260
370k
    hb_font_funcs_t *funcs = this->klass; \
261
370k
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
262
370k
    return has_func (i); \
263
370k
  } \
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
259
370k
  { \
260
370k
    hb_font_funcs_t *funcs = this->klass; \
261
370k
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
262
370k
    return has_func (i); \
263
370k
  } \
Unexecuted instantiation: hb_font_t::has_glyph_v_origin_func()
Unexecuted instantiation: hb_font_t::has_glyph_h_origins_func()
Unexecuted instantiation: hb_font_t::has_glyph_v_origins_func()
hb_font_t::has_glyph_h_kerning_func()
Line
Count
Source
259
32
  { \
260
32
    hb_font_funcs_t *funcs = this->klass; \
261
32
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
262
32
    return has_func (i); \
263
32
  } \
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()
264
  bool \
265
  has_##name##_func_set () \
266
633k
  { \
267
633k
    hb_font_funcs_t *funcs = this->klass; \
268
633k
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
269
633k
    return has_func_set (i); \
270
633k
  }
Unexecuted instantiation: hb_font_t::has_font_h_extents_func_set()
Unexecuted instantiation: hb_font_t::has_font_v_extents_func_set()
hb_font_t::has_nominal_glyph_func_set()
Line
Count
Source
266
123k
  { \
267
123k
    hb_font_funcs_t *funcs = this->klass; \
268
123k
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
269
123k
    return has_func_set (i); \
270
123k
  }
Unexecuted instantiation: hb_font_t::has_nominal_glyphs_func_set()
Unexecuted instantiation: hb_font_t::has_variation_glyph_func_set()
hb_font_t::has_glyph_h_advance_func_set()
Line
Count
Source
266
123k
  { \
267
123k
    hb_font_funcs_t *funcs = this->klass; \
268
123k
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
269
123k
    return has_func_set (i); \
270
123k
  }
Unexecuted instantiation: hb_font_t::has_glyph_v_advance_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_h_advances_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_v_advances_func_set()
hb_font_t::has_glyph_h_origin_func_set()
Line
Count
Source
266
386k
  { \
267
386k
    hb_font_funcs_t *funcs = this->klass; \
268
386k
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
269
386k
    return has_func_set (i); \
270
386k
  }
Unexecuted instantiation: hb_font_t::has_glyph_v_origin_func_set()
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_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
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
272
#undef HB_FONT_FUNC_IMPLEMENT
273
274
  hb_bool_t get_font_h_extents (hb_font_extents_t *extents,
275
        bool synthetic = true)
276
0
  {
277
0
    hb_memset (extents, 0, sizeof (*extents));
278
0
    bool ret = klass->get.f.font_h_extents (this, user_data,
279
0
              extents,
280
0
              !klass->user_data ? nullptr : klass->user_data->font_h_extents);
281
282
0
    if (synthetic && ret)
283
0
    {
284
      /* Embolden */
285
0
      int y_shift = y_scale < 0 ? -y_strength : y_strength;
286
0
      extents->ascender += y_shift;
287
0
    }
288
289
0
    return ret;
290
0
  }
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
0
  {
317
0
    hb_codepoint_t glyph;
318
0
    return get_nominal_glyph (unicode, &glyph);
319
0
  }
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
968k
  {
325
968k
    *glyph = not_found;
326
968k
    return klass->get.f.nominal_glyph (this, user_data,
327
968k
               unicode, glyph,
328
968k
               !klass->user_data ? nullptr : klass->user_data->nominal_glyph);
329
968k
  }
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
123k
  {
336
123k
    return klass->get.f.nominal_glyphs (this, user_data,
337
123k
          count,
338
123k
          first_unicode, unicode_stride,
339
123k
          first_glyph, glyph_stride,
340
123k
          !klass->user_data ? nullptr : klass->user_data->nominal_glyphs);
341
123k
  }
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
0
  {
347
0
    *glyph = not_found;
348
0
    return klass->get.f.variation_glyph (this, user_data,
349
0
           unicode, variation_selector, glyph,
350
0
           !klass->user_data ? nullptr : klass->user_data->variation_glyph);
351
0
  }
352
353
  hb_position_t get_glyph_h_advance (hb_codepoint_t glyph,
354
             bool synthetic = true)
355
947k
  {
356
947k
    hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data,
357
947k
                glyph,
358
947k
                !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
359
360
947k
    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
947k
    return advance;
368
947k
  }
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
123k
  {
394
123k
    klass->get.f.glyph_h_advances (this, user_data,
395
123k
           count,
396
123k
           first_glyph, glyph_stride,
397
123k
           first_advance, advance_stride,
398
123k
           !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
399
400
123k
    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
123k
  }
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
0
  {
419
0
    klass->get.f.glyph_v_advances (this, user_data,
420
0
           count,
421
0
           first_glyph, glyph_stride,
422
0
           first_advance, advance_stride,
423
0
           !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
424
425
0
    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
0
  }
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
2.84M
  {
441
2.84M
    *x = *y = 0;
442
2.84M
    bool ret = klass->get.f.glyph_h_origin (this, user_data,
443
2.84M
              glyph, x, y,
444
2.84M
              !klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
445
446
2.84M
    if (synthetic && ret)
447
0
    {
448
      /* Slant */
449
0
      if (slant_xy)
450
0
  *x += roundf (*y * slant_xy);
451
452
      /* Embolden */
453
0
      if (!embolden_in_place)
454
0
      {
455
0
        *x += x_scale < 0 ? -x_strength : x_strength;
456
0
  *y += y_scale < 0 ? -y_strength : y_strength;
457
0
      }
458
0
    }
459
460
2.84M
    return ret;
461
2.84M
  }
462
463
  hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
464
        hb_position_t *x, hb_position_t *y,
465
        bool synthetic = true)
466
0
  {
467
0
    *x = *y = 0;
468
0
    bool ret = klass->get.f.glyph_v_origin (this, user_data,
469
0
              glyph, x, y,
470
0
              !klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
471
472
0
    if (synthetic && ret)
473
0
    {
474
      /* Slant */
475
0
      if (slant_xy)
476
0
  *x += roundf (*y * slant_xy);
477
478
      /* Embolden */
479
0
      if (!embolden_in_place)
480
0
      {
481
0
        *x += x_scale < 0 ? -x_strength : x_strength;
482
0
  *y += y_scale < 0 ? -y_strength : y_strength;
483
0
      }
484
0
    }
485
486
0
    return ret;
487
0
  }
488
489
  hb_bool_t get_glyph_h_origins (unsigned int count,
490
         const hb_codepoint_t *first_glyph,
491
         unsigned int glyph_stride,
492
         hb_position_t *first_x,
493
         unsigned int x_stride,
494
         hb_position_t *first_y,
495
         unsigned int y_stride,
496
         bool synthetic = true)
497
498
386k
  {
499
386k
    bool ret = klass->get.f.glyph_h_origins (this, user_data,
500
386k
               count,
501
386k
               first_glyph, glyph_stride,
502
386k
               first_x, x_stride, first_y, y_stride,
503
386k
               !klass->user_data ? nullptr : klass->user_data->glyph_h_origins);
504
505
386k
    if (synthetic && ret)
506
386k
    {
507
386k
      hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength;
508
386k
      hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
509
3.22M
      for (unsigned i = 0; i < count; i++)
510
2.84M
      {
511
  /* Slant */
512
2.84M
  if (slant_xy)
513
0
    *first_x += roundf (*first_y * slant_xy);
514
515
  /* Embolden */
516
2.84M
  if (!embolden_in_place)
517
0
  {
518
0
    *first_x += x_shift;
519
0
    *first_y += y_shift;
520
0
  }
521
2.84M
      }
522
386k
      first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
523
386k
      first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
524
386k
    }
525
526
386k
    return ret;
527
386k
  }
528
529
  hb_bool_t get_glyph_v_origins (unsigned int count,
530
         const hb_codepoint_t *first_glyph,
531
         unsigned int glyph_stride,
532
         hb_position_t *first_x,
533
         unsigned int x_stride,
534
         hb_position_t *first_y,
535
         unsigned int y_stride,
536
         bool synthetic = true)
537
538
0
  {
539
0
    bool ret = klass->get.f.glyph_v_origins (this, user_data,
540
0
               count,
541
0
               first_glyph, glyph_stride,
542
0
               first_x, x_stride, first_y, y_stride,
543
0
               !klass->user_data ? nullptr : klass->user_data->glyph_v_origins);
544
545
0
    if (synthetic && is_synthetic && ret)
546
0
    {
547
0
      hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength;
548
0
      hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
549
0
      for (unsigned i = 0; i < count; i++)
550
0
      {
551
  /* Slant */
552
0
  if (slant_xy)
553
0
    *first_x += roundf (*first_y * slant_xy);
554
555
  /* Embolden */
556
0
  if (!embolden_in_place)
557
0
  {
558
0
    *first_x += x_shift;
559
0
    *first_y += y_shift;
560
0
  }
561
0
      }
562
0
      first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
563
0
      first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
564
0
    }
565
566
0
    return ret;
567
0
  }
568
569
  hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
570
             hb_codepoint_t right_glyph)
571
0
  {
572
#ifdef HB_DISABLE_DEPRECATED
573
    return 0;
574
#else
575
0
    return klass->get.f.glyph_h_kerning (this, user_data,
576
0
           left_glyph, right_glyph,
577
0
           !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning);
578
0
#endif
579
0
  }
580
581
  hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
582
             hb_codepoint_t bottom_glyph)
583
0
  {
584
#ifdef HB_DISABLE_DEPRECATED
585
    return 0;
586
#else
587
0
    return klass->get.f.glyph_v_kerning (this, user_data,
588
0
           top_glyph, bottom_glyph,
589
0
           !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning);
590
0
#endif
591
0
  }
592
593
  hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
594
             hb_glyph_extents_t *extents,
595
             bool synthetic = true)
596
64
  {
597
64
    hb_memset (extents, 0, sizeof (*extents));
598
599
    /* This is rather messy, but necessary. */
600
601
64
    if (!synthetic)
602
0
    {
603
0
      return klass->get.f.glyph_extents (this, user_data,
604
0
           glyph,
605
0
           extents,
606
0
           !klass->user_data ? nullptr : klass->user_data->glyph_extents);
607
0
    }
608
64
    if (!is_synthetic &&
609
64
  klass->get.f.glyph_extents (this, user_data,
610
64
            glyph,
611
64
            extents,
612
64
            !klass->user_data ? nullptr : klass->user_data->glyph_extents))
613
64
      return true;
614
615
    /* Try getting extents from paint(), then draw(), *then* get_extents()
616
     * and apply synthetic settings in the last case. */
617
618
0
#ifndef HB_NO_PAINT
619
0
    hb_paint_extents_context_t paint_extents;
620
0
    if (paint_glyph_or_fail (glyph,
621
0
           hb_paint_extents_get_funcs (), &paint_extents,
622
0
           0, 0))
623
0
    {
624
0
      *extents = paint_extents.get_extents ().to_glyph_extents ();
625
0
      return true;
626
0
    }
627
0
#endif
628
629
0
#ifndef HB_NO_DRAW
630
0
    hb_extents_t<> draw_extents;
631
0
    if (draw_glyph_or_fail (glyph,
632
0
          hb_draw_extents_get_funcs (), &draw_extents))
633
0
    {
634
0
      *extents = draw_extents.to_glyph_extents ();
635
0
      return true;
636
0
    }
637
0
#endif
638
639
0
    bool ret = klass->get.f.glyph_extents (this, user_data,
640
0
             glyph,
641
0
             extents,
642
0
             !klass->user_data ? nullptr : klass->user_data->glyph_extents);
643
0
    if (ret)
644
0
      synthetic_glyph_extents (extents);
645
646
0
    return ret;
647
0
  }
648
649
  hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
650
             hb_position_t *x, hb_position_t *y,
651
             bool synthetic = true)
652
0
  {
653
0
    *x = *y = 0;
654
0
    bool ret = klass->get.f.glyph_contour_point (this, user_data,
655
0
             glyph, point_index,
656
0
             x, y,
657
0
             !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
658
659
0
    if (synthetic && ret)
660
0
    {
661
      /* Slant */
662
0
      if (slant_xy)
663
0
        *x += roundf (*y * slant_xy);
664
665
      /* Embolden */
666
0
      if (!embolden_in_place)
667
0
      {
668
0
  int x_shift = x_scale < 0 ? -x_strength : x_strength;
669
0
  *x += x_shift;
670
0
      }
671
0
    }
672
673
0
    return ret;
674
0
  }
675
676
  hb_bool_t get_glyph_name (hb_codepoint_t glyph,
677
          char *name, unsigned int size)
678
0
  {
679
0
    if (size) *name = '\0';
680
0
    return klass->get.f.glyph_name (this, user_data,
681
0
            glyph,
682
0
            name, size,
683
0
            !klass->user_data ? nullptr : klass->user_data->glyph_name);
684
0
  }
685
686
  hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
687
         hb_codepoint_t *glyph)
688
0
  {
689
0
    *glyph = 0;
690
0
    if (len == -1) len = strlen (name);
691
0
    return klass->get.f.glyph_from_name (this, user_data,
692
0
           name, len,
693
0
           glyph,
694
0
           !klass->user_data ? nullptr : klass->user_data->glyph_from_name);
695
0
  }
696
697
  bool draw_glyph_or_fail (hb_codepoint_t glyph,
698
         hb_draw_funcs_t *draw_funcs, void *draw_data,
699
         bool synthetic = true)
700
0
  {
701
0
#ifndef HB_NO_DRAW
702
0
#ifndef HB_NO_OUTLINE
703
0
    bool embolden = x_strength || y_strength;
704
0
    bool slanted = slant_xy;
705
0
    synthetic = synthetic && (embolden || slanted);
706
#else
707
    synthetic = false;
708
#endif
709
710
0
    if (!synthetic)
711
0
    {
712
0
      return klass->get.f.draw_glyph_or_fail (this, user_data,
713
0
                glyph,
714
0
                draw_funcs, draw_data,
715
0
                !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail);
716
0
    }
717
718
0
#ifndef HB_NO_OUTLINE
719
720
0
    hb_outline_t outline;
721
0
    if (!klass->get.f.draw_glyph_or_fail (this, user_data,
722
0
            glyph,
723
0
            hb_outline_recording_pen_get_funcs (), &outline,
724
0
            !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail))
725
0
      return false;
726
727
    // Slant before embolden; produces nicer results.
728
729
0
    if (slanted)
730
0
      outline.slant (slant_xy);
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
0
  {
787
0
    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
0
  }
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
947k
  {
848
947k
    *x += dx;
849
947k
    *y += dy;
850
947k
  }
851
  void subtract_offset (hb_position_t *x, hb_position_t *y,
852
      hb_position_t dx, hb_position_t dy)
853
1.89M
  {
854
1.89M
    *x -= dx;
855
1.89M
    *y -= dy;
856
1.89M
  }
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
370k
  {
870
370k
    bool has_ascender = false;
871
370k
    hb_position_t ascender = 0;
872
873
370k
    struct { hb_position_t x, y; } origins[32];
874
875
370k
    unsigned int offset = 0;
876
370k
    unsigned int count = buf->len;
877
756k
    while (offset < count)
878
386k
    {
879
386k
      unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
880
386k
      if (!get_glyph_h_origins (n,
881
386k
        &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
882
386k
        &origins[0].x, sizeof (origins[0]),
883
386k
        &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
    for (unsigned j = 0; j < n; j++)
909
0
    {
910
0
      origins[j].x = 0;
911
0
      origins[j].y = 0;
912
0
    }
913
0
  }
914
0
      }
915
916
386k
      assert (mult == -1 || mult == +1);
917
386k
      if (mult == +1)
918
1.07M
        for (unsigned j = 0; j < n; j++)
919
947k
  {
920
947k
    hb_glyph_position_t *pos = &buf->pos[offset + j];
921
947k
    add_offset (&pos->x_offset, &pos->y_offset,
922
947k
          origins[j].x, origins[j].y);
923
947k
  }
924
257k
      else /* mult == -1 */
925
2.15M
  for (unsigned j = 0; j < n; j++)
926
1.89M
  {
927
1.89M
    hb_glyph_position_t *pos = &buf->pos[offset + j];
928
1.89M
    subtract_offset (&pos->x_offset, &pos->y_offset,
929
1.89M
         origins[j].x, origins[j].y);
930
1.89M
  }
931
932
386k
      offset += n;
933
386k
    }
934
370k
  }
935
  void apply_glyph_v_origins_with_fallback (hb_buffer_t *buf, int mult)
936
0
  {
937
0
    bool has_ascender = false;
938
0
    hb_position_t ascender = 0;
939
940
0
    struct { hb_position_t x, y; } origins[32];
941
942
0
    unsigned int offset = 0;
943
0
    unsigned int count = buf->len;
944
0
    while (offset < count)
945
0
    {
946
0
      unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
947
0
      if (!get_glyph_v_origins (n,
948
0
        &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
949
0
        &origins[0].x, sizeof (origins[0]),
950
0
        &origins[0].y, sizeof (origins[0])))
951
0
      {
952
0
  if (get_glyph_h_origins (n,
953
0
         &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
954
0
         &origins[0].x, sizeof (origins[0]),
955
0
         &origins[0].y, sizeof (origins[0])))
956
0
  {
957
0
    if (!has_ascender)
958
0
    {
959
0
      hb_font_extents_t extents;
960
0
      get_h_extents_with_fallback (&extents);
961
0
      ascender = extents.ascender;
962
0
      has_ascender = true;
963
0
    }
964
965
    /* We got the h_origins, adjust them to v_origins. */
966
0
    for (unsigned j = 0; j < n; j++)
967
0
    {
968
0
      hb_codepoint_t glyph = buf->info[offset + j].codepoint;
969
0
      origins[j].x += get_glyph_h_advance (glyph) / 2;
970
0
      origins[j].y += ascender;
971
0
    }
972
0
  }
973
0
  else
974
0
  {
975
0
    for (unsigned j = 0; j < n; j++)
976
0
    {
977
0
      origins[j].x = 0;
978
0
      origins[j].y = 0;
979
0
    }
980
0
  }
981
0
      }
982
983
0
      assert (mult == -1 || mult == +1);
984
0
      if (mult == +1)
985
0
        for (unsigned j = 0; j < n; j++)
986
0
  {
987
0
    hb_glyph_position_t *pos = &buf->pos[offset + j];
988
0
    add_offset (&pos->x_offset, &pos->y_offset,
989
0
          origins[j].x, origins[j].y);
990
0
  }
991
0
      else /* mult == -1 */
992
0
  for (unsigned j = 0; j < n; j++)
993
0
  {
994
0
    hb_glyph_position_t *pos = &buf->pos[offset + j];
995
0
    subtract_offset (&pos->x_offset, &pos->y_offset,
996
0
         origins[j].x, origins[j].y);
997
0
  }
998
999
0
      offset += n;
1000
0
    }
1001
0
  }
1002
1003
  void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
1004
           hb_position_t *x, hb_position_t *y)
1005
0
  {
1006
0
    if (!get_glyph_h_origin (glyph, x, y) &&
1007
0
   get_glyph_v_origin (glyph, x, y))
1008
0
    {
1009
0
      hb_position_t dx, dy;
1010
0
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
1011
0
      subtract_offset (x, y, dx, dy);
1012
0
    }
1013
0
  }
1014
  void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
1015
           hb_position_t *x, hb_position_t *y)
1016
0
  {
1017
0
    if (!get_glyph_v_origin (glyph, x, y) &&
1018
0
   get_glyph_h_origin (glyph, x, y))
1019
0
    {
1020
0
      hb_position_t dx, dy;
1021
0
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
1022
0
      add_offset (x, y, dx, dy);
1023
0
    }
1024
0
  }
1025
1026
  void get_glyph_origin_for_direction (hb_codepoint_t glyph,
1027
               hb_direction_t direction,
1028
               hb_position_t *x, hb_position_t *y)
1029
0
  {
1030
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
1031
0
      get_glyph_h_origin_with_fallback (glyph, x, y);
1032
0
    else
1033
0
      get_glyph_v_origin_with_fallback (glyph, x, y);
1034
0
  }
1035
1036
  void add_glyph_h_origins (hb_buffer_t *buf)
1037
123k
  {
1038
123k
    apply_glyph_h_origins_with_fallback (buf, +1);
1039
123k
  }
1040
  void add_glyph_v_origins (hb_buffer_t *buf)
1041
0
  {
1042
0
    apply_glyph_v_origins_with_fallback (buf, +1);
1043
0
  }
1044
  void add_glyph_origin_for_direction (hb_codepoint_t glyph,
1045
               hb_direction_t direction,
1046
               hb_position_t *x, hb_position_t *y)
1047
0
  {
1048
0
    hb_position_t origin_x, origin_y;
1049
0
    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
1050
0
    add_offset (x, y, origin_x, origin_y);
1051
0
  }
1052
1053
  void subtract_glyph_h_origins (hb_buffer_t *buf)
1054
246k
  {
1055
246k
    apply_glyph_h_origins_with_fallback (buf, -1);
1056
246k
  }
1057
  void subtract_glyph_v_origins (hb_buffer_t *buf)
1058
0
  {
1059
0
    apply_glyph_v_origins_with_fallback (buf, -1);
1060
0
  }
1061
  void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
1062
              hb_direction_t direction,
1063
              hb_position_t *x, hb_position_t *y)
1064
0
  {
1065
0
    hb_position_t origin_x, origin_y;
1066
0
    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
1067
0
    subtract_offset (x, y, origin_x, origin_y);
1068
0
  }
1069
1070
  void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
1071
          hb_direction_t direction,
1072
          hb_position_t *x, hb_position_t *y)
1073
0
  {
1074
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
1075
0
      *y = 0;
1076
0
      *x = get_glyph_h_kerning (first_glyph, second_glyph);
1077
0
    } else {
1078
0
      *x = 0;
1079
0
      *y = get_glyph_v_kerning (first_glyph, second_glyph);
1080
0
    }
1081
0
  }
1082
1083
  hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
1084
            hb_direction_t direction,
1085
            hb_glyph_extents_t *extents)
1086
0
  {
1087
0
    hb_bool_t ret = get_glyph_extents (glyph, extents);
1088
1089
0
    if (ret)
1090
0
      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
1091
1092
0
    return ret;
1093
0
  }
1094
1095
  hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
1096
            hb_direction_t direction,
1097
            hb_position_t *x, hb_position_t *y)
1098
0
  {
1099
0
    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
1100
1101
0
    if (ret)
1102
0
      subtract_glyph_origin_for_direction (glyph, direction, x, y);
1103
1104
0
    return ret;
1105
0
  }
1106
1107
  /* Generates gidDDD if glyph has no name. */
1108
  void
1109
  glyph_to_string (hb_codepoint_t glyph,
1110
       char *s, unsigned int size)
1111
0
  {
1112
0
    if (get_glyph_name (glyph, s, size)) return;
1113
1114
0
    if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0)
1115
0
      *s = '\0';
1116
0
  }
1117
1118
  /* Parses gidDDD and uniUUUU strings automatically. */
1119
  hb_bool_t
1120
  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
1121
         hb_codepoint_t *glyph)
1122
0
  {
1123
0
    if (get_glyph_from_name (s, len, glyph)) return true;
1124
1125
0
    if (len == -1) len = strlen (s);
1126
1127
    /* Straight glyph index. */
1128
0
    if (hb_codepoint_parse (s, len, 10, glyph))
1129
0
      return true;
1130
1131
0
    if (len > 3)
1132
0
    {
1133
      /* gidDDD syntax for glyph indices. */
1134
0
      if (0 == strncmp (s, "gid", 3) &&
1135
0
    hb_codepoint_parse (s + 3, len - 3, 10, glyph))
1136
0
  return true;
1137
1138
      /* uniUUUU and other Unicode character indices. */
1139
0
      hb_codepoint_t unichar;
1140
0
      if (0 == strncmp (s, "uni", 3) &&
1141
0
    hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
1142
0
    get_nominal_glyph (unichar, glyph))
1143
0
  return true;
1144
0
    }
1145
1146
0
    return false;
1147
0
  }
1148
1149
  void changed ()
1150
511k
  {
1151
511k
    float upem = face->get_upem ();
1152
1153
511k
    x_multf = x_scale / upem;
1154
511k
    y_multf = y_scale / upem;
1155
511k
    bool x_neg = x_scale < 0;
1156
511k
    x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem;
1157
511k
    bool y_neg = y_scale < 0;
1158
511k
    y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
1159
1160
511k
    is_synthetic =  x_embolden || y_embolden || slant;
1161
1162
511k
    x_strength = roundf (abs (x_scale) * x_embolden);
1163
511k
    y_strength = roundf (abs (y_scale) * y_embolden);
1164
1165
511k
    slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
1166
1167
511k
    data.fini ();
1168
1169
511k
    serial++;
1170
511k
  }
1171
1172
  hb_position_t em_mult (int16_t v, int64_t mult)
1173
0
  { return (hb_position_t) ((v * mult + 32768) >> 16); }
1174
  hb_position_t em_multf (float v, float mult)
1175
0
  { return (hb_position_t) roundf (em_fmultf (v, mult)); }
1176
  float em_fmultf (float v, float mult)
1177
0
  { return v * mult; }
1178
  float em_fmult (int16_t v, float mult)
1179
0
  { return (float) v * mult; }
1180
};
1181
DECLARE_NULL_INSTANCE (hb_font_t);
1182
1183
1184
#endif /* HB_FONT_HH */