Coverage Report

Created: 2025-12-04 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/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
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
283k
  { \
260
283k
    hb_font_funcs_t *funcs = this->klass; \
261
283k
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
262
283k
    return has_func (i); \
263
283k
  } \
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
483k
  { \
267
483k
    hb_font_funcs_t *funcs = this->klass; \
268
483k
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
269
483k
    return has_func_set (i); \
270
483k
  }
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
767k
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
hb_font_t::has_nominal_glyph_func_set()
Line
Count
Source
271
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
Unexecuted instantiation: hb_font_t::has_nominal_glyphs_func_set()
hb_font_t::has_glyph_h_advance_func_set()
Line
Count
Source
271
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
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()
Line
Count
Source
271
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
hb_font_t::has_glyph_h_origin_func_set()
Line
Count
Source
271
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
Unexecuted instantiation: hb_font_t::has_glyph_v_origin_func_set()
Unexecuted instantiation: hb_font_t::has_glyph_h_origins_func()
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()
Unexecuted instantiation: hb_font_t::has_glyph_extents_func()
272
767k
#undef HB_FONT_FUNC_IMPLEMENT
273
767k
274
767k
  hb_bool_t get_font_h_extents (hb_font_extents_t *extents,
275
767k
        bool synthetic = true)
276
767k
  {
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
26
  {
317
26
    hb_codepoint_t glyph;
318
26
    return get_nominal_glyph (unicode, &glyph);
319
26
  }
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
619k
  {
325
619k
    *glyph = not_found;
326
619k
    return klass->get.f.nominal_glyph (this, user_data,
327
619k
               unicode, glyph,
328
619k
               !klass->user_data ? nullptr : klass->user_data->nominal_glyph);
329
619k
  }
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
94.5k
  {
336
94.5k
    return klass->get.f.nominal_glyphs (this, user_data,
337
94.5k
          count,
338
94.5k
          first_unicode, unicode_stride,
339
94.5k
          first_glyph, glyph_stride,
340
94.5k
          !klass->user_data ? nullptr : klass->user_data->nominal_glyphs);
341
94.5k
  }
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
603k
  {
356
603k
    hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data,
357
603k
                glyph,
358
603k
                !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
359
360
603k
    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
603k
    return advance;
368
603k
  }
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
94.5k
  {
394
94.5k
    klass->get.f.glyph_h_advances (this, user_data,
395
94.5k
           count,
396
94.5k
           first_glyph, glyph_stride,
397
94.5k
           first_advance, advance_stride,
398
94.5k
           !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
399
400
94.5k
    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
94.5k
  }
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
1.80M
  {
441
1.80M
    *x = *y = 0;
442
1.80M
    bool ret = klass->get.f.glyph_h_origin (this, user_data,
443
1.80M
              glyph, x, y,
444
1.80M
              !klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
445
446
1.80M
    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
1.80M
    return ret;
459
1.80M
  }
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
294k
  {
495
294k
    bool ret = klass->get.f.glyph_h_origins (this, user_data,
496
294k
               count,
497
294k
               first_glyph, glyph_stride,
498
294k
               first_x, x_stride, first_y, y_stride,
499
294k
               !klass->user_data ? nullptr : klass->user_data->glyph_h_origins);
500
501
294k
    if (synthetic && ret)
502
294k
    {
503
294k
      hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength;
504
294k
      hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
505
2.10M
      for (unsigned i = 0; i < count; i++)
506
1.80M
      {
507
  /* Slant is ignored as it does not affect glyph origin */
508
509
  /* Embolden */
510
1.80M
  if (!embolden_in_place)
511
0
  {
512
0
    *first_x += x_shift;
513
0
    *first_y += y_shift;
514
0
  }
515
1.80M
  first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
516
1.80M
  first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
517
1.80M
      }
518
294k
    }
519
520
294k
    return ret;
521
294k
  }
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
0
  {
533
0
    bool ret = klass->get.f.glyph_v_origins (this, user_data,
534
0
               count,
535
0
               first_glyph, glyph_stride,
536
0
               first_x, x_stride, first_y, y_stride,
537
0
               !klass->user_data ? nullptr : klass->user_data->glyph_v_origins);
538
539
0
    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
0
    return ret;
559
0
  }
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
0
  {
589
0
    hb_memset (extents, 0, sizeof (*extents));
590
591
    /* This is rather messy, but necessary. */
592
593
0
    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
0
    if (!is_synthetic &&
601
0
  klass->get.f.glyph_extents (this, user_data,
602
0
            glyph,
603
0
            extents,
604
0
            !klass->user_data ? nullptr : klass->user_data->glyph_extents))
605
0
      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
    {
723
0
      hb_position_t xo = 0, yo = 0;
724
0
      get_glyph_h_origin (glyph, &xo, &yo, false);
725
0
      outline.translate (-xo, -yo);
726
0
      outline.slant (slant_xy);
727
0
      outline.translate (xo, yo);
728
0
    }
729
730
0
    if (embolden)
731
0
    {
732
0
      float x_shift = embolden_in_place ? 0 : (float) x_strength / 2;
733
0
      float y_shift = (float) y_strength / 2;
734
0
      if (x_scale < 0) x_shift = -x_shift;
735
0
      if (y_scale < 0) y_shift = -y_shift;
736
0
      outline.embolden (x_strength, y_strength, x_shift, y_shift);
737
0
    }
738
739
0
    outline.replay (draw_funcs, draw_data);
740
741
0
    return true;
742
0
#endif
743
0
#endif
744
0
    return false;
745
0
  }
746
747
  bool paint_glyph_or_fail (hb_codepoint_t glyph,
748
          hb_paint_funcs_t *paint_funcs, void *paint_data,
749
          unsigned int palette,
750
          hb_color_t foreground,
751
          bool synthetic = true)
752
0
  {
753
0
#ifndef HB_NO_PAINT
754
    /* Slant */
755
0
    if (synthetic && slant_xy)
756
0
      hb_paint_push_transform (paint_funcs, paint_data,
757
0
             1.f, 0.f,
758
0
             slant_xy, 1.f,
759
0
             0.f, 0.f);
760
761
0
    bool ret = klass->get.f.paint_glyph_or_fail (this, user_data,
762
0
             glyph,
763
0
             paint_funcs, paint_data,
764
0
             palette, foreground,
765
0
             !klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail);
766
767
0
    if (synthetic && slant_xy)
768
0
      hb_paint_pop_transform (paint_funcs, paint_data);
769
770
0
    return ret;
771
0
#endif
772
0
    return false;
773
0
  }
774
775
  /* A bit higher-level, and with fallback */
776
777
  HB_INTERNAL
778
  void paint_glyph (hb_codepoint_t glyph,
779
        hb_paint_funcs_t *paint_funcs, void *paint_data,
780
        unsigned int palette,
781
        hb_color_t foreground);
782
783
  void get_h_extents_with_fallback (hb_font_extents_t *extents)
784
0
  {
785
0
    if (!get_font_h_extents (extents))
786
0
    {
787
0
      extents->ascender = y_scale * .8;
788
0
      extents->descender = extents->ascender - y_scale;
789
0
      extents->line_gap = 0;
790
0
    }
791
0
  }
792
  void get_v_extents_with_fallback (hb_font_extents_t *extents)
793
0
  {
794
0
    if (!get_font_v_extents (extents))
795
0
    {
796
0
      extents->ascender = x_scale / 2;
797
0
      extents->descender = extents->ascender - x_scale;
798
0
      extents->line_gap = 0;
799
0
    }
800
0
  }
801
802
  void get_extents_for_direction (hb_direction_t direction,
803
          hb_font_extents_t *extents)
804
0
  {
805
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
806
0
      get_h_extents_with_fallback (extents);
807
0
    else
808
0
      get_v_extents_with_fallback (extents);
809
0
  }
810
811
  void get_glyph_advance_for_direction (hb_codepoint_t glyph,
812
          hb_direction_t direction,
813
          hb_position_t *x, hb_position_t *y)
814
0
  {
815
0
    *x = *y = 0;
816
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
817
0
      *x = get_glyph_h_advance (glyph);
818
0
    else
819
0
      *y = get_glyph_v_advance (glyph);
820
0
  }
821
  void get_glyph_advances_for_direction (hb_direction_t direction,
822
           unsigned int count,
823
           const hb_codepoint_t *first_glyph,
824
           unsigned glyph_stride,
825
           hb_position_t *first_advance,
826
           unsigned advance_stride)
827
0
  {
828
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
829
0
      get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
830
0
    else
831
0
      get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
832
0
  }
833
834
  void apply_offset (hb_position_t *x, hb_position_t *y,
835
         hb_position_t dx, hb_position_t dy,
836
         signed mult)
837
0
  {
838
0
    assert (mult == -1 || mult == +1);
839
0
840
0
    *x += dx * mult;
841
0
    *y += dy * mult;
842
0
  }
843
  void add_offset (hb_position_t *x, hb_position_t *y,
844
       hb_position_t dx, hb_position_t dy)
845
603k
  {
846
603k
    *x += dx;
847
603k
    *y += dy;
848
603k
  }
849
  void subtract_offset (hb_position_t *x, hb_position_t *y,
850
      hb_position_t dx, hb_position_t dy)
851
1.20M
  {
852
1.20M
    *x -= dx;
853
1.20M
    *y -= dy;
854
1.20M
  }
855
856
  void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
857
              hb_position_t *x, hb_position_t *y)
858
0
  {
859
0
    *x = get_glyph_h_advance (glyph) / 2;
860
861
0
    hb_font_extents_t extents;
862
0
    get_h_extents_with_fallback (&extents);
863
0
    *y = extents.ascender;
864
0
  }
865
866
  void apply_glyph_h_origins_with_fallback (hb_buffer_t *buf, int mult)
867
283k
  {
868
283k
    bool has_ascender = false;
869
283k
    hb_position_t ascender = 0;
870
871
283k
    struct { hb_position_t x, y; } origins[32];
872
873
283k
    unsigned int offset = 0;
874
283k
    unsigned int count = buf->len;
875
578k
    while (offset < count)
876
294k
    {
877
294k
      unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
878
294k
      if (!get_glyph_h_origins (n,
879
294k
        &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
880
294k
        &origins[0].x, sizeof (origins[0]),
881
294k
        &origins[0].y, sizeof (origins[0])))
882
0
      {
883
0
        if (get_glyph_v_origins (n,
884
0
          &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
885
0
          &origins[0].x, sizeof (origins[0]),
886
0
          &origins[0].y, sizeof (origins[0])))
887
0
  {
888
0
    if (!has_ascender)
889
0
    {
890
0
      hb_font_extents_t extents;
891
0
      get_h_extents_with_fallback (&extents);
892
0
      ascender = extents.ascender;
893
0
      has_ascender = true;
894
0
    }
895
896
    /* We got the v_origins, adjust them to h_origins. */
897
0
    for (unsigned j = 0; j < n; j++)
898
0
    {
899
0
      hb_codepoint_t glyph = buf->info[offset + j].codepoint;
900
0
      origins[j].x -= get_glyph_h_advance (glyph) / 2;
901
0
      origins[j].y -= ascender;
902
0
    }
903
0
  }
904
0
  else
905
0
  {
906
0
    for (unsigned j = 0; j < n; j++)
907
0
    {
908
0
      origins[j].x = 0;
909
0
      origins[j].y = 0;
910
0
    }
911
0
  }
912
0
      }
913
914
294k
      assert (mult == -1 || mult == +1);
915
294k
      if (mult == +1)
916
701k
        for (unsigned j = 0; j < n; j++)
917
603k
  {
918
603k
    hb_glyph_position_t *pos = &buf->pos[offset + j];
919
603k
    add_offset (&pos->x_offset, &pos->y_offset,
920
603k
          origins[j].x, origins[j].y);
921
603k
  }
922
196k
      else /* mult == -1 */
923
1.40M
  for (unsigned j = 0; j < n; j++)
924
1.20M
  {
925
1.20M
    hb_glyph_position_t *pos = &buf->pos[offset + j];
926
1.20M
    subtract_offset (&pos->x_offset, &pos->y_offset,
927
1.20M
         origins[j].x, origins[j].y);
928
1.20M
  }
929
930
294k
      offset += n;
931
294k
    }
932
283k
  }
933
  void apply_glyph_v_origins_with_fallback (hb_buffer_t *buf, int mult)
934
0
  {
935
0
    bool has_ascender = false;
936
0
    hb_position_t ascender = 0;
937
938
0
    struct { hb_position_t x, y; } origins[32];
939
940
0
    unsigned int offset = 0;
941
0
    unsigned int count = buf->len;
942
0
    while (offset < count)
943
0
    {
944
0
      unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
945
0
      if (!get_glyph_v_origins (n,
946
0
        &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
947
0
        &origins[0].x, sizeof (origins[0]),
948
0
        &origins[0].y, sizeof (origins[0])))
949
0
      {
950
0
  if (get_glyph_h_origins (n,
951
0
         &buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
952
0
         &origins[0].x, sizeof (origins[0]),
953
0
         &origins[0].y, sizeof (origins[0])))
954
0
  {
955
0
    if (!has_ascender)
956
0
    {
957
0
      hb_font_extents_t extents;
958
0
      get_h_extents_with_fallback (&extents);
959
0
      ascender = extents.ascender;
960
0
      has_ascender = true;
961
0
    }
962
963
    /* We got the h_origins, adjust them to v_origins. */
964
0
    for (unsigned j = 0; j < n; j++)
965
0
    {
966
0
      hb_codepoint_t glyph = buf->info[offset + j].codepoint;
967
0
      origins[j].x += get_glyph_h_advance (glyph) / 2;
968
0
      origins[j].y += ascender;
969
0
    }
970
0
  }
971
0
  else
972
0
  {
973
0
    for (unsigned j = 0; j < n; j++)
974
0
    {
975
0
      origins[j].x = 0;
976
0
      origins[j].y = 0;
977
0
    }
978
0
  }
979
0
      }
980
981
0
      assert (mult == -1 || mult == +1);
982
0
      if (mult == +1)
983
0
        for (unsigned j = 0; j < n; j++)
984
0
  {
985
0
    hb_glyph_position_t *pos = &buf->pos[offset + j];
986
0
    add_offset (&pos->x_offset, &pos->y_offset,
987
0
          origins[j].x, origins[j].y);
988
0
  }
989
0
      else /* mult == -1 */
990
0
  for (unsigned j = 0; j < n; j++)
991
0
  {
992
0
    hb_glyph_position_t *pos = &buf->pos[offset + j];
993
0
    subtract_offset (&pos->x_offset, &pos->y_offset,
994
0
         origins[j].x, origins[j].y);
995
0
  }
996
997
0
      offset += n;
998
0
    }
999
0
  }
1000
1001
  void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
1002
           hb_position_t *x, hb_position_t *y)
1003
0
  {
1004
0
    if (!get_glyph_h_origin (glyph, x, y) &&
1005
0
   get_glyph_v_origin (glyph, x, y))
1006
0
    {
1007
0
      hb_position_t dx, dy;
1008
0
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
1009
0
      subtract_offset (x, y, dx, dy);
1010
0
    }
1011
0
  }
1012
  void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
1013
           hb_position_t *x, hb_position_t *y)
