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_PRIVATE_HH
30#define HB_FONT_PRIVATE_HH
31
32#include "hb-private.hh"
33
34#include "hb-object-private.hh"
35#include "hb-face-private.hh"
36#include "hb-shaper-private.hh"
37
38
39
40/*
41 * hb_font_funcs_t
42 */
43
44#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
45 HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
46 HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
47 HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
48 HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
49 HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
50 HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
51 HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
52 HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
53 HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
54 HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
55 HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
56 HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
57 HB_FONT_FUNC_IMPLEMENT (glyph_name) \
58 HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
59 /* ^--- Add new callbacks here */
60
61struct hb_font_funcs_t {
62 hb_object_header_t header;
63 ASSERT_POD ();
64
65 hb_bool_t immutable;
66
67 struct {
68#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
69 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
70#undef HB_FONT_FUNC_IMPLEMENT
71 } user_data;
72
73 struct {
74#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
75 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
76#undef HB_FONT_FUNC_IMPLEMENT
77 } destroy;
78
79 /* Don't access these directly. Call font->get_*() instead. */
80 union get_t {
81 struct get_funcs_t {
82#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
83 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
84#undef HB_FONT_FUNC_IMPLEMENT
85 } f;
86 void (*array[VAR]) (void);
87 } get;
88};
89
90
91
92/*
93 * hb_font_t
94 */
95
96struct hb_font_t {
97 hb_object_header_t header;
98 ASSERT_POD ();
99
100 hb_bool_t immutable;
101
102 hb_font_t *parent;
103 hb_face_t *face;
104
105 int x_scale;
106 int y_scale;
107
108 unsigned int x_ppem;
109 unsigned int y_ppem;
110
111 float ptem;
112
113 /* Font variation coordinates. */
114 unsigned int num_coords;
115 int *coords;
116
117 hb_font_funcs_t *klass;
118 void *user_data;
119 hb_destroy_func_t destroy;
120
121 struct hb_shaper_data_t shaper_data;
122
123
124 /* Convert from font-space to user-space */
125 inline int dir_scale (hb_direction_t direction)
126 { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
127 inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, scale: x_scale); }
128 inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, scale: y_scale); }
129 inline hb_position_t em_scalef_x (float v) { return em_scalef (v, scale: this->x_scale); }
130 inline hb_position_t em_scalef_y (float v) { return em_scalef (v, scale: this->y_scale); }
131 inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
132 { return em_scale (v, scale: dir_scale (direction)); }
133
134 /* Convert from parent-font user-space to our user-space */
135 inline hb_position_t parent_scale_x_distance (hb_position_t v) {
136 if (unlikely (parent && parent->x_scale != x_scale))
137 return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
138 return v;
139 }
140 inline hb_position_t parent_scale_y_distance (hb_position_t v) {
141 if (unlikely (parent && parent->y_scale != y_scale))
142 return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
143 return v;
144 }
145 inline hb_position_t parent_scale_x_position (hb_position_t v) {
146 return parent_scale_x_distance (v);
147 }
148 inline hb_position_t parent_scale_y_position (hb_position_t v) {
149 return parent_scale_y_distance (v);
150 }
151
152 inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
153 *x = parent_scale_x_distance (v: *x);
154 *y = parent_scale_y_distance (v: *y);
155 }
156 inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
157 *x = parent_scale_x_position (v: *x);
158 *y = parent_scale_y_position (v: *y);
159 }
160
161
162 /* Public getters */
163
164 HB_INTERNAL bool has_func (unsigned int i);
165
166 /* has_* ... */
167#define HB_FONT_FUNC_IMPLEMENT(name) \
168 bool \
169 has_##name##_func (void) \
170 { \
171 hb_font_funcs_t *funcs = this->klass; \
172 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
173 return has_func (i); \
174 }
175 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
176#undef HB_FONT_FUNC_IMPLEMENT
177
178 inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
179 {
180 memset (s: extents, c: 0, n: sizeof (*extents));
181 return klass->get.f.font_h_extents (this, user_data,
182 extents,
183 klass->user_data.font_h_extents);
184 }
185 inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
186 {
187 memset (s: extents, c: 0, n: sizeof (*extents));
188 return klass->get.f.font_v_extents (this, user_data,
189 extents,
190 klass->user_data.font_v_extents);
191 }
192
193 inline bool has_glyph (hb_codepoint_t unicode)
194 {
195 hb_codepoint_t glyph;
196 return get_nominal_glyph (unicode, glyph: &glyph);
197 }
198
199 inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
200 hb_codepoint_t *glyph)
201 {
202 *glyph = 0;
203 return klass->get.f.nominal_glyph (this, user_data,
204 unicode, glyph,
205 klass->user_data.nominal_glyph);
206 }
207
208 inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
209 hb_codepoint_t *glyph)
210 {
211 *glyph = 0;
212 return klass->get.f.variation_glyph (this, user_data,
213 unicode, variation_selector, glyph,
214 klass->user_data.variation_glyph);
215 }
216
217 inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
218 {
219 return klass->get.f.glyph_h_advance (this, user_data,
220 glyph,
221 klass->user_data.glyph_h_advance);
222 }
223
224 inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
225 {
226 return klass->get.f.glyph_v_advance (this, user_data,
227 glyph,
228 klass->user_data.glyph_v_advance);
229 }
230
231 inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
232 hb_position_t *x, hb_position_t *y)
233 {
234 *x = *y = 0;
235 return klass->get.f.glyph_h_origin (this, user_data,
236 glyph, x, y,
237 klass->user_data.glyph_h_origin);
238 }
239
240 inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
241 hb_position_t *x, hb_position_t *y)
242 {
243 *x = *y = 0;
244 return klass->get.f.glyph_v_origin (this, user_data,
245 glyph, x, y,
246 klass->user_data.glyph_v_origin);
247 }
248
249 inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
250 {
251 return klass->get.f.glyph_h_kerning (this, user_data,
252 left_glyph, right_glyph,
253 klass->user_data.glyph_h_kerning);
254 }
255
256 inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
257 {
258 return klass->get.f.glyph_v_kerning (this, user_data,
259 top_glyph, bottom_glyph,
260 klass->user_data.glyph_v_kerning);
261 }
262
263 inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
264 hb_glyph_extents_t *extents)
265 {
266 memset (s: extents, c: 0, n: sizeof (*extents));
267 return klass->get.f.glyph_extents (this, user_data,
268 glyph,
269 extents,
270 klass->user_data.glyph_extents);
271 }
272
273 inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
274 hb_position_t *x, hb_position_t *y)
275 {
276 *x = *y = 0;
277 return klass->get.f.glyph_contour_point (this, user_data,
278 glyph, point_index,
279 x, y,
280 klass->user_data.glyph_contour_point);
281 }
282
283 inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
284 char *name, unsigned int size)
285 {
286 if (size) *name = '\0';
287 return klass->get.f.glyph_name (this, user_data,
288 glyph,
289 name, size,
290 klass->user_data.glyph_name);
291 }
292
293 inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
294 hb_codepoint_t *glyph)
295 {
296 *glyph = 0;
297 if (len == -1) len = strlen (s: name);
298 return klass->get.f.glyph_from_name (this, user_data,
299 name, len,
300 glyph,
301 klass->user_data.glyph_from_name);
302 }
303
304
305 /* A bit higher-level, and with fallback */
306
307 inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
308 {
309 if (!get_font_h_extents (extents))
310 {
311 extents->ascender = y_scale * .8;
312 extents->descender = extents->ascender - y_scale;
313 extents->line_gap = 0;
314 }
315 }
316 inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
317 {
318 if (!get_font_v_extents (extents))
319 {
320 extents->ascender = x_scale / 2;
321 extents->descender = extents->ascender - x_scale;
322 extents->line_gap = 0;
323 }
324 }
325
326 inline void get_extents_for_direction (hb_direction_t direction,
327 hb_font_extents_t *extents)
328 {
329 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
330 get_h_extents_with_fallback (extents);
331 else
332 get_v_extents_with_fallback (extents);
333 }
334
335 inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
336 hb_direction_t direction,
337 hb_position_t *x, hb_position_t *y)
338 {
339 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
340 *x = get_glyph_h_advance (glyph);
341 *y = 0;
342 } else {
343 *x = 0;
344 *y = get_glyph_v_advance (glyph);
345 }
346 }
347
348 inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
349 hb_position_t *x, hb_position_t *y)
350 {
351 *x = get_glyph_h_advance (glyph) / 2;
352
353 /* TODO cache this somehow?! */
354 hb_font_extents_t extents;
355 get_h_extents_with_fallback (extents: &extents);
356 *y = extents.ascender;
357 }
358
359 inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
360 hb_position_t *x, hb_position_t *y)
361 {
362 if (!get_glyph_h_origin (glyph, x, y) &&
363 get_glyph_v_origin (glyph, x, y))
364 {
365 hb_position_t dx, dy;
366 guess_v_origin_minus_h_origin (glyph, x: &dx, y: &dy);
367 *x -= dx; *y -= dy;
368 }
369 }
370 inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
371 hb_position_t *x, hb_position_t *y)
372 {
373 if (!get_glyph_v_origin (glyph, x, y) &&
374 get_glyph_h_origin (glyph, x, y))
375 {
376 hb_position_t dx, dy;
377 guess_v_origin_minus_h_origin (glyph, x: &dx, y: &dy);
378 *x += dx; *y += dy;
379 }
380 }
381
382 inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
383 hb_direction_t direction,
384 hb_position_t *x, hb_position_t *y)
385 {
386 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
387 get_glyph_h_origin_with_fallback (glyph, x, y);
388 else
389 get_glyph_v_origin_with_fallback (glyph, x, y);
390 }
391
392 inline void add_glyph_h_origin (hb_codepoint_t glyph,
393 hb_position_t *x, hb_position_t *y)
394 {
395 hb_position_t origin_x, origin_y;
396
397 get_glyph_h_origin_with_fallback (glyph, x: &origin_x, y: &origin_y);
398
399 *x += origin_x;
400 *y += origin_y;
401 }
402 inline void add_glyph_v_origin (hb_codepoint_t glyph,
403 hb_position_t *x, hb_position_t *y)
404 {
405 hb_position_t origin_x, origin_y;
406
407 get_glyph_v_origin_with_fallback (glyph, x: &origin_x, y: &origin_y);
408
409 *x += origin_x;
410 *y += origin_y;
411 }
412 inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
413 hb_direction_t direction,
414 hb_position_t *x, hb_position_t *y)
415 {
416 hb_position_t origin_x, origin_y;
417
418 get_glyph_origin_for_direction (glyph, direction, x: &origin_x, y: &origin_y);
419
420 *x += origin_x;
421 *y += origin_y;
422 }
423
424 inline void subtract_glyph_h_origin (hb_codepoint_t glyph,
425 hb_position_t *x, hb_position_t *y)
426 {
427 hb_position_t origin_x, origin_y;
428
429 get_glyph_h_origin_with_fallback (glyph, x: &origin_x, y: &origin_y);
430
431 *x -= origin_x;
432 *y -= origin_y;
433 }
434 inline void subtract_glyph_v_origin (hb_codepoint_t glyph,
435 hb_position_t *x, hb_position_t *y)
436 {
437 hb_position_t origin_x, origin_y;
438
439 get_glyph_v_origin_with_fallback (glyph, x: &origin_x, y: &origin_y);
440
441 *x -= origin_x;
442 *y -= origin_y;
443 }
444 inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
445 hb_direction_t direction,
446 hb_position_t *x, hb_position_t *y)
447 {
448 hb_position_t origin_x, origin_y;
449
450 get_glyph_origin_for_direction (glyph, direction, x: &origin_x, y: &origin_y);
451
452 *x -= origin_x;
453 *y -= origin_y;
454 }
455
456 inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
457 hb_direction_t direction,
458 hb_position_t *x, hb_position_t *y)
459 {
460 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
461 *x = get_glyph_h_kerning (left_glyph: first_glyph, right_glyph: second_glyph);
462 *y = 0;
463 } else {
464 *x = 0;
465 *y = get_glyph_v_kerning (top_glyph: first_glyph, bottom_glyph: second_glyph);
466 }
467 }
468
469 inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
470 hb_direction_t direction,
471 hb_glyph_extents_t *extents)
472 {
473 hb_bool_t ret = get_glyph_extents (glyph, extents);
474
475 if (ret)
476 subtract_glyph_origin_for_direction (glyph, direction, x: &extents->x_bearing, y: &extents->y_bearing);
477
478 return ret;
479 }
480
481 inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
482 hb_direction_t direction,
483 hb_position_t *x, hb_position_t *y)
484 {
485 hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
486
487 if (ret)
488 subtract_glyph_origin_for_direction (glyph, direction, x, y);
489
490 return ret;
491 }
492
493 /* Generates gidDDD if glyph has no name. */
494 inline void
495 glyph_to_string (hb_codepoint_t glyph,
496 char *s, unsigned int size)
497 {
498 if (get_glyph_name (glyph, name: s, size)) return;
499
500 if (size && snprintf (s: s, maxlen: size, format: "gid%u", glyph) < 0)
501 *s = '\0';
502 }
503
504 /* Parses gidDDD and uniUUUU strings automatically. */
505 inline hb_bool_t
506 glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
507 hb_codepoint_t *glyph)
508 {
509 if (get_glyph_from_name (name: s, len, glyph)) return true;
510
511 if (len == -1) len = strlen (s: s);
512
513 /* Straight glyph index. */
514 if (hb_codepoint_parse (s, len, base: 10, out: glyph))
515 return true;
516
517 if (len > 3)
518 {
519 /* gidDDD syntax for glyph indices. */
520 if (0 == strncmp (s1: s, s2: "gid", n: 3) &&
521 hb_codepoint_parse (s: s + 3, len: len - 3, base: 10, out: glyph))
522 return true;
523
524 /* uniUUUU and other Unicode character indices. */
525 hb_codepoint_t unichar;
526 if (0 == strncmp (s1: s, s2: "uni", n: 3) &&
527 hb_codepoint_parse (s: s + 3, len: len - 3, base: 16, out: &unichar) &&
528 get_nominal_glyph (unicode: unichar, glyph))
529 return true;
530 }
531
532 return false;
533 }
534
535 inline hb_position_t em_scale (int16_t v, int scale)
536 {
537 int upem = face->get_upem ();
538 int64_t scaled = v * (int64_t) scale;
539 scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
540 return (hb_position_t) (scaled / upem);
541 }
542 inline hb_position_t em_scalef (float v, int scale)
543 {
544 return (hb_position_t) (v * scale / face->get_upem ());
545 }
546};
547
548#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
549#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
550#include "hb-shaper-list.hh"
551#undef HB_SHAPER_IMPLEMENT
552#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
553
554
555#endif /* HB_FONT_PRIVATE_HH */
556

source code of qtbase/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh