add explicit freetype2 linking
[charfbuzz.git] / hb-font.c
blob80df40b5a885a7e2ae668ef1fc01020247a4e155
1 /*
2 Port from c++ is protected by a GNU Lesser GPLv3
3 Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
4 <sylware@legeek.net>
5 */
6 #include <stdlib.h>
7 #include <string.h>
9 #include <ft2build.h>
10 #include FT_FREETYPE_H
12 #include "hb.h"
13 #include "hb-private.h"
14 #include "hb-atomic-private.h"
15 #include "hb-shaper-private.h"
16 #include "hb-face-private.h"
17 #include "hb-font-private.h"
19 void hb_font_destroy(hb_font_t * font)
21 if (!font)
22 return;
23 if (hb_atomic_int32_get(&font->ref_cnt) == REF_CNT_INVALID_VAL)
24 return;
25 hb_atomic_int32_add(&font->ref_cnt, -1);
26 if (hb_atomic_int32_get(&font->ref_cnt) > 0)
27 return;
28 hb_atomic_int32_set(&font->ref_cnt, REF_CNT_INVALID_VAL);
30 #ifdef HAVE_GRAPHITE2
31 if (font->shaper_data.graphite2
32 && font->shaper_data.graphite2 != HB_SHAPER_DATA_INVALID
33 && font->shaper_data.graphite2 != HB_SHAPER_DATA_SUCCEEDED)
34 hb_graphite2_shaper_font_data_destroy(font->shaper_data.
35 graphite2);
36 #endif
37 #ifdef HAVE_OT
38 if (font->shaper_data.ot
39 && font->shaper_data.ot != HB_SHAPER_DATA_INVALID
40 && font->shaper_data.ot != HB_SHAPER_DATA_SUCCEEDED)
41 hb_ot_shaper_font_data_destroy(font->shaper_data.ot);
42 #endif
43 if (font->shaper_data.fallback
44 && font->shaper_data.fallback != HB_SHAPER_DATA_INVALID
45 && font->shaper_data.fallback != HB_SHAPER_DATA_SUCCEEDED)
46 hb_fallback_shaper_font_data_destroy(font->shaper_data.
47 fallback);
49 if (font->destroy)
50 font->destroy(font->user_data);
52 hb_font_destroy(font->parent);
53 hb_face_destroy(font->face);
54 hb_font_funcs_destroy(font->klass);
55 free(font);
58 hb_bool_t hb_font_get_glyph(hb_font_t * font, hb_codepoint_t unicode,
59 hb_codepoint_t variation_selector,
60 hb_codepoint_t * glyph)
62 *glyph = 0;
63 return font->klass->get.glyph(font, font->user_data, unicode,
64 variation_selector, glyph,
65 font->klass->user_data.glyph);
68 /*Convert from parent-font user-space to our user-space*/
69 hb_position_t hb_font_parent_scale_x_distance(hb_font_t * font, hb_position_t v)
71 if (font->parent && font->parent->x_scale != font->x_scale)
72 return v * (int64_t) font->x_scale / font->parent->x_scale;
73 return v;
76 hb_position_t hb_font_parent_scale_y_distance(hb_font_t * font, hb_position_t v)
78 if (font->parent && font->parent->y_scale != font->y_scale)
79 return v * (int64_t) font->y_scale / font->parent->y_scale;
80 return v;
83 hb_position_t hb_font_parent_scale_x_position(hb_font_t * font, hb_position_t v)
85 return hb_font_parent_scale_x_distance(font, v);
88 hb_position_t hb_font_parent_scale_y_position(hb_font_t * font, hb_position_t v)
90 return hb_font_parent_scale_y_distance(font, v);
93 void hb_font_parent_scale_position(hb_font_t * font, hb_position_t * x,
94 hb_position_t * y)
96 *x = hb_font_parent_scale_x_position(font, *x);
97 *y = hb_font_parent_scale_y_position(font, *y);
100 void hb_font_parent_scale_distance(hb_font_t * font, hb_position_t * x,
101 hb_position_t * y)
103 *x = hb_font_parent_scale_x_distance(font, *x);
104 *y = hb_font_parent_scale_y_distance(font, *y);
107 hb_position_t hb_font_get_glyph_h_advance(hb_font_t * font,
108 hb_codepoint_t glyph)
110 return font->klass->get.glyph_h_advance(font, font->user_data, glyph,
111 font->klass->user_data.
112 glyph_h_advance);
115 hb_position_t hb_font_get_glyph_v_advance(hb_font_t * font,
116 hb_codepoint_t glyph)
118 return font->klass->get.glyph_v_advance(font, font->user_data, glyph,
119 font->klass->user_data.
120 glyph_v_advance);
123 hb_bool_t hb_font_get_glyph_h_origin(hb_font_t * font, hb_codepoint_t glyph,
124 hb_position_t * x, hb_position_t * y)
126 *x = *y = 0;
127 return font->klass->get.glyph_h_origin(font, font->user_data, glyph, x,
129 font->klass->user_data.
130 glyph_h_origin);
133 hb_bool_t hb_font_get_glyph_v_origin(hb_font_t * font, hb_codepoint_t glyph,
134 hb_position_t * x, hb_position_t * y)
136 *x = *y = 0;
137 return font->klass->get.glyph_v_origin(font, font->user_data, glyph, x,
139 font->klass->user_data.
140 glyph_v_origin);
143 hb_position_t hb_font_get_glyph_h_kerning(hb_font_t * font,
144 hb_codepoint_t left_glyph,
145 hb_codepoint_t right_glyph)
147 return font->klass->get.glyph_h_kerning(font, font->user_data,
148 left_glyph, right_glyph,
149 font->klass->user_data.
150 glyph_h_kerning);
153 hb_position_t hb_font_get_glyph_v_kerning(hb_font_t * font,
154 hb_codepoint_t top_glyph,
155 hb_codepoint_t bottom_glyph)
157 return font->klass->get.glyph_v_kerning(font, font->user_data,
158 top_glyph, bottom_glyph,
159 font->klass->user_data.
160 glyph_v_kerning);
163 hb_bool_t hb_font_get_glyph_extents(hb_font_t * font, hb_codepoint_t glyph,
164 hb_glyph_extents_t * extents)
166 memset(extents, 0, sizeof(*extents));
167 return font->klass->get.glyph_extents(font, font->user_data, glyph,
168 extents,
169 font->klass->user_data.
170 glyph_extents);
173 hb_bool_t hb_font_get_glyph_contour_point(hb_font_t * font,
174 hb_codepoint_t glyph,
175 unsigned int point_index,
176 hb_position_t * x, hb_position_t * y)
178 *x = *y = 0;
179 return font->klass->get.glyph_contour_point(font, font->user_data,
180 glyph, point_index, x, y,
181 font->klass->user_data.
182 glyph_contour_point);
185 hb_bool_t hb_font_get_glyph_name(hb_font_t * font, hb_codepoint_t glyph,
186 char *name, unsigned int size)
188 if (size)
189 *name = '\0';
190 return font->klass->get.glyph_name(font, font->user_data, glyph, name,
191 size,
192 font->klass->user_data.glyph_name);
195 hb_bool_t hb_font_get_glyph_from_name(hb_font_t * font, const char *name,
196 int len /*-1 means nul-terminated*/ ,
197 hb_codepoint_t * glyph)
199 *glyph = 0;
200 if (len == -1)
201 len = strlen(name);
202 return font->klass->get.glyph_from_name(font, font->user_data, name,
203 len, glyph,
204 font->klass->user_data.
205 glyph_from_name);
208 static hb_bool_t hb_font_get_glyph_nil(hb_font_t * font,
209 void *font_data HB_UNUSED,
210 hb_codepoint_t unicode,
211 hb_codepoint_t variation_selector,
212 hb_codepoint_t * glyph,
213 void *user_data HB_UNUSED)
215 if (font->parent)
216 return hb_font_get_glyph(font->parent, unicode,
217 variation_selector, glyph);
219 *glyph = 0;
220 return FALSE;
223 static hb_position_t hb_font_get_glyph_h_advance_nil(hb_font_t * font,
224 void *font_data HB_UNUSED,
225 hb_codepoint_t glyph,
226 void *user_data HB_UNUSED)
228 if (font->parent)
229 return hb_font_parent_scale_x_distance(font,
230 hb_font_get_glyph_h_advance
231 (font->parent, glyph));
232 return font->x_scale;
235 static hb_position_t hb_font_get_glyph_v_advance_nil(hb_font_t * font,
236 void *font_data HB_UNUSED,
237 hb_codepoint_t glyph,
238 void *user_data HB_UNUSED)
240 if (font->parent)
241 return hb_font_parent_scale_y_distance(font,
242 hb_font_get_glyph_v_advance
243 (font->parent, glyph));
244 return font->y_scale;
247 static hb_bool_t hb_font_get_glyph_h_origin_nil(hb_font_t * font,
248 void *font_data HB_UNUSED,
249 hb_codepoint_t glyph,
250 hb_position_t * x,
251 hb_position_t * y,
252 void *user_data HB_UNUSED)
254 if (font->parent) {
255 hb_bool_t ret;
257 ret = hb_font_get_glyph_h_origin(font->parent, glyph, x, y);
258 if (ret)
259 hb_font_parent_scale_position(font, x, y);
260 return ret;
263 *x = *y = 0;
264 return FALSE;
267 static hb_bool_t hb_font_get_glyph_v_origin_nil(hb_font_t * font,
268 void *font_data HB_UNUSED,
269 hb_codepoint_t glyph,
270 hb_position_t * x,
271 hb_position_t * y,
272 void *user_data HB_UNUSED)
274 if (font->parent) {
275 hb_bool_t ret;
277 ret = hb_font_get_glyph_v_origin(font->parent, glyph, x, y);
278 if (ret)
279 hb_font_parent_scale_position(font, x, y);
280 return ret;
283 *x = *y = 0;
284 return FALSE;
287 static hb_position_t hb_font_get_glyph_h_kerning_nil(hb_font_t * font,
288 void *font_data HB_UNUSED,
289 hb_codepoint_t left_glyph,
290 hb_codepoint_t right_glyph,
291 void *user_data HB_UNUSED)
293 if (font->parent)
294 return hb_font_parent_scale_x_distance(font,
295 hb_font_get_glyph_h_kerning
296 (font->parent,
297 left_glyph,
298 right_glyph));
299 return 0;
302 static hb_position_t hb_font_get_glyph_v_kerning_nil(hb_font_t * font,
303 void *font_data HB_UNUSED,
304 hb_codepoint_t top_glyph,
305 hb_codepoint_t
306 bottom_glyph,
307 void *user_data HB_UNUSED)
309 if (font->parent)
310 return hb_font_parent_scale_y_distance(font,
311 hb_font_get_glyph_v_kerning
312 (font->parent, top_glyph,
313 bottom_glyph));
314 return 0;
317 static hb_bool_t hb_font_get_glyph_extents_nil(hb_font_t * font,
318 void *font_data HB_UNUSED,
319 hb_codepoint_t glyph,
320 hb_glyph_extents_t * extents,
321 void *user_data HB_UNUSED)
323 if (font->parent) {
324 hb_bool_t ret;
326 ret = hb_font_get_glyph_extents(font->parent, glyph, extents);
327 if (ret) {
328 hb_font_parent_scale_position(font, &extents->x_bearing,
329 &extents->y_bearing);
330 hb_font_parent_scale_distance(font, &extents->width,
331 &extents->height);
333 return ret;
336 memset(extents, 0, sizeof(*extents));
337 return FALSE;
340 static hb_bool_t hb_font_get_glyph_contour_point_nil(hb_font_t * font,
341 void *font_data HB_UNUSED,
342 hb_codepoint_t glyph,
343 unsigned int point_index,
344 hb_position_t * x,
345 hb_position_t * y,
346 void *user_data HB_UNUSED)
348 if (font->parent) {
349 hb_bool_t ret;
351 ret =
352 hb_font_get_glyph_contour_point(font->parent, glyph,
353 point_index, x, y);
354 if (ret)
355 hb_font_parent_scale_position(font, x, y);
356 return ret;
359 *x = *y = 0;
360 return FALSE;
363 static hb_bool_t hb_font_get_glyph_name_nil(hb_font_t * font,
364 void *font_data HB_UNUSED,
365 hb_codepoint_t glyph, char *name,
366 unsigned int size,
367 void *user_data HB_UNUSED)
369 if (font->parent)
370 return hb_font_get_glyph_name(font->parent, glyph, name, size);
372 if (size)
373 *name = '\0';
374 return FALSE;
377 static hb_bool_t hb_font_get_glyph_from_name_nil(hb_font_t * font,
378 void *font_data HB_UNUSED,
379 const char *name,
380 int len
381 /*-1 means nul-terminated*/ ,
382 hb_codepoint_t * glyph,
383 void *user_data HB_UNUSED)
385 if (font->parent)
386 return hb_font_get_glyph_from_name(font->parent, name, len,
387 glyph);
389 *glyph = 0;
390 return FALSE;
393 /*A bit higher-level, and with fallback*/
395 void hb_font_get_glyph_advance_for_direction(hb_font_t * font,
396 hb_codepoint_t glyph,
397 hb_direction_t direction,
398 hb_position_t * x,
399 hb_position_t * y)
401 if (HB_DIRECTION_IS_HORIZONTAL(direction)) {
402 *x = hb_font_get_glyph_h_advance(font, glyph);
403 *y = 0;
404 } else {
405 *x = 0;
406 *y = hb_font_get_glyph_v_advance(font, glyph);
410 /*Internal only*/
411 static void
412 hb_font_guess_v_origin_minus_h_origin(hb_font_t * font, hb_codepoint_t glyph,
413 hb_position_t * x, hb_position_t * y)
415 *x = hb_font_get_glyph_h_advance(font, glyph) / 2;
417 /*TODO:use font_metics.ascent */
418 *y = font->y_scale;
421 void hb_font_get_glyph_origin_for_direction(hb_font_t * font,
422 hb_codepoint_t glyph,
423 hb_direction_t direction,
424 hb_position_t * x,
425 hb_position_t * y)
427 if (HB_DIRECTION_IS_HORIZONTAL(direction)) {
428 if (!hb_font_get_glyph_h_origin(font, glyph, x, y)
429 && hb_font_get_glyph_v_origin(font, glyph, x, y)) {
430 hb_position_t dx, dy;
431 hb_font_guess_v_origin_minus_h_origin(font, glyph, &dx,
432 &dy);
433 *x -= dx;
434 *y -= dy;
436 } else {
437 if (!hb_font_get_glyph_v_origin(font, glyph, x, y)
438 && hb_font_get_glyph_h_origin(font, glyph, x, y)) {
439 hb_position_t dx, dy;
440 hb_font_guess_v_origin_minus_h_origin(font, glyph, &dx,
441 &dy);
442 *x += dx;
443 *y += dy;
448 void hb_font_subtract_glyph_origin_for_direction(hb_font_t * font,
449 hb_codepoint_t glyph,
450 hb_direction_t direction,
451 hb_position_t * x,
452 hb_position_t * y)
454 hb_position_t origin_x, origin_y;
456 hb_font_get_glyph_origin_for_direction(font, glyph, direction,
457 &origin_x, &origin_y);
459 *x -= origin_x;
460 *y -= origin_y;
463 /*XXX:should go in lib "global init"*/
464 static hb_font_funcs_t hb_font_funcs_nil = {
465 REF_CNT_INVALID_VAL, /*ref_cnt */
466 TRUE, /*immutable */
467 { /*get */
468 hb_font_get_glyph_nil,
469 hb_font_get_glyph_h_advance_nil,
470 hb_font_get_glyph_v_advance_nil,
471 hb_font_get_glyph_h_origin_nil,
472 hb_font_get_glyph_v_origin_nil,
473 hb_font_get_glyph_h_kerning_nil,
474 hb_font_get_glyph_v_kerning_nil,
475 hb_font_get_glyph_extents_nil,
476 hb_font_get_glyph_contour_point_nil,
477 hb_font_get_glyph_name_nil,
478 hb_font_get_glyph_from_name_nil,
480 { /*user_data */
481 NULL, /*glyph */
482 NULL, /*glyph_h_advance */
483 NULL, /*glyph_v_advance */
484 NULL, /*glyph_h_origin */
485 NULL, /*glyph_v_origin */
486 NULL, /*glyph_h_kerning */
487 NULL, /*glyph_v_kerning */
488 NULL, /*glyph_extents */
489 NULL, /*glyph_contour_po */
490 NULL, /*glyph_name */
491 NULL, /*glyph_from_name */
493 { /*destroy */
494 NULL, /*glyph */
495 NULL, /*glyph_h_advance */
496 NULL, /*glyph_v_advance */
497 NULL, /*glyph_h_origin */
498 NULL, /*glyph_v_origin */
499 NULL, /*glyph_h_kerning */
500 NULL, /*glyph_v_kerning */
501 NULL, /*glyph_extents */
502 NULL, /*glyph_contour_po */
503 NULL, /*glyph_name */
504 NULL, /*glyph_from_name */
508 /*XXX:should go in lib "global init"*/
509 static hb_font_t hb_font_nil = {
510 REF_CNT_INVALID_VAL, /*ref_cnt */
511 TRUE, /*immutable */
512 NULL, /*parent */
513 NULL, /*face */
514 0, /*x_scale */
515 0, /*y_scale */
516 0, /*x_ppem */
517 0, /*y_ppem */
518 NULL, /*klass */
519 NULL, /*user_data */
520 NULL, /*destroy */
522 #ifdef HAVE_GRAPHITE2
523 HB_SHAPER_DATA_INVALID,
524 #endif
525 #ifdef HAVE_OT
526 HB_SHAPER_DATA_INVALID,
527 #endif
528 HB_SHAPER_DATA_INVALID /*fallback */
532 hb_font_funcs_t *hb_font_funcs_get_empty(void)
534 return &hb_font_funcs_nil;
537 hb_font_t *hb_font_get_empty(void)
539 return &hb_font_nil;
542 void hb_font_funcs_destroy(hb_font_funcs_t * ffuncs)
544 if (!ffuncs)
545 return;
546 if (hb_atomic_int32_get(&ffuncs->ref_cnt) == REF_CNT_INVALID_VAL)
547 return;
548 hb_atomic_int32_add(&ffuncs->ref_cnt, -1);
549 if (hb_atomic_int32_get(&ffuncs->ref_cnt) > 0)
550 return;
551 hb_atomic_int32_set(&ffuncs->ref_cnt, REF_CNT_INVALID_VAL);
553 if (ffuncs->destroy.glyph)
554 ffuncs->destroy.glyph(ffuncs->user_data.glyph);
555 if (ffuncs->destroy.glyph_h_advance)
556 ffuncs->destroy.glyph_h_advance(ffuncs->user_data.
557 glyph_h_advance);
558 if (ffuncs->destroy.glyph_v_advance)
559 ffuncs->destroy.glyph_v_advance(ffuncs->user_data.
560 glyph_v_advance);
561 if (ffuncs->destroy.glyph_h_origin)
562 ffuncs->destroy.glyph_h_origin(ffuncs->user_data.
563 glyph_h_origin);
564 if (ffuncs->destroy.glyph_v_origin)
565 ffuncs->destroy.glyph_v_origin(ffuncs->user_data.
566 glyph_v_origin);
567 if (ffuncs->destroy.glyph_h_kerning)
568 ffuncs->destroy.glyph_h_kerning(ffuncs->user_data.
569 glyph_h_kerning);
570 if (ffuncs->destroy.glyph_v_kerning)
571 ffuncs->destroy.glyph_v_kerning(ffuncs->user_data.
572 glyph_v_kerning);
573 if (ffuncs->destroy.glyph_extents)
574 ffuncs->destroy.glyph_extents(ffuncs->user_data.glyph_extents);
575 if (ffuncs->destroy.glyph_contour_point)
576 ffuncs->destroy.glyph_contour_point(ffuncs->user_data.
577 glyph_contour_point);
578 if (ffuncs->destroy.glyph_name)
579 ffuncs->destroy.glyph_name(ffuncs->user_data.glyph_name);
580 if (ffuncs->destroy.glyph_from_name)
581 ffuncs->destroy.glyph_from_name(ffuncs->user_data.
582 glyph_from_name);
584 free(ffuncs);
587 hb_font_t *hb_font_create(hb_face_t * face)
589 hb_font_t *font;
591 if (!face)
592 face = hb_face_get_empty();
594 if (face->ref_cnt == REF_CNT_INVALID_VAL)
595 return hb_font_get_empty();
597 font = calloc(1, sizeof(*font));
598 if (!font)
599 return hb_font_get_empty();
601 hb_atomic_int32_set(&font->ref_cnt, 1);
602 hb_face_make_immutable(face);
603 font->face = hb_face_reference(face);
604 font->klass = hb_font_funcs_get_empty();
605 return font;
608 void hb_font_funcs_set_glyph_func(hb_font_funcs_t * ffuncs,
609 hb_font_get_glyph_func_t func,
610 void *user_data, hb_destroy_func_t destroy)
612 if (ffuncs->immutable) {
613 if (destroy)
614 destroy(user_data);
615 return;
618 if (ffuncs->destroy.glyph)
619 ffuncs->destroy.glyph(ffuncs->user_data.glyph);
621 if (func) {
622 ffuncs->get.glyph = func;
623 ffuncs->user_data.glyph = user_data;
624 ffuncs->destroy.glyph = destroy;
625 } else {
626 ffuncs->get.glyph = hb_font_get_glyph_nil;
627 ffuncs->user_data.glyph = NULL;
628 ffuncs->destroy.glyph = NULL;
632 void hb_font_funcs_set_glyph_h_advance_func(hb_font_funcs_t * ffuncs,
633 hb_font_get_glyph_h_advance_func_t
634 func, void *user_data,
635 hb_destroy_func_t destroy)
637 if (ffuncs->immutable) {
638 if (destroy)
639 destroy(user_data);
640 return;
643 if (ffuncs->destroy.glyph_h_advance)
644 ffuncs->destroy.glyph_h_advance(ffuncs->user_data.
645 glyph_h_advance);
647 if (func) {
648 ffuncs->get.glyph_h_advance = func;
649 ffuncs->user_data.glyph_h_advance = user_data;
650 ffuncs->destroy.glyph_h_advance = destroy;
651 } else {
652 ffuncs->get.glyph_h_advance = hb_font_get_glyph_h_advance_nil;
653 ffuncs->user_data.glyph_h_advance = NULL;
654 ffuncs->destroy.glyph_h_advance = NULL;
658 void hb_font_funcs_set_glyph_v_advance_func(hb_font_funcs_t * ffuncs,
659 hb_font_get_glyph_v_advance_func_t
660 func, void *user_data,
661 hb_destroy_func_t destroy)
663 if (ffuncs->immutable) {
664 if (destroy)
665 destroy(user_data);
666 return;
669 if (ffuncs->destroy.glyph_v_advance)
670 ffuncs->destroy.glyph_v_advance(ffuncs->user_data.
671 glyph_v_advance);
673 if (func) {
674 ffuncs->get.glyph_v_advance = func;
675 ffuncs->user_data.glyph_v_advance = user_data;
676 ffuncs->destroy.glyph_v_advance = destroy;
677 } else {
678 ffuncs->get.glyph_v_advance = hb_font_get_glyph_v_advance_nil;
679 ffuncs->user_data.glyph_v_advance = NULL;
680 ffuncs->destroy.glyph_v_advance = NULL;
684 void hb_font_funcs_set_glyph_h_origin_func(hb_font_funcs_t * ffuncs,
685 hb_font_get_glyph_h_origin_func_t
686 func, void *user_data,
687 hb_destroy_func_t destroy)
689 if (ffuncs->immutable) {
690 if (destroy)
691 destroy(user_data);
692 return;
695 if (ffuncs->destroy.glyph_h_origin)
696 ffuncs->destroy.glyph_h_origin(ffuncs->user_data.
697 glyph_h_origin);
699 if (func) {
700 ffuncs->get.glyph_h_origin = func;
701 ffuncs->user_data.glyph_h_origin = user_data;
702 ffuncs->destroy.glyph_h_origin = destroy;
703 } else {
704 ffuncs->get.glyph_h_origin = hb_font_get_glyph_h_origin_nil;
705 ffuncs->user_data.glyph_h_origin = NULL;
706 ffuncs->destroy.glyph_h_origin = NULL;
710 void hb_font_funcs_set_glyph_v_origin_func(hb_font_funcs_t * ffuncs,
711 hb_font_get_glyph_v_origin_func_t
712 func, void *user_data,
713 hb_destroy_func_t destroy)
715 if (ffuncs->immutable) {
716 if (destroy)
717 destroy(user_data);
718 return;
721 if (ffuncs->destroy.glyph_v_origin)
722 ffuncs->destroy.glyph_v_origin(ffuncs->user_data.
723 glyph_v_origin);
725 if (func) {
726 ffuncs->get.glyph_v_origin = func;
727 ffuncs->user_data.glyph_v_origin = user_data;
728 ffuncs->destroy.glyph_v_origin = destroy;
729 } else {
730 ffuncs->get.glyph_v_origin = hb_font_get_glyph_v_origin_nil;
731 ffuncs->user_data.glyph_v_origin = NULL;
732 ffuncs->destroy.glyph_v_origin = NULL;
736 void hb_font_funcs_set_glyph_h_kerning_func(hb_font_funcs_t * ffuncs,
737 hb_font_get_glyph_h_kerning_func_t
738 func, void *user_data,
739 hb_destroy_func_t destroy)
741 if (ffuncs->immutable) {
742 if (destroy)
743 destroy(user_data);
744 return;
747 if (ffuncs->destroy.glyph_h_kerning)
748 ffuncs->destroy.glyph_h_kerning(ffuncs->user_data.
749 glyph_h_kerning);
751 if (func) {
752 ffuncs->get.glyph_h_kerning = func;
753 ffuncs->user_data.glyph_h_kerning = user_data;
754 ffuncs->destroy.glyph_h_kerning = destroy;
755 } else {
756 ffuncs->get.glyph_h_kerning = hb_font_get_glyph_h_kerning_nil;
757 ffuncs->user_data.glyph_h_kerning = NULL;
758 ffuncs->destroy.glyph_h_kerning = NULL;
762 void hb_font_funcs_set_glyph_v_kerning_func(hb_font_funcs_t * ffuncs,
763 hb_font_get_glyph_v_kerning_func_t
764 func, void *user_data,
765 hb_destroy_func_t destroy)
767 if (ffuncs->immutable) {
768 if (destroy)
769 destroy(user_data);
770 return;
773 if (ffuncs->destroy.glyph_v_kerning)
774 ffuncs->destroy.glyph_v_kerning(ffuncs->user_data.
775 glyph_v_kerning);
777 if (func) {
778 ffuncs->get.glyph_v_kerning = func;
779 ffuncs->user_data.glyph_v_kerning = user_data;
780 ffuncs->destroy.glyph_v_kerning = destroy;
781 } else {
782 ffuncs->get.glyph_v_kerning = hb_font_get_glyph_v_kerning_nil;
783 ffuncs->user_data.glyph_v_kerning = NULL;
784 ffuncs->destroy.glyph_v_kerning = NULL;
788 void hb_font_funcs_set_glyph_extents_func(hb_font_funcs_t * ffuncs,
789 hb_font_get_glyph_extents_func_t func,
790 void *user_data,
791 hb_destroy_func_t destroy)
793 if (ffuncs->immutable) {
794 if (destroy)
795 destroy(user_data);
796 return;
799 if (ffuncs->destroy.glyph_extents)
800 ffuncs->destroy.glyph_extents(ffuncs->user_data.glyph_extents);
802 if (func) {
803 ffuncs->get.glyph_extents = func;
804 ffuncs->user_data.glyph_extents = user_data;
805 ffuncs->destroy.glyph_extents = destroy;
806 } else {
807 ffuncs->get.glyph_extents = hb_font_get_glyph_extents_nil;
808 ffuncs->user_data.glyph_extents = NULL;
809 ffuncs->destroy.glyph_extents = NULL;
813 void hb_font_funcs_set_glyph_contour_point_func(hb_font_funcs_t * ffuncs,
814 hb_font_get_glyph_contour_point_func_t
815 func, void *user_data,
816 hb_destroy_func_t destroy)
818 if (ffuncs->immutable) {
819 if (destroy)
820 destroy(user_data);
821 return;
824 if (ffuncs->destroy.glyph_contour_point)
825 ffuncs->destroy.glyph_contour_point(ffuncs->user_data.
826 glyph_contour_point);
828 if (func) {
829 ffuncs->get.glyph_contour_point = func;
830 ffuncs->user_data.glyph_contour_point = user_data;
831 ffuncs->destroy.glyph_contour_point = destroy;
832 } else {
833 ffuncs->get.glyph_contour_point =
834 hb_font_get_glyph_contour_point_nil;
835 ffuncs->user_data.glyph_contour_point = NULL;
836 ffuncs->destroy.glyph_contour_point = NULL;
840 void hb_font_funcs_set_glyph_name_func(hb_font_funcs_t * ffuncs,
841 hb_font_get_glyph_name_func_t func,
842 void *user_data,
843 hb_destroy_func_t destroy)
845 if (ffuncs->immutable) {
846 if (destroy)
847 destroy(user_data);
848 return;
851 if (ffuncs->destroy.glyph_name)
852 ffuncs->destroy.glyph_name(ffuncs->user_data.glyph_name);
854 if (func) {
855 ffuncs->get.glyph_name = func;
856 ffuncs->user_data.glyph_name = user_data;
857 ffuncs->destroy.glyph_name = destroy;
858 } else {
859 ffuncs->get.glyph_name = hb_font_get_glyph_name_nil;
860 ffuncs->user_data.glyph_name = NULL;
861 ffuncs->destroy.glyph_name = NULL;
865 void hb_font_funcs_set_glyph_from_name_func(hb_font_funcs_t * ffuncs,
866 hb_font_get_glyph_from_name_func_t
867 func, void *user_data,
868 hb_destroy_func_t destroy)
870 if (ffuncs->immutable) {
871 if (destroy)
872 destroy(user_data);
873 return;
876 if (ffuncs->destroy.glyph_from_name)
877 ffuncs->destroy.glyph_from_name(ffuncs->user_data.
878 glyph_from_name);
880 if (func) {
881 ffuncs->get.glyph_from_name = func;
882 ffuncs->user_data.glyph_from_name = user_data;
883 ffuncs->destroy.glyph_from_name = destroy;
884 } else {
885 ffuncs->get.glyph_from_name = hb_font_get_glyph_from_name_nil;
886 ffuncs->user_data.glyph_from_name = NULL;
887 ffuncs->destroy.glyph_from_name = NULL;
891 hb_font_funcs_t *hb_font_funcs_create(void)
893 hb_font_funcs_t *ffuncs;
895 ffuncs = calloc(1, sizeof(*ffuncs));
896 if (!ffuncs)
897 return hb_font_funcs_get_empty();
898 hb_atomic_int32_set(&ffuncs->ref_cnt, 1);
900 ffuncs->get = hb_font_funcs_nil.get;
901 return ffuncs;
904 void hb_font_set_funcs(hb_font_t * font, hb_font_funcs_t * klass,
905 void *font_data, hb_destroy_func_t destroy)
907 if (font->immutable) {
908 if (destroy)
909 destroy(font_data);
910 return;
913 if (font->destroy)
914 font->destroy(font->user_data);
916 if (!klass)
917 klass = hb_font_funcs_get_empty();
919 hb_font_funcs_reference(klass);
920 hb_font_funcs_destroy(font->klass);
921 font->klass = klass;
922 font->user_data = font_data;
923 font->destroy = destroy;
926 hb_font_funcs_t *hb_font_funcs_reference(hb_font_funcs_t * ffuncs)
928 if (hb_atomic_int32_get(&ffuncs->ref_cnt) != REF_CNT_INVALID_VAL)
929 hb_atomic_int32_add(&ffuncs->ref_cnt, 1);
930 return ffuncs;
933 void hb_font_set_scale(hb_font_t * font, int x_scale, int y_scale)
935 if (font->immutable)
936 return;
938 font->x_scale = x_scale;
939 font->y_scale = y_scale;
942 void hb_font_set_ppem(hb_font_t * font, unsigned int x_ppem,
943 unsigned int y_ppem)
945 if (font->immutable)
946 return;
948 font->x_ppem = x_ppem;
949 font->y_ppem = y_ppem;