1014
0
  {
1015
0
    if (!get_glyph_v_origin (glyph, x, y) &&
1016
0
   get_glyph_h_origin (glyph, x, y))
1017
0
    {
1018
0
      hb_position_t dx, dy;
1019
0
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
1020
0
      add_offset (x, y, dx, dy);
1021
0
    }
1022
0
  }
1023
1024
  void get_glyph_origin_for_direction (hb_codepoint_t glyph,
1025
               hb_direction_t direction,
1026
               hb_position_t *x, hb_position_t *y)
1027
0
  {
1028
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
1029
0
      get_glyph_h_origin_with_fallback (glyph, x, y);
1030
0
    else
1031
0
      get_glyph_v_origin_with_fallback (glyph, x, y);
1032
0
  }
1033
1034
  void add_glyph_h_origins (hb_buffer_t *buf)
1035
94.5k
  {
1036
94.5k
    apply_glyph_h_origins_with_fallback (buf, +1);
1037
94.5k
  }
1038
  void add_glyph_v_origins (hb_buffer_t *buf)
1039
0
  {
1040
0
    apply_glyph_v_origins_with_fallback (buf, +1);
1041
0
  }
1042
  void add_glyph_origin_for_direction (hb_codepoint_t glyph,
1043
               hb_direction_t direction,
1044
               hb_position_t *x, hb_position_t *y)
