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