1 : /*
2 : * Copyright © 2009 Red Hat, Inc.
3 : *
4 : * This is part of HarfBuzz, a text shaping library.
5 : *
6 : * Permission is hereby granted, without written agreement and without
7 : * license or royalty fees, to use, copy, modify, and distribute this
8 : * software and its documentation for any purpose, provided that the
9 : * above copyright notice and the following two paragraphs appear in
10 : * all copies of this software.
11 : *
12 : * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 : * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 : * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 : * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 : * DAMAGE.
17 : *
18 : * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 : * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 : * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 : * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 : * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 : *
24 : * Red Hat Author(s): Behdad Esfahbod
25 : */
26 :
27 : #include "hb-private.hh"
28 :
29 : #include "hb-ot-layout-private.hh"
30 :
31 : #include "hb-font-private.hh"
32 : #include "hb-blob.h"
33 : #include "hb-open-file-private.hh"
34 : #include "hb-ot-head-table.hh"
35 :
36 : #include <string.h>
37 :
38 :
39 :
40 : /*
41 : * hb_font_funcs_t
42 : */
43 :
44 : static hb_bool_t
45 0 : hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
46 : void *font_data HB_UNUSED,
47 : hb_codepoint_t unicode,
48 : hb_codepoint_t variation_selector,
49 : hb_codepoint_t *glyph,
50 : void *user_data HB_UNUSED)
51 : {
52 0 : if (font->parent)
53 0 : return hb_font_get_glyph (font->parent, unicode, variation_selector, glyph);
54 :
55 0 : *glyph = 0;
56 0 : return FALSE;
57 : }
58 :
59 : static hb_position_t
60 0 : hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
61 : void *font_data HB_UNUSED,
62 : hb_codepoint_t glyph,
63 : void *user_data HB_UNUSED)
64 : {
65 0 : if (font->parent)
66 0 : return font->parent_scale_x_distance (hb_font_get_glyph_h_advance (font->parent, glyph));
67 :
68 0 : return font->x_scale;
69 : }
70 :
71 : static hb_position_t
72 0 : hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
73 : void *font_data HB_UNUSED,
74 : hb_codepoint_t glyph,
75 : void *user_data HB_UNUSED)
76 : {
77 0 : if (font->parent)
78 0 : return font->parent_scale_y_distance (hb_font_get_glyph_v_advance (font->parent, glyph));
79 :
80 0 : return font->y_scale;
81 : }
82 :
83 : static hb_bool_t
84 0 : hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
85 : void *font_data HB_UNUSED,
86 : hb_codepoint_t glyph,
87 : hb_position_t *x,
88 : hb_position_t *y,
89 : void *user_data HB_UNUSED)
90 : {
91 0 : if (font->parent) {
92 : hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent,
93 : glyph,
94 0 : x, y);
95 0 : if (ret)
96 0 : font->parent_scale_position (x, y);
97 0 : return ret;
98 : }
99 :
100 0 : *x = *y = 0;
101 0 : return FALSE;
102 : }
103 :
104 : static hb_bool_t
105 0 : hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
106 : void *font_data HB_UNUSED,
107 : hb_codepoint_t glyph,
108 : hb_position_t *x,
109 : hb_position_t *y,
110 : void *user_data HB_UNUSED)
111 : {
112 0 : if (font->parent) {
113 : hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent,
114 : glyph,
115 0 : x, y);
116 0 : if (ret)
117 0 : font->parent_scale_position (x, y);
118 0 : return ret;
119 : }
120 :
121 0 : *x = *y = 0;
122 0 : return FALSE;
123 : }
124 :
125 : static hb_position_t
126 0 : hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
127 : void *font_data HB_UNUSED,
128 : hb_codepoint_t left_glyph,
129 : hb_codepoint_t right_glyph,
130 : void *user_data HB_UNUSED)
131 : {
132 0 : if (font->parent)
133 0 : return font->parent_scale_x_distance (hb_font_get_glyph_h_kerning (font->parent, left_glyph, right_glyph));
134 :
135 0 : return 0;
136 : }
137 :
138 : static hb_position_t
139 0 : hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
140 : void *font_data HB_UNUSED,
141 : hb_codepoint_t top_glyph,
142 : hb_codepoint_t bottom_glyph,
143 : void *user_data HB_UNUSED)
144 : {
145 0 : if (font->parent)
146 0 : return font->parent_scale_y_distance (hb_font_get_glyph_v_kerning (font->parent, top_glyph, bottom_glyph));
147 :
148 0 : return 0;
149 : }
150 :
151 : static hb_bool_t
152 0 : hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
153 : void *font_data HB_UNUSED,
154 : hb_codepoint_t glyph,
155 : hb_glyph_extents_t *extents,
156 : void *user_data HB_UNUSED)
157 : {
158 0 : if (font->parent) {
159 : hb_bool_t ret = hb_font_get_glyph_extents (font->parent,
160 : glyph,
161 0 : extents);
162 0 : if (ret) {
163 0 : font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
164 0 : font->parent_scale_distance (&extents->width, &extents->height);
165 : }
166 0 : return ret;
167 : }
168 :
169 0 : memset (extents, 0, sizeof (*extents));
170 0 : return FALSE;
171 : }
172 :
173 : static hb_bool_t
174 0 : hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
175 : void *font_data HB_UNUSED,
176 : hb_codepoint_t glyph,
177 : unsigned int point_index,
178 : hb_position_t *x,
179 : hb_position_t *y,
180 : void *user_data HB_UNUSED)
181 : {
182 0 : if (font->parent) {
183 : hb_bool_t ret = hb_font_get_glyph_contour_point (font->parent,
184 : glyph, point_index,
185 0 : x, y);
186 0 : if (ret)
187 0 : font->parent_scale_position (x, y);
188 0 : return ret;
189 : }
190 :
191 0 : *x = *y = 0;
192 0 : return FALSE;
193 : }
194 :
195 :
196 : static hb_font_funcs_t _hb_font_funcs_nil = {
197 : HB_OBJECT_HEADER_STATIC,
198 :
199 : TRUE, /* immutable */
200 :
201 : {
202 : #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
203 : HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
204 : #undef HB_FONT_FUNC_IMPLEMENT
205 : }
206 1464 : };
207 :
208 :
209 : hb_font_funcs_t *
210 0 : hb_font_funcs_create (void)
211 : {
212 : hb_font_funcs_t *ffuncs;
213 :
214 0 : if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
215 0 : return &_hb_font_funcs_nil;
216 :
217 0 : ffuncs->get = _hb_font_funcs_nil.get;
218 :
219 0 : return ffuncs;
220 : }
221 :
222 : hb_font_funcs_t *
223 0 : hb_font_funcs_get_empty (void)
224 : {
225 0 : return &_hb_font_funcs_nil;
226 : }
227 :
228 : hb_font_funcs_t *
229 0 : hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
230 : {
231 0 : return hb_object_reference (ffuncs);
232 : }
233 :
234 : void
235 0 : hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
236 : {
237 0 : if (!hb_object_destroy (ffuncs)) return;
238 :
239 : #define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
240 : ffuncs->destroy.name (ffuncs->user_data.name);
241 0 : HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
242 : #undef HB_FONT_FUNC_IMPLEMENT
243 :
244 0 : free (ffuncs);
245 : }
246 :
247 : hb_bool_t
248 0 : hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
249 : hb_user_data_key_t *key,
250 : void * data,
251 : hb_destroy_func_t destroy,
252 : hb_bool_t replace)
253 : {
254 0 : return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
255 : }
256 :
257 : void *
258 0 : hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
259 : hb_user_data_key_t *key)
260 : {
261 0 : return hb_object_get_user_data (ffuncs, key);
262 : }
263 :
264 :
265 : void
266 0 : hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
267 : {
268 0 : if (hb_object_is_inert (ffuncs))
269 0 : return;
270 :
271 0 : ffuncs->immutable = TRUE;
272 : }
273 :
274 : hb_bool_t
275 0 : hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
276 : {
277 0 : return ffuncs->immutable;
278 : }
279 :
280 :
281 : #define HB_FONT_FUNC_IMPLEMENT(name) \
282 : \
283 : void \
284 : hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
285 : hb_font_get_##name##_func_t func, \
286 : void *user_data, \
287 : hb_destroy_func_t destroy) \
288 : { \
289 : if (ffuncs->immutable) { \
290 : if (destroy) \
291 : destroy (user_data); \
292 : return; \
293 : } \
294 : \
295 : if (ffuncs->destroy.name) \
296 : ffuncs->destroy.name (ffuncs->user_data.name); \
297 : \
298 : if (func) { \
299 : ffuncs->get.name = func; \
300 : ffuncs->user_data.name = user_data; \
301 : ffuncs->destroy.name = destroy; \
302 : } else { \
303 : ffuncs->get.name = hb_font_get_##name##_nil; \
304 : ffuncs->user_data.name = NULL; \
305 : ffuncs->destroy.name = NULL; \
306 : } \
307 : }
308 :
309 0 : HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
310 : #undef HB_FONT_FUNC_IMPLEMENT
311 :
312 :
313 : hb_bool_t
314 0 : hb_font_get_glyph (hb_font_t *font,
315 : hb_codepoint_t unicode, hb_codepoint_t variation_selector,
316 : hb_codepoint_t *glyph)
317 : {
318 0 : *glyph = 0;
319 : return font->klass->get.glyph (font, font->user_data,
320 : unicode, variation_selector, glyph,
321 0 : font->klass->user_data.glyph);
322 : }
323 :
324 : hb_position_t
325 0 : hb_font_get_glyph_h_advance (hb_font_t *font,
326 : hb_codepoint_t glyph)
327 : {
328 : return font->klass->get.glyph_h_advance (font, font->user_data,
329 : glyph,
330 0 : font->klass->user_data.glyph_h_advance);
331 : }
332 :
333 : hb_position_t
334 0 : hb_font_get_glyph_v_advance (hb_font_t *font,
335 : hb_codepoint_t glyph)
336 : {
337 : return font->klass->get.glyph_v_advance (font, font->user_data,
338 : glyph,
339 0 : font->klass->user_data.glyph_v_advance);
340 : }
341 :
342 : hb_bool_t
343 0 : hb_font_get_glyph_h_origin (hb_font_t *font,
344 : hb_codepoint_t glyph,
345 : hb_position_t *x, hb_position_t *y)
346 : {
347 0 : *x = *y = 0;
348 : return font->klass->get.glyph_h_origin (font, font->user_data,
349 : glyph, x, y,
350 0 : font->klass->user_data.glyph_h_origin);
351 : }
352 :
353 : hb_bool_t
354 0 : hb_font_get_glyph_v_origin (hb_font_t *font,
355 : hb_codepoint_t glyph,
356 : hb_position_t *x, hb_position_t *y)
357 : {
358 0 : *x = *y = 0;
359 : return font->klass->get.glyph_v_origin (font, font->user_data,
360 : glyph, x, y,
361 0 : font->klass->user_data.glyph_v_origin);
362 : }
363 :
364 : hb_position_t
365 0 : hb_font_get_glyph_h_kerning (hb_font_t *font,
366 : hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
367 : {
368 : return font->klass->get.glyph_h_kerning (font, font->user_data,
369 : left_glyph, right_glyph,
370 0 : font->klass->user_data.glyph_h_kerning);
371 : }
372 :
373 : hb_position_t
374 0 : hb_font_get_glyph_v_kerning (hb_font_t *font,
375 : hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
376 : {
377 : return font->klass->get.glyph_v_kerning (font, font->user_data,
378 : left_glyph, right_glyph,
379 0 : font->klass->user_data.glyph_v_kerning);
380 : }
381 :
382 : hb_bool_t
383 0 : hb_font_get_glyph_extents (hb_font_t *font,
384 : hb_codepoint_t glyph,
385 : hb_glyph_extents_t *extents)
386 : {
387 0 : memset (extents, 0, sizeof (*extents));
388 : return font->klass->get.glyph_extents (font, font->user_data,
389 : glyph,
390 : extents,
391 0 : font->klass->user_data.glyph_extents);
392 : }
393 :
394 : hb_bool_t
395 0 : hb_font_get_glyph_contour_point (hb_font_t *font,
396 : hb_codepoint_t glyph, unsigned int point_index,
397 : hb_position_t *x, hb_position_t *y)
398 : {
399 0 : *x = *y = 0;
400 : return font->klass->get.glyph_contour_point (font, font->user_data,
401 : glyph, point_index,
402 : x, y,
403 0 : font->klass->user_data.glyph_contour_point);
404 : }
405 :
406 :
407 : /* A bit higher-level, and with fallback */
408 :
409 : void
410 0 : hb_font_get_glyph_advance_for_direction (hb_font_t *font,
411 : hb_codepoint_t glyph,
412 : hb_direction_t direction,
413 : hb_position_t *x, hb_position_t *y)
414 : {
415 0 : if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
416 0 : *x = hb_font_get_glyph_h_advance (font, glyph);
417 0 : *y = 0;
418 : } else {
419 0 : *x = 0;
420 0 : *y = hb_font_get_glyph_v_advance (font, glyph);
421 : }
422 0 : }
423 :
424 : static void
425 0 : guess_v_origin_minus_h_origin (hb_font_t *font,
426 : hb_codepoint_t glyph,
427 : hb_position_t *x, hb_position_t *y)
428 : {
429 0 : *x = hb_font_get_glyph_h_advance (font, glyph) / 2;
430 :
431 : /* TODO use font_metics.ascent */
432 0 : *y = font->y_scale;
433 0 : }
434 :
435 :
436 : void
437 0 : hb_font_get_glyph_origin_for_direction (hb_font_t *font,
438 : hb_codepoint_t glyph,
439 : hb_direction_t direction,
440 : hb_position_t *x, hb_position_t *y)
441 : {
442 0 : if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
443 0 : hb_bool_t ret = hb_font_get_glyph_h_origin (font, glyph, x, y);
444 0 : if (!ret && (ret = hb_font_get_glyph_v_origin (font, glyph, x, y))) {
445 : hb_position_t dx, dy;
446 0 : guess_v_origin_minus_h_origin (font, glyph, &dx, &dy);
447 0 : *x -= dx; *y -= dy;
448 : }
449 : } else {
450 0 : hb_bool_t ret = hb_font_get_glyph_v_origin (font, glyph, x, y);
451 0 : if (!ret && (ret = hb_font_get_glyph_h_origin (font, glyph, x, y))) {
452 : hb_position_t dx, dy;
453 0 : guess_v_origin_minus_h_origin (font, glyph, &dx, &dy);
454 0 : *x += dx; *y += dy;
455 : }
456 : }
457 0 : }
458 :
459 : void
460 0 : hb_font_add_glyph_origin_for_direction (hb_font_t *font,
461 : hb_codepoint_t glyph,
462 : hb_direction_t direction,
463 : hb_position_t *x, hb_position_t *y)
464 : {
465 : hb_position_t origin_x, origin_y;
466 :
467 0 : hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y);
468 :
469 0 : *x += origin_x;
470 0 : *y += origin_y;
471 0 : }
472 :
473 : void
474 0 : hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
475 : hb_codepoint_t glyph,
476 : hb_direction_t direction,
477 : hb_position_t *x, hb_position_t *y)
478 : {
479 : hb_position_t origin_x, origin_y;
480 :
481 0 : hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y);
482 :
483 0 : *x -= origin_x;
484 0 : *y -= origin_y;
485 0 : }
486 :
487 : void
488 0 : hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
489 : hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
490 : hb_direction_t direction,
491 : hb_position_t *x, hb_position_t *y)
492 : {
493 0 : if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
494 0 : *x = hb_font_get_glyph_h_kerning (font, first_glyph, second_glyph);
495 0 : *y = 0;
496 : } else {
497 0 : *x = 0;
498 0 : *y = hb_font_get_glyph_v_kerning (font, first_glyph, second_glyph);
499 : }
500 0 : }
501 :
502 : hb_bool_t
503 0 : hb_font_get_glyph_extents_for_origin (hb_font_t *font,
504 : hb_codepoint_t glyph,
505 : hb_direction_t direction,
506 : hb_glyph_extents_t *extents)
507 : {
508 0 : hb_bool_t ret = hb_font_get_glyph_extents (font, glyph, extents);
509 :
510 0 : if (ret)
511 0 : hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, &extents->x_bearing, &extents->y_bearing);
512 :
513 0 : return ret;
514 : }
515 :
516 : hb_bool_t
517 0 : hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
518 : hb_codepoint_t glyph, unsigned int point_index,
519 : hb_direction_t direction,
520 : hb_position_t *x, hb_position_t *y)
521 : {
522 0 : hb_bool_t ret = hb_font_get_glyph_contour_point (font, glyph, point_index, x, y);
523 :
524 0 : if (ret)
525 0 : hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, x, y);
526 :
527 0 : return ret;
528 : }
529 :
530 :
531 : /*
532 : * hb_face_t
533 : */
534 :
535 : static hb_face_t _hb_face_nil = {
536 : HB_OBJECT_HEADER_STATIC,
537 :
538 : TRUE, /* immutable */
539 :
540 : NULL, /* reference_table */
541 : NULL, /* user_data */
542 : NULL, /* destroy */
543 :
544 : NULL, /* ot_layout */
545 :
546 : 0, /* index */
547 : 1000 /* upem */
548 1464 : };
549 :
550 :
551 : hb_face_t *
552 0 : hb_face_create_for_tables (hb_reference_table_func_t reference_table,
553 : void *user_data,
554 : hb_destroy_func_t destroy)
555 : {
556 : hb_face_t *face;
557 :
558 0 : if (!reference_table || !(face = hb_object_create<hb_face_t> ())) {
559 0 : if (destroy)
560 0 : destroy (user_data);
561 0 : return &_hb_face_nil;
562 : }
563 :
564 0 : face->reference_table = reference_table;
565 0 : face->user_data = user_data;
566 0 : face->destroy = destroy;
567 :
568 0 : face->ot_layout = _hb_ot_layout_create (face);
569 :
570 0 : face->upem = 0;
571 :
572 0 : return face;
573 : }
574 :
575 :
576 : typedef struct _hb_face_for_data_closure_t {
577 : hb_blob_t *blob;
578 : unsigned int index;
579 : } hb_face_for_data_closure_t;
580 :
581 : static hb_face_for_data_closure_t *
582 0 : _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
583 : {
584 : hb_face_for_data_closure_t *closure;
585 :
586 0 : closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
587 0 : if (unlikely (!closure))
588 0 : return NULL;
589 :
590 0 : closure->blob = blob;
591 0 : closure->index = index;
592 :
593 0 : return closure;
594 : }
595 :
596 : static void
597 0 : _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
598 : {
599 0 : hb_blob_destroy (closure->blob);
600 0 : free (closure);
601 0 : }
602 :
603 : static hb_blob_t *
604 0 : _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
605 : {
606 0 : hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
607 :
608 0 : if (tag == HB_TAG_NONE)
609 0 : return hb_blob_reference (data->blob);
610 :
611 0 : const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
612 0 : const OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
613 :
614 0 : const OpenTypeTable &table = ot_face.get_table_by_tag (tag);
615 :
616 0 : hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
617 :
618 0 : return blob;
619 : }
620 :
621 : hb_face_t *
622 0 : hb_face_create (hb_blob_t *blob,
623 : unsigned int index)
624 : {
625 : hb_face_t *face;
626 :
627 0 : if (unlikely (!blob || !hb_blob_get_length (blob)))
628 0 : return &_hb_face_nil;
629 :
630 0 : hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
631 :
632 0 : if (unlikely (!closure))
633 0 : return &_hb_face_nil;
634 :
635 : face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
636 : closure,
637 0 : (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
638 :
639 0 : hb_face_set_index (face, index);
640 :
641 0 : return face;
642 : }
643 :
644 : hb_face_t *
645 0 : hb_face_get_empty (void)
646 : {
647 0 : return &_hb_face_nil;
648 : }
649 :
650 :
651 : hb_face_t *
652 0 : hb_face_reference (hb_face_t *face)
653 : {
654 0 : return hb_object_reference (face);
655 : }
656 :
657 : void
658 0 : hb_face_destroy (hb_face_t *face)
659 : {
660 0 : if (!hb_object_destroy (face)) return;
661 :
662 0 : _hb_ot_layout_destroy (face->ot_layout);
663 :
664 0 : if (face->destroy)
665 0 : face->destroy (face->user_data);
666 :
667 0 : free (face);
668 : }
669 :
670 : hb_bool_t
671 0 : hb_face_set_user_data (hb_face_t *face,
672 : hb_user_data_key_t *key,
673 : void * data,
674 : hb_destroy_func_t destroy,
675 : hb_bool_t replace)
676 : {
677 0 : return hb_object_set_user_data (face, key, data, destroy, replace);
678 : }
679 :
680 : void *
681 0 : hb_face_get_user_data (hb_face_t *face,
682 : hb_user_data_key_t *key)
683 : {
684 0 : return hb_object_get_user_data (face, key);
685 : }
686 :
687 : void
688 0 : hb_face_make_immutable (hb_face_t *face)
689 : {
690 0 : if (hb_object_is_inert (face))
691 0 : return;
692 :
693 0 : face->immutable = true;
694 : }
695 :
696 : hb_bool_t
697 0 : hb_face_is_immutable (hb_face_t *face)
698 : {
699 0 : return face->immutable;
700 : }
701 :
702 :
703 : hb_blob_t *
704 0 : hb_face_reference_table (hb_face_t *face,
705 : hb_tag_t tag)
706 : {
707 : hb_blob_t *blob;
708 :
709 0 : if (unlikely (!face || !face->reference_table))
710 0 : return hb_blob_get_empty ();
711 :
712 0 : blob = face->reference_table (face, tag, face->user_data);
713 0 : if (unlikely (!blob))
714 0 : return hb_blob_get_empty ();
715 :
716 0 : return blob;
717 : }
718 :
719 : hb_blob_t *
720 0 : hb_face_reference_blob (hb_face_t *face)
721 : {
722 0 : return hb_face_reference_table (face, HB_TAG_NONE);
723 : }
724 :
725 : void
726 0 : hb_face_set_index (hb_face_t *face,
727 : unsigned int index)
728 : {
729 0 : if (hb_object_is_inert (face))
730 0 : return;
731 :
732 0 : face->index = 0;
733 : }
734 :
735 : unsigned int
736 0 : hb_face_get_index (hb_face_t *face)
737 : {
738 0 : return face->index;
739 : }
740 :
741 : void
742 0 : hb_face_set_upem (hb_face_t *face,
743 : unsigned int upem)
744 : {
745 0 : if (hb_object_is_inert (face))
746 0 : return;
747 :
748 0 : face->upem = upem;
749 : }
750 :
751 : unsigned int
752 0 : hb_face_get_upem (hb_face_t *face)
753 : {
754 0 : if (unlikely (!face->upem)) {
755 0 : hb_blob_t *head_blob = Sanitizer<head>::sanitize (hb_face_reference_table (face, HB_OT_TAG_head));
756 0 : const head *head_table = Sanitizer<head>::lock_instance (head_blob);
757 0 : face->upem = head_table->get_upem ();
758 0 : hb_blob_destroy (head_blob);
759 : }
760 0 : return face->upem;
761 : }
762 :
763 :
764 : /*
765 : * hb_font_t
766 : */
767 :
768 : static hb_font_t _hb_font_nil = {
769 : HB_OBJECT_HEADER_STATIC,
770 :
771 : TRUE, /* immutable */
772 :
773 : NULL, /* parent */
774 : &_hb_face_nil,
775 :
776 : 0, /* x_scale */
777 : 0, /* y_scale */
778 :
779 : 0, /* x_ppem */
780 : 0, /* y_ppem */
781 :
782 : &_hb_font_funcs_nil, /* klass */
783 : NULL, /* user_data */
784 : NULL /* destroy */
785 1464 : };
786 :
787 : hb_font_t *
788 0 : hb_font_create (hb_face_t *face)
789 : {
790 : hb_font_t *font;
791 :
792 0 : if (unlikely (!face))
793 0 : face = &_hb_face_nil;
794 0 : if (unlikely (hb_object_is_inert (face)))
795 0 : return &_hb_font_nil;
796 0 : if (!(font = hb_object_create<hb_font_t> ()))
797 0 : return &_hb_font_nil;
798 :
799 0 : hb_face_make_immutable (face);
800 0 : font->face = hb_face_reference (face);
801 0 : font->klass = &_hb_font_funcs_nil;
802 :
803 0 : return font;
804 : }
805 :
806 : hb_font_t *
807 0 : hb_font_create_sub_font (hb_font_t *parent)
808 : {
809 0 : if (unlikely (!parent))
810 0 : return &_hb_font_nil;
811 :
812 0 : hb_font_t *font = hb_font_create (parent->face);
813 :
814 0 : if (unlikely (hb_object_is_inert (font)))
815 0 : return font;
816 :
817 0 : hb_font_make_immutable (parent);
818 0 : font->parent = hb_font_reference (parent);
819 :
820 0 : font->x_scale = parent->x_scale;
821 0 : font->y_scale = parent->y_scale;
822 0 : font->x_ppem = parent->x_ppem;
823 0 : font->y_ppem = parent->y_ppem;
824 :
825 0 : font->klass = &_hb_font_funcs_nil;
826 :
827 0 : return font;
828 : }
829 :
830 : hb_font_t *
831 0 : hb_font_get_empty (void)
832 : {
833 0 : return &_hb_font_nil;
834 : }
835 :
836 : hb_font_t *
837 0 : hb_font_reference (hb_font_t *font)
838 : {
839 0 : return hb_object_reference (font);
840 : }
841 :
842 : void
843 0 : hb_font_destroy (hb_font_t *font)
844 : {
845 0 : if (!hb_object_destroy (font)) return;
846 :
847 0 : hb_font_destroy (font->parent);
848 0 : hb_face_destroy (font->face);
849 0 : hb_font_funcs_destroy (font->klass);
850 0 : if (font->destroy)
851 0 : font->destroy (font->user_data);
852 :
853 0 : free (font);
854 : }
855 :
856 : hb_bool_t
857 0 : hb_font_set_user_data (hb_font_t *font,
858 : hb_user_data_key_t *key,
859 : void * data,
860 : hb_destroy_func_t destroy,
861 : hb_bool_t replace)
862 : {
863 0 : return hb_object_set_user_data (font, key, data, destroy, replace);
864 : }
865 :
866 : void *
867 0 : hb_font_get_user_data (hb_font_t *font,
868 : hb_user_data_key_t *key)
869 : {
870 0 : return hb_object_get_user_data (font, key);
871 : }
872 :
873 : void
874 0 : hb_font_make_immutable (hb_font_t *font)
875 : {
876 0 : if (hb_object_is_inert (font))
877 0 : return;
878 :
879 0 : font->immutable = true;
880 : }
881 :
882 : hb_bool_t
883 0 : hb_font_is_immutable (hb_font_t *font)
884 : {
885 0 : return font->immutable;
886 : }
887 :
888 : hb_font_t *
889 0 : hb_font_get_parent (hb_font_t *font)
890 : {
891 0 : return font->parent;
892 : }
893 :
894 : hb_face_t *
895 0 : hb_font_get_face (hb_font_t *font)
896 : {
897 0 : return font->face;
898 : }
899 :
900 :
901 : void
902 0 : hb_font_set_funcs (hb_font_t *font,
903 : hb_font_funcs_t *klass,
904 : void *user_data,
905 : hb_destroy_func_t destroy)
906 : {
907 0 : if (font->immutable) {
908 0 : if (destroy)
909 0 : destroy (user_data);
910 0 : return;
911 : }
912 :
913 0 : if (font->destroy)
914 0 : font->destroy (font->user_data);
915 :
916 0 : if (!klass)
917 0 : klass = &_hb_font_funcs_nil;
918 :
919 0 : hb_font_funcs_reference (klass);
920 0 : hb_font_funcs_destroy (font->klass);
921 0 : font->klass = klass;
922 0 : font->user_data = user_data;
923 0 : font->destroy = destroy;
924 : }
925 :
926 : void
927 0 : hb_font_set_funcs_data (hb_font_t *font,
928 : void *user_data,
929 : hb_destroy_func_t destroy)
930 : {
931 : /* Destroy user_data? */
932 0 : if (font->immutable) {
933 0 : if (destroy)
934 0 : destroy (user_data);
935 0 : return;
936 : }
937 :
938 0 : if (font->destroy)
939 0 : font->destroy (font->user_data);
940 :
941 0 : font->user_data = user_data;
942 0 : font->destroy = destroy;
943 : }
944 :
945 :
946 : void
947 0 : hb_font_set_scale (hb_font_t *font,
948 : int x_scale,
949 : int y_scale)
950 : {
951 0 : if (font->immutable)
952 0 : return;
953 :
954 0 : font->x_scale = x_scale;
955 0 : font->y_scale = y_scale;
956 : }
957 :
958 : void
959 0 : hb_font_get_scale (hb_font_t *font,
960 : int *x_scale,
961 : int *y_scale)
962 : {
963 0 : if (x_scale) *x_scale = font->x_scale;
964 0 : if (y_scale) *y_scale = font->y_scale;
965 0 : }
966 :
967 : void
968 0 : hb_font_set_ppem (hb_font_t *font,
969 : unsigned int x_ppem,
970 : unsigned int y_ppem)
971 : {
972 0 : if (font->immutable)
973 0 : return;
974 :
975 0 : font->x_ppem = x_ppem;
976 0 : font->y_ppem = y_ppem;
977 : }
978 :
979 : void
980 0 : hb_font_get_ppem (hb_font_t *font,
981 : unsigned int *x_ppem,
982 : unsigned int *y_ppem)
983 : {
984 0 : if (x_ppem) *x_ppem = font->x_ppem;
985 0 : if (y_ppem) *y_ppem = font->y_ppem;
986 4392 : }
987 :
988 :
|