1045
0
  {
1046
0
    hb_position_t origin_x, origin_y;
1047
0
    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
1048
0
    add_offset (x, y, origin_x, origin_y);
1049
0
  }
1050
1051
  void subtract_glyph_h_origins (hb_buffer_t *buf)
1052
189k
  {
1053
189k
    apply_glyph_h_origins_with_fallback (buf, -1);
1054
189k
  }
1055
  void subtract_glyph_v_origins (hb_buffer_t *buf)
1056
0
  {
1057
0
    apply_glyph_v_origins_with_fallback (buf, -1);
1058
0
  }
1059
  void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
1060
              hb_direction_t direction,
1061
              hb_position_t *x, hb_position_t *y)
1062
0
  {
1063
0
    hb_position_t origin_x, origin_y;
1064
0
    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
1065
0
    subtract_offset (x, y, origin_x, origin_y);
1066
0
  }
1067
1068
  void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
1069
          hb_direction_t direction,
1070
          hb_position_t *x, hb_position_t *y)
1071
0
  {
1072
0
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
1073
0
      *y = 0;
1074
0
      *x = get_glyph_h_kerning (first_glyph, second_glyph);
1075
0
    } else {
1076
0
      *x = 0;
1077
0
      *y = get_glyph_v_kerning (first_glyph, second_glyph);
1078
0
    }
1079
0
  }
1080
1081
  hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
1082
            hb_direction_t direction,
1083
            hb_glyph_extents_t *extents)
1084
0
  {
1085
0
    hb_bool_t ret = get_glyph_extents (glyph, extents);
1086
1087
0
    if (ret)
1088
0
      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
1089
1090
0
    return ret;
1091
0
  }
1092
1093
  hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
1094
            hb_direction_t direction,
1095
            hb_position_t *x, hb_position_t *y)
1096
0
  {
1097
0
    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
1098
1099
0
    if (ret)
1100
0
      subtract_glyph_origin_for_direction (glyph, direction, x, y);
1101
1102
0
    return ret;
1103
0
  }
1104
1105
  /* Generates gidDDD if glyph has no name. */
1106
  void
1107
  glyph_to_string (hb_codepoint_t glyph,
1108
       char *s, unsigned int size)
1109
0
  {
1110
0
    if (get_glyph_name (glyph, s, size)) return;
1111
1112
0
    if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0)
1113
0
      *s = '\0';
1114
0
  }
1115
1116
  /* Parses gidDDD and uniUUUU strings automatically. */
1117
  hb_bool_t
1118
  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
1119
         hb_codepoint_t *glyph)
1120
0
  {
1121
0
    if (get_glyph_from_name (s, len, glyph)) return true;
1122
1123
0
    if (len == -1) len = strlen (s);
1124
1125
    /* Straight glyph index. */
1126
0
    if (hb_codepoint_parse (s, len, 10, glyph))
1127
0
      return true;
1128
1129
0
    if (len > 3)
1130
0
    {
1131
      /* gidDDD syntax for glyph indices. */
1132
0
      if (0 == strncmp (s, "gid", 3) &&
1133
0
    hb_codepoint_parse (s + 3, len - 3, 10, glyph))
1134
0
  return true;
1135
1136
      /* uniUUUU and other Unicode character indices. */
1137
0
      hb_codepoint_t unichar;
1138
0
      if (0 == strncmp (s, "uni", 3) &&
1139
0
    hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
1140
0
    get_nominal_glyph (unichar, glyph))
1141
0
  return true;
1142
0
    }
1143
1144
0
    return false;
1145
0
  }
1146
1147
  void changed ()
1148
394k
  {
1149
394k
    float upem = face->get_upem ();
1150
1151
394k
    x_multf = x_scale / upem;
1152
394k
    y_multf = y_scale / upem;
1153
394k
    bool x_neg = x_scale < 0;
1154
394k
    x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem;
1155
394k
    bool y_neg = y_scale < 0;
1156
394k
    y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
1157
1158
394k
    is_synthetic =  x_embolden || y_embolden || slant;
1159
1160
394k
    x_strength = roundf (abs (x_scale) * x_embolden);
1161
394k
    y_strength = roundf (abs (y_scale) * y_embolden);
1162
1163
394k
    slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
1164
1165
394k
    data.fini ();
1166
1167
394k
    serial++;
1168
394k
  }
1169
1170
  hb_position_t em_mult (int16_t v, int64_t mult)
1171
0
  { return (hb_position_t) ((v * mult + 32768) >> 16); }
1172
  hb_position_t em_multf (float v, float mult)
1173
0
  { return (hb_position_t) roundf (em_fmultf (v, mult)); }
1174
  float em_fmultf (float v, float mult)
1175
0
  { return v * mult; }
1176
  float em_fmult (int16_t v, float mult)
1177
0
  { return (float) v * mult; }
1178
};
1179
DECLARE_NULL_INSTANCE (hb_font_t);
1180
1181
1182
#endif /* HB_FONT_HH */