File: | root/firefox-clang/gfx/cairo/cairo/src/cairo-truetype-subset.c |
Warning: | line 338, column 2 Value stored to 'status' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ |
2 | /* cairo - a vector graphics library with display and print output |
3 | * |
4 | * Copyright © 2004 Red Hat, Inc |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it either under the terms of the GNU Lesser General Public |
8 | * License version 2.1 as published by the Free Software Foundation |
9 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
10 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
11 | * notice, a recipient may use your version of this file under either |
12 | * the MPL or the LGPL. |
13 | * |
14 | * You should have received a copy of the LGPL along with this library |
15 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
16 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
17 | * You should have received a copy of the MPL along with this library |
18 | * in the file COPYING-MPL-1.1 |
19 | * |
20 | * The contents of this file are subject to the Mozilla Public License |
21 | * Version 1.1 (the "License"); you may not use this file except in |
22 | * compliance with the License. You may obtain a copy of the License at |
23 | * http://www.mozilla.org/MPL/ |
24 | * |
25 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
26 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
27 | * the specific language governing rights and limitations. |
28 | * |
29 | * The Original Code is the cairo graphics library. |
30 | * |
31 | * The Initial Developer of the Original Code is Red Hat, Inc. |
32 | * |
33 | * Contributor(s): |
34 | * Kristian Høgsberg <krh@redhat.com> |
35 | * Adrian Johnson <ajohnson@redneon.com> |
36 | */ |
37 | |
38 | /* |
39 | * Useful links: |
40 | * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html |
41 | * http://www.microsoft.com/typography/specs/default.htm |
42 | */ |
43 | |
44 | #define _DEFAULT_SOURCE1 /* for snprintf(), strdup() */ |
45 | #include "cairoint.h" |
46 | |
47 | #include "cairo-array-private.h" |
48 | #include "cairo-error-private.h" |
49 | |
50 | #if CAIRO_HAS_FONT_SUBSET1 |
51 | |
52 | #include "cairo-scaled-font-subsets-private.h" |
53 | #include "cairo-truetype-subset-private.h" |
54 | |
55 | |
56 | typedef struct subset_glyph subset_glyph_t; |
57 | struct subset_glyph { |
58 | int parent_index; |
59 | unsigned long location; |
60 | }; |
61 | |
62 | typedef struct _cairo_truetype_font cairo_truetype_font_t; |
63 | |
64 | typedef struct table table_t; |
65 | struct table { |
66 | unsigned long tag; |
67 | cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag); |
68 | int pos; /* position in the font directory */ |
69 | }; |
70 | |
71 | struct _cairo_truetype_font { |
72 | |
73 | cairo_scaled_font_subset_t *scaled_font_subset; |
74 | |
75 | table_t truetype_tables[10]; |
76 | int num_tables; |
77 | |
78 | struct { |
79 | char *font_name; |
80 | char *ps_name; |
81 | int num_glyphs_in_face; /* glyphs in font */ |
82 | long x_min, y_min, x_max, y_max; |
83 | long ascent, descent; |
84 | int units_per_em; |
85 | } base; |
86 | |
87 | subset_glyph_t *glyphs; /* array size: num_glyphs_in_face + 2 */ |
88 | const cairo_scaled_font_backend_t *backend; |
89 | unsigned int num_glyphs; /* glyphs used */ |
90 | int *widths; /* array size: num_glyphs_in_face + 1 */ |
91 | int checksum_index; |
92 | cairo_array_t output; |
93 | cairo_array_t string_offsets; |
94 | unsigned long last_offset; |
95 | unsigned long last_boundary; |
96 | int *parent_to_subset; /* array size: num_glyphs_in_face + 1 */ |
97 | cairo_status_t status; |
98 | cairo_bool_t is_pdf; |
99 | }; |
100 | |
101 | /* |
102 | * Test that the structs we define for TrueType tables have the |
103 | * correct size, ie. they are not padded. |
104 | */ |
105 | #define check(T, S) COMPILE_TIME_ASSERT (sizeof (T) == (S))typedef int compile_time_assertion_at_line_105_failed [(sizeof (T) == (S))?1:-1] |
106 | check (tt_head_t, 54); |
107 | check (tt_hhea_t, 36); |
108 | check (tt_maxp_t, 32); |
109 | check (tt_name_record_t, 12); |
110 | check (tt_name_t, 18); |
111 | check (tt_composite_glyph_t, 16); |
112 | check (tt_glyph_data_t, 26); |
113 | #undef check |
114 | |
115 | static cairo_status_t |
116 | cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, |
117 | unsigned short glyph, |
118 | unsigned short *out); |
119 | |
120 | #define SFNT_VERSION0x00010000 0x00010000 |
121 | #define SFNT_STRING_MAX_LENGTH65535 65535 |
122 | |
123 | static cairo_status_t |
124 | _cairo_truetype_font_set_error (cairo_truetype_font_t *font, |
125 | cairo_status_t status) |
126 | { |
127 | if (status == CAIRO_STATUS_SUCCESS || |
128 | status == (int)CAIRO_INT_STATUS_UNSUPPORTED) |
129 | return status; |
130 | |
131 | _cairo_status_set_error (&font->status, status)do { int ret__; ((void) sizeof ((status < CAIRO_STATUS_LAST_STATUS ) ? 1 : 0), __extension__ ({ if (status < CAIRO_STATUS_LAST_STATUS ) ; else __assert_fail ("status < CAIRO_STATUS_LAST_STATUS" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-truetype-subset.c" , 131, __extension__ __PRETTY_FUNCTION__); })); ((void) sizeof ((sizeof(*&font->status) == sizeof(cairo_atomic_int_t )) ? 1 : 0), __extension__ ({ if (sizeof(*&font->status ) == sizeof(cairo_atomic_int_t)) ; else __assert_fail ("sizeof(*&font->status) == sizeof(cairo_atomic_int_t)" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-truetype-subset.c" , 131, __extension__ __PRETTY_FUNCTION__); })); ret__ = _cairo_atomic_int_cmpxchg_impl ((cairo_atomic_int_t *) &font->status, CAIRO_STATUS_SUCCESS , status); (void) ret__; } while (0); |
132 | |
133 | return _cairo_error (status); |
134 | } |
135 | |
136 | static cairo_status_t |
137 | _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, |
138 | cairo_bool_t is_pdf, |
139 | cairo_truetype_font_t **font_return) |
140 | { |
141 | cairo_status_t status; |
142 | cairo_bool_t is_synthetic; |
143 | cairo_truetype_font_t *font; |
144 | const cairo_scaled_font_backend_t *backend; |
145 | tt_head_t head; |
146 | tt_hhea_t hhea; |
147 | tt_maxp_t maxp; |
148 | unsigned long size; |
149 | |
150 | backend = scaled_font_subset->scaled_font->backend; |
151 | if (!backend->load_truetype_table) |
152 | return CAIRO_INT_STATUS_UNSUPPORTED; |
153 | |
154 | /* FIXME: We should either support subsetting vertical fonts, or fail on |
155 | * vertical. Currently font_options_t doesn't have vertical flag, but |
156 | * it should be added in the future. For now, the freetype backend |
157 | * returns UNSUPPORTED in load_truetype_table if the font is vertical. |
158 | * |
159 | * if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font)) |
160 | * return CAIRO_INT_STATUS_UNSUPPORTED; |
161 | */ |
162 | |
163 | /* We need to use a fallback font if this font differs from the glyf outlines. */ |
164 | if (backend->is_synthetic) { |
165 | status = backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic); |
166 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
167 | return status; |
168 | |
169 | if (is_synthetic) |
170 | return CAIRO_INT_STATUS_UNSUPPORTED; |
171 | } |
172 | |
173 | size = sizeof (tt_head_t); |
174 | status = backend->load_truetype_table (scaled_font_subset->scaled_font, |
175 | TT_TAG_head((int)((uint32_t)'h'<<24 | 'e'<<16 | 'a'<<8 | 'd')), 0, |
176 | (unsigned char *) &head, |
177 | &size); |
178 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
179 | return status; |
180 | |
181 | size = sizeof (tt_maxp_t); |
182 | status = backend->load_truetype_table (scaled_font_subset->scaled_font, |
183 | TT_TAG_maxp((int)((uint32_t)'m'<<24 | 'a'<<16 | 'x'<<8 | 'p')), 0, |
184 | (unsigned char *) &maxp, |
185 | &size); |
186 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
187 | return status; |
188 | |
189 | size = sizeof (tt_hhea_t); |
190 | status = backend->load_truetype_table (scaled_font_subset->scaled_font, |
191 | TT_TAG_hhea((int)((uint32_t)'h'<<24 | 'h'<<16 | 'e'<<8 | 'a')), 0, |
192 | (unsigned char *) &hhea, |
193 | &size); |
194 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
195 | return status; |
196 | |
197 | font = _cairo_malloc (sizeof (cairo_truetype_font_t))((sizeof (cairo_truetype_font_t)) != 0 ? malloc(sizeof (cairo_truetype_font_t )) : ((void*)0)); |
198 | if (unlikely (font == NULL)(__builtin_expect (!!(font == ((void*)0)), 0))) |
199 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
200 | |
201 | font->backend = backend; |
202 | font->base.num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs); |
203 | font->scaled_font_subset = scaled_font_subset; |
204 | |
205 | font->last_offset = 0; |
206 | font->last_boundary = 0; |
207 | _cairo_array_init (&font->output, sizeof (char)); |
208 | status = _cairo_array_grow_by (&font->output, 4096); |
209 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
210 | goto fail1; |
211 | |
212 | /* Add 2: +1 case font does not contain .notdef, and +1 because an extra |
213 | * entry is required to contain the end location of the last glyph. |
214 | */ |
215 | font->glyphs = calloc (font->base.num_glyphs_in_face + 2, sizeof (subset_glyph_t)); |
216 | if (unlikely (font->glyphs == NULL)(__builtin_expect (!!(font->glyphs == ((void*)0)), 0))) { |
217 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
218 | goto fail1; |
219 | } |
220 | |
221 | /* Add 1 in case font does not contain .notdef */ |
222 | font->parent_to_subset = calloc (font->base.num_glyphs_in_face + 1, sizeof (int)); |
223 | if (unlikely (font->parent_to_subset == NULL)(__builtin_expect (!!(font->parent_to_subset == ((void*)0) ), 0))) { |
224 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
225 | goto fail2; |
226 | } |
227 | |
228 | font->is_pdf = is_pdf; |
229 | font->num_glyphs = 0; |
230 | font->base.x_min = (int16_t) be16_to_cpu (head.x_min); |
231 | font->base.y_min = (int16_t) be16_to_cpu (head.y_min); |
232 | font->base.x_max = (int16_t) be16_to_cpu (head.x_max); |
233 | font->base.y_max = (int16_t) be16_to_cpu (head.y_max); |
234 | font->base.ascent = (int16_t) be16_to_cpu (hhea.ascender); |
235 | font->base.descent = (int16_t) be16_to_cpu (hhea.descender); |
236 | font->base.units_per_em = (int16_t) be16_to_cpu (head.units_per_em); |
237 | if (font->base.units_per_em == 0) |
238 | font->base.units_per_em = 2048; |
239 | |
240 | font->base.ps_name = NULL((void*)0); |
241 | font->base.font_name = NULL((void*)0); |
242 | status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font, |
243 | &font->base.ps_name, |
244 | &font->base.font_name); |
245 | if (_cairo_status_is_error (status)((status) != CAIRO_STATUS_SUCCESS && (status) < CAIRO_STATUS_LAST_STATUS )) |
246 | goto fail3; |
247 | |
248 | /* If the PS name is not found, create a CairoFont-x-y name. */ |
249 | if (font->base.ps_name == NULL((void*)0)) { |
250 | font->base.ps_name = _cairo_malloc (30)((30) != 0 ? malloc(30) : ((void*)0)); |
251 | if (unlikely (font->base.ps_name == NULL)(__builtin_expect (!!(font->base.ps_name == ((void*)0)), 0 ))) { |
252 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
253 | goto fail3; |
254 | } |
255 | |
256 | snprintf(font->base.ps_name, 30, "CairoFont-%u-%u", |
257 | scaled_font_subset->font_id, |
258 | scaled_font_subset->subset_id); |
259 | } |
260 | |
261 | /* Add 1 in case font does not contain .notdef */ |
262 | font->widths = calloc (font->base.num_glyphs_in_face + 1, sizeof (int)); |
263 | if (unlikely (font->widths == NULL)(__builtin_expect (!!(font->widths == ((void*)0)), 0))) { |
264 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
265 | goto fail4; |
266 | } |
267 | |
268 | _cairo_array_init (&font->string_offsets, sizeof (unsigned long)); |
269 | status = _cairo_array_grow_by (&font->string_offsets, 10); |
270 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
271 | goto fail5; |
272 | |
273 | font->status = CAIRO_STATUS_SUCCESS; |
274 | |
275 | *font_return = font; |
276 | |
277 | return CAIRO_STATUS_SUCCESS; |
278 | |
279 | fail5: |
280 | _cairo_array_fini (&font->string_offsets); |
281 | free (font->widths); |
282 | fail4: |
283 | free (font->base.ps_name); |
284 | fail3: |
285 | free (font->parent_to_subset); |
286 | free (font->base.font_name); |
287 | fail2: |
288 | free (font->glyphs); |
289 | fail1: |
290 | _cairo_array_fini (&font->output); |
291 | free (font); |
292 | |
293 | return status; |
294 | } |
295 | |
296 | static void |
297 | cairo_truetype_font_destroy (cairo_truetype_font_t *font) |
298 | { |
299 | _cairo_array_fini (&font->string_offsets); |
300 | free (font->widths); |
301 | free (font->base.ps_name); |
302 | free (font->base.font_name); |
303 | free (font->parent_to_subset); |
304 | free (font->glyphs); |
305 | _cairo_array_fini (&font->output); |
306 | free (font); |
307 | } |
308 | |
309 | static cairo_status_t |
310 | cairo_truetype_font_allocate_write_buffer (cairo_truetype_font_t *font, |
311 | size_t length, |
312 | unsigned char **buffer) |
313 | { |
314 | cairo_status_t status; |
315 | |
316 | if (font->status) |
317 | return font->status; |
318 | |
319 | status = _cairo_array_allocate (&font->output, length, (void **) buffer); |
320 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
321 | return _cairo_truetype_font_set_error (font, status); |
322 | |
323 | return CAIRO_STATUS_SUCCESS; |
324 | } |
325 | |
326 | static void |
327 | cairo_truetype_font_write (cairo_truetype_font_t *font, |
328 | const void *data, |
329 | size_t length) |
330 | { |
331 | cairo_status_t status; |
332 | |
333 | if (font->status) |
334 | return; |
335 | |
336 | status = _cairo_array_append_multiple (&font->output, data, length); |
337 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
338 | status = _cairo_truetype_font_set_error (font, status); |
Value stored to 'status' is never read | |
339 | } |
340 | |
341 | static void |
342 | cairo_truetype_font_write_be16 (cairo_truetype_font_t *font, |
343 | uint16_t value) |
344 | { |
345 | uint16_t be16_value; |
346 | |
347 | if (font->status) |
348 | return; |
349 | |
350 | be16_value = cpu_to_be16 (value); |
351 | cairo_truetype_font_write (font, &be16_value, sizeof be16_value); |
352 | } |
353 | |
354 | static void |
355 | cairo_truetype_font_write_be32 (cairo_truetype_font_t *font, |
356 | uint32_t value) |
357 | { |
358 | uint32_t be32_value; |
359 | |
360 | if (font->status) |
361 | return; |
362 | |
363 | be32_value = cpu_to_be32 (value); |
364 | cairo_truetype_font_write (font, &be32_value, sizeof be32_value); |
365 | } |
366 | |
367 | static cairo_status_t |
368 | cairo_truetype_font_align_output (cairo_truetype_font_t *font, |
369 | unsigned long *aligned) |
370 | { |
371 | int length, pad; |
372 | unsigned char *padding; |
373 | |
374 | length = _cairo_array_num_elements (&font->output); |
375 | *aligned = (length + 3) & ~3; |
376 | pad = *aligned - length; |
377 | |
378 | if (pad) { |
379 | cairo_status_t status; |
380 | |
381 | status = cairo_truetype_font_allocate_write_buffer (font, pad, |
382 | &padding); |
383 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
384 | return status; |
385 | |
386 | memset (padding, 0, pad); |
387 | } |
388 | |
389 | return CAIRO_STATUS_SUCCESS; |
390 | } |
391 | |
392 | static cairo_status_t |
393 | cairo_truetype_font_check_boundary (cairo_truetype_font_t *font, |
394 | unsigned long boundary) |
395 | { |
396 | cairo_status_t status; |
397 | |
398 | if (font->status) |
399 | return font->status; |
400 | |
401 | if (boundary - font->last_offset > SFNT_STRING_MAX_LENGTH65535) |
402 | { |
403 | status = _cairo_array_append (&font->string_offsets, |
404 | &font->last_boundary); |
405 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
406 | return _cairo_truetype_font_set_error (font, status); |
407 | |
408 | font->last_offset = font->last_boundary; |
409 | } |
410 | font->last_boundary = boundary; |
411 | |
412 | return CAIRO_STATUS_SUCCESS; |
413 | } |
414 | |
415 | typedef struct _cmap_unicode_range { |
416 | unsigned int start; |
417 | unsigned int end; |
418 | } cmap_unicode_range_t; |
419 | |
420 | static cmap_unicode_range_t winansi_unicode_ranges[] = { |
421 | { 0x0020, 0x007f }, |
422 | { 0x00a0, 0x00ff }, |
423 | { 0x0152, 0x0153 }, |
424 | { 0x0160, 0x0161 }, |
425 | { 0x0178, 0x0178 }, |
426 | { 0x017d, 0x017e }, |
427 | { 0x0192, 0x0192 }, |
428 | { 0x02c6, 0x02c6 }, |
429 | { 0x02dc, 0x02dc }, |
430 | { 0x2013, 0x2026 }, |
431 | { 0x2030, 0x2030 }, |
432 | { 0x2039, 0x203a }, |
433 | { 0x20ac, 0x20ac }, |
434 | { 0x2122, 0x2122 }, |
435 | }; |
436 | |
437 | static cairo_status_t |
438 | cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font, |
439 | unsigned long tag) |
440 | { |
441 | int i; |
442 | unsigned int j; |
443 | int range_offset; |
444 | int num_ranges; |
445 | int entry_selector; |
446 | int length; |
447 | |
448 | num_ranges = ARRAY_LENGTH (winansi_unicode_ranges)((int) (sizeof (winansi_unicode_ranges) / sizeof (winansi_unicode_ranges [0]))); |
449 | |
450 | length = 16 + (num_ranges + 1)*8; |
451 | for (i = 0; i < num_ranges; i++) |
452 | length += (winansi_unicode_ranges[i].end - winansi_unicode_ranges[i].start + 1)*2; |
453 | |
454 | entry_selector = 0; |
455 | while ((1 << entry_selector) <= (num_ranges + 1)) |
456 | entry_selector++; |
457 | |
458 | entry_selector--; |
459 | |
460 | cairo_truetype_font_write_be16 (font, 0); /* Table version */ |
461 | cairo_truetype_font_write_be16 (font, 1); /* Num tables */ |
462 | |
463 | cairo_truetype_font_write_be16 (font, 3); /* Platform */ |
464 | cairo_truetype_font_write_be16 (font, 1); /* Encoding */ |
465 | cairo_truetype_font_write_be32 (font, 12); /* Offset to start of table */ |
466 | |
467 | /* Output a format 4 encoding table for the winansi encoding */ |
468 | |
469 | cairo_truetype_font_write_be16 (font, 4); /* Format */ |
470 | cairo_truetype_font_write_be16 (font, length); /* Length */ |
471 | cairo_truetype_font_write_be16 (font, 0); /* Version */ |
472 | cairo_truetype_font_write_be16 (font, num_ranges*2 + 2); /* 2*segcount */ |
473 | cairo_truetype_font_write_be16 (font, (1 << (entry_selector + 1))); /* searchrange */ |
474 | cairo_truetype_font_write_be16 (font, entry_selector); /* entry selector */ |
475 | cairo_truetype_font_write_be16 (font, num_ranges*2 + 2 - (1 << (entry_selector + 1))); /* rangeshift */ |
476 | for (i = 0; i < num_ranges; i++) |
477 | cairo_truetype_font_write_be16 (font, winansi_unicode_ranges[i].end); /* end count[] */ |
478 | cairo_truetype_font_write_be16 (font, 0xffff); /* end count[] */ |
479 | |
480 | cairo_truetype_font_write_be16 (font, 0); /* reserved */ |
481 | |
482 | for (i = 0; i < num_ranges; i++) |
483 | cairo_truetype_font_write_be16 (font, winansi_unicode_ranges[i].start); /* startCode[] */ |
484 | cairo_truetype_font_write_be16 (font, 0xffff); /* startCode[] */ |
485 | |
486 | for (i = 0; i < num_ranges; i++) |
487 | cairo_truetype_font_write_be16 (font, 0x0000); /* delta[] */ |
488 | cairo_truetype_font_write_be16 (font, 1); /* delta[] */ |
489 | |
490 | range_offset = num_ranges*2 + 2; |
491 | for (i = 0; i < num_ranges; i++) { |
492 | cairo_truetype_font_write_be16 (font, range_offset); /* rangeOffset[] */ |
493 | range_offset += (winansi_unicode_ranges[i].end - winansi_unicode_ranges[i].start + 1)*2 - 2; |
494 | } |
495 | cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[] */ |
496 | |
497 | for (i = 0; i < num_ranges; i++) { |
498 | for (j = winansi_unicode_ranges[i].start; j < winansi_unicode_ranges[i].end + 1; j++) { |
499 | int ch = _cairo_unicode_to_winansi (j); |
500 | int glyph; |
501 | |
502 | if (ch > 0) |
503 | glyph = font->scaled_font_subset->latin_to_subset_glyph_index[ch]; |
504 | else |
505 | glyph = 0; |
506 | cairo_truetype_font_write_be16 (font, glyph); |
507 | } |
508 | } |
509 | |
510 | return font->status; |
511 | } |
512 | |
513 | static cairo_status_t |
514 | cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font, |
515 | unsigned long tag) |
516 | { |
517 | cairo_status_t status; |
518 | unsigned char *buffer; |
519 | unsigned long size; |
520 | |
521 | if (font->status) |
522 | return font->status; |
523 | |
524 | size = 0; |
525 | status = font->backend->load_truetype_table(font->scaled_font_subset->scaled_font, |
526 | tag, 0, NULL((void*)0), &size); |
527 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
528 | return _cairo_truetype_font_set_error (font, status); |
529 | |
530 | status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); |
531 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
532 | return _cairo_truetype_font_set_error (font, status); |
533 | |
534 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
535 | tag, 0, buffer, &size); |
536 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
537 | return _cairo_truetype_font_set_error (font, status); |
538 | |
539 | return CAIRO_STATUS_SUCCESS; |
540 | } |
541 | |
542 | static cairo_status_t |
543 | cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font, |
544 | unsigned char *buffer, |
545 | unsigned long size) |
546 | { |
547 | tt_glyph_data_t *glyph_data; |
548 | tt_composite_glyph_t *composite_glyph; |
549 | int num_args; |
550 | int has_more_components; |
551 | unsigned short flags; |
552 | unsigned short index; |
553 | cairo_status_t status; |
554 | unsigned char *end = buffer + size; |
555 | |
556 | if (font->status) |
557 | return font->status; |
558 | |
559 | glyph_data = (tt_glyph_data_t *) buffer; |
560 | if ((unsigned char *)(&glyph_data->data) >= end) |
561 | return CAIRO_INT_STATUS_UNSUPPORTED; |
562 | |
563 | if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0) |
564 | return CAIRO_STATUS_SUCCESS; |
565 | |
566 | composite_glyph = &glyph_data->glyph; |
567 | do { |
568 | if ((unsigned char *)(&composite_glyph->args[1]) > end) |
569 | return CAIRO_INT_STATUS_UNSUPPORTED; |
570 | |
571 | flags = be16_to_cpu (composite_glyph->flags); |
572 | has_more_components = flags & TT_MORE_COMPONENTS0x0020; |
573 | status = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index), &index); |
574 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
575 | return status; |
576 | |
577 | composite_glyph->index = cpu_to_be16 (index); |
578 | num_args = 1; |
579 | if (flags & TT_ARG_1_AND_2_ARE_WORDS0x0001) |
580 | num_args += 1; |
581 | |
582 | if (flags & TT_WE_HAVE_A_SCALE0x0008) |
583 | num_args += 1; |
584 | else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE0x0040) |
585 | num_args += 2; |
586 | else if (flags & TT_WE_HAVE_A_TWO_BY_TWO0x0080) |
587 | num_args += 4; |
588 | |
589 | composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]); |
590 | } while (has_more_components); |
591 | |
592 | return CAIRO_STATUS_SUCCESS; |
593 | } |
594 | |
595 | static cairo_status_t |
596 | cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font, |
597 | unsigned long tag) |
598 | { |
599 | unsigned long start_offset, index, size, next; |
600 | tt_head_t header; |
601 | unsigned long begin, end; |
602 | unsigned char *buffer; |
603 | unsigned int i; |
604 | union { |
605 | unsigned char *bytes; |
606 | uint16_t *short_offsets; |
607 | uint32_t *long_offsets; |
608 | } u; |
609 | cairo_status_t status; |
610 | |
611 | if (font->status) |
612 | return font->status; |
613 | |
614 | size = sizeof (tt_head_t); |
615 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
616 | TT_TAG_head((int)((uint32_t)'h'<<24 | 'e'<<16 | 'a'<<8 | 'd')), 0, |
617 | (unsigned char*) &header, &size); |
618 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
619 | return _cairo_truetype_font_set_error (font, status); |
620 | |
621 | if (be16_to_cpu (header.index_to_loc_format) == 0) |
622 | size = sizeof (int16_t) * (font->base.num_glyphs_in_face + 1); |
623 | else |
624 | size = sizeof (int32_t) * (font->base.num_glyphs_in_face + 1); |
625 | |
626 | u.bytes = _cairo_malloc (size)((size) != 0 ? malloc(size) : ((void*)0)); |
627 | if (unlikely (u.bytes == NULL)(__builtin_expect (!!(u.bytes == ((void*)0)), 0))) |
628 | return _cairo_truetype_font_set_error (font, CAIRO_STATUS_NO_MEMORY); |
629 | |
630 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
631 | TT_TAG_loca((int)((uint32_t)'l'<<24 | 'o'<<16 | 'c'<<8 | 'a')), 0, u.bytes, &size); |
632 | if (unlikely (status)(__builtin_expect (!!(status), 0))) { |
633 | free (u.bytes); |
634 | return _cairo_truetype_font_set_error (font, status); |
635 | } |
636 | |
637 | start_offset = _cairo_array_num_elements (&font->output); |
638 | for (i = 0; i < font->num_glyphs; i++) { |
639 | index = font->glyphs[i].parent_index; |
640 | if (be16_to_cpu (header.index_to_loc_format) == 0) { |
641 | begin = be16_to_cpu (u.short_offsets[index]) * 2; |
642 | end = be16_to_cpu (u.short_offsets[index + 1]) * 2; |
643 | } |
644 | else { |
645 | begin = be32_to_cpu (u.long_offsets[index]); |
646 | end = be32_to_cpu (u.long_offsets[index + 1]); |
647 | } |
648 | |
649 | /* quick sanity check... */ |
650 | if (end < begin) { |
651 | status = CAIRO_INT_STATUS_UNSUPPORTED; |
652 | goto FAIL; |
653 | } |
654 | |
655 | size = end - begin; |
656 | status = cairo_truetype_font_align_output (font, &next); |
657 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
658 | goto FAIL; |
659 | |
660 | status = cairo_truetype_font_check_boundary (font, next); |
661 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
662 | goto FAIL; |
663 | |
664 | font->glyphs[i].location = next - start_offset; |
665 | |
666 | status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); |
667 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
668 | goto FAIL; |
669 | |
670 | if (size > 1) { |
671 | tt_glyph_data_t *glyph_data; |
672 | int num_contours; |
673 | |
674 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
675 | TT_TAG_glyf((int)((uint32_t)'g'<<24 | 'l'<<16 | 'y'<<8 | 'f')), begin, buffer, &size); |
676 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
677 | goto FAIL; |
678 | |
679 | glyph_data = (tt_glyph_data_t *) buffer; |
680 | num_contours = (int16_t)be16_to_cpu (glyph_data->num_contours); |
681 | if (num_contours < 0) { |
682 | status = cairo_truetype_font_remap_composite_glyph (font, buffer, size); |
683 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
684 | goto FAIL; |
685 | } else if (num_contours == 0) { |
686 | /* num_contours == 0 is undefined in the Opentype |
687 | * spec. There are some embedded fonts that have a |
688 | * space glyph with num_contours = 0 that fails on |
689 | * some printers. The spec requires glyphs without |
690 | * contours to have a 0 size glyph entry in the loca |
691 | * table. |
692 | * |
693 | * If num_contours == 0, truncate the glyph to 0 size. |
694 | */ |
695 | _cairo_array_truncate (&font->output, _cairo_array_num_elements (&font->output) - size); |
696 | } |
697 | } |
698 | } |
699 | |
700 | status = cairo_truetype_font_align_output (font, &next); |
701 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
702 | goto FAIL; |
703 | |
704 | font->glyphs[i].location = next - start_offset; |
705 | |
706 | status = font->status; |
707 | FAIL: |
708 | free (u.bytes); |
709 | |
710 | return _cairo_truetype_font_set_error (font, status); |
711 | } |
712 | |
713 | static cairo_status_t |
714 | cairo_truetype_font_write_head_table (cairo_truetype_font_t *font, |
715 | unsigned long tag) |
716 | { |
717 | unsigned char *buffer; |
718 | unsigned long size; |
719 | cairo_status_t status; |
720 | |
721 | if (font->status) |
722 | return font->status; |
723 | |
724 | size = 0; |
725 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
726 | tag, 0, NULL((void*)0), &size); |
727 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
728 | return _cairo_truetype_font_set_error (font, status); |
729 | |
730 | font->checksum_index = _cairo_array_num_elements (&font->output) + 8; |
731 | status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); |
732 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
733 | return _cairo_truetype_font_set_error (font, status); |
734 | |
735 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
736 | tag, 0, buffer, &size); |
737 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
738 | return _cairo_truetype_font_set_error (font, status); |
739 | |
740 | /* set checkSumAdjustment to 0 for table checksum calculation */ |
741 | *(uint32_t *)(buffer + 8) = 0; |
742 | |
743 | return CAIRO_STATUS_SUCCESS; |
744 | } |
745 | |
746 | static cairo_status_t |
747 | cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag) |
748 | { |
749 | tt_hhea_t *hhea; |
750 | unsigned long size; |
751 | cairo_status_t status; |
752 | |
753 | if (font->status) |
754 | return font->status; |
755 | |
756 | size = sizeof (tt_hhea_t); |
757 | status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &hhea); |
758 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
759 | return _cairo_truetype_font_set_error (font, status); |
760 | |
761 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
762 | tag, 0, (unsigned char *) hhea, &size); |
763 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
764 | return _cairo_truetype_font_set_error (font, status); |
765 | |
766 | hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->num_glyphs)); |
767 | |
768 | return CAIRO_STATUS_SUCCESS; |
769 | } |
770 | |
771 | static cairo_status_t |
772 | cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font, |
773 | unsigned long tag) |
774 | { |
775 | unsigned long size; |
776 | unsigned long long_entry_size; |
777 | unsigned long short_entry_size; |
778 | short *p; |
779 | unsigned int i; |
780 | tt_hhea_t hhea; |
781 | int num_hmetrics; |
782 | cairo_status_t status; |
783 | |
784 | if (font->status) |
785 | return font->status; |
786 | |
787 | size = sizeof (tt_hhea_t); |
788 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
789 | TT_TAG_hhea((int)((uint32_t)'h'<<24 | 'h'<<16 | 'e'<<8 | 'a')), 0, |
790 | (unsigned char*) &hhea, &size); |
791 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
792 | return _cairo_truetype_font_set_error (font, status); |
793 | |
794 | num_hmetrics = be16_to_cpu(hhea.num_hmetrics); |
795 | |
796 | for (i = 0; i < font->num_glyphs; i++) { |
797 | long_entry_size = 2 * sizeof (int16_t); |
798 | short_entry_size = sizeof (int16_t); |
799 | status = cairo_truetype_font_allocate_write_buffer (font, |
800 | long_entry_size, |
801 | (unsigned char **) &p); |
802 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
803 | return _cairo_truetype_font_set_error (font, status); |
804 | |
805 | if (font->glyphs[i].parent_index < num_hmetrics) { |
806 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
807 | TT_TAG_hmtx((int)((uint32_t)'h'<<24 | 'm'<<16 | 't'<<8 | 'x')), |
808 | font->glyphs[i].parent_index * long_entry_size, |
809 | (unsigned char *) p, &long_entry_size); |
810 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
811 | return _cairo_truetype_font_set_error (font, status); |
812 | } |
813 | else |
814 | { |
815 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
816 | TT_TAG_hmtx((int)((uint32_t)'h'<<24 | 'm'<<16 | 't'<<8 | 'x')), |
817 | (num_hmetrics - 1) * long_entry_size, |
818 | (unsigned char *) p, &short_entry_size); |
819 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
820 | return _cairo_truetype_font_set_error (font, status); |
821 | |
822 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
823 | TT_TAG_hmtx((int)((uint32_t)'h'<<24 | 'm'<<16 | 't'<<8 | 'x')), |
824 | num_hmetrics * long_entry_size + |
825 | (font->glyphs[i].parent_index - num_hmetrics) * short_entry_size, |
826 | (unsigned char *) (p + 1), &short_entry_size); |
827 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
828 | return _cairo_truetype_font_set_error (font, status); |
829 | } |
830 | font->widths[i] = be16_to_cpu (p[0]); |
831 | } |
832 | |
833 | return CAIRO_STATUS_SUCCESS; |
834 | } |
835 | |
836 | static cairo_status_t |
837 | cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font, |
838 | unsigned long tag) |
839 | { |
840 | unsigned int i; |
841 | tt_head_t header; |
842 | unsigned long size; |
843 | cairo_status_t status; |
844 | |
845 | if (font->status) |
846 | return font->status; |
847 | |
848 | size = sizeof(tt_head_t); |
849 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
850 | TT_TAG_head((int)((uint32_t)'h'<<24 | 'e'<<16 | 'a'<<8 | 'd')), 0, |
851 | (unsigned char*) &header, &size); |
852 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
853 | return _cairo_truetype_font_set_error (font, status); |
854 | |
855 | if (be16_to_cpu (header.index_to_loc_format) == 0) |
856 | { |
857 | for (i = 0; i < font->num_glyphs + 1; i++) |
858 | cairo_truetype_font_write_be16 (font, font->glyphs[i].location / 2); |
859 | } else { |
860 | for (i = 0; i < font->num_glyphs + 1; i++) |
861 | cairo_truetype_font_write_be32 (font, font->glyphs[i].location); |
862 | } |
863 | |
864 | return font->status; |
865 | } |
866 | |
867 | static cairo_status_t |
868 | cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font, |
869 | unsigned long tag) |
870 | { |
871 | tt_maxp_t *maxp; |
872 | unsigned long size; |
873 | cairo_status_t status; |
874 | |
875 | if (font->status) |
876 | return font->status; |
877 | |
878 | size = sizeof (tt_maxp_t); |
879 | status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp); |
880 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
881 | return _cairo_truetype_font_set_error (font, status); |
882 | |
883 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
884 | tag, 0, (unsigned char *) maxp, &size); |
885 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
886 | return _cairo_truetype_font_set_error (font, status); |
887 | |
888 | maxp->num_glyphs = cpu_to_be16 (font->num_glyphs); |
889 | |
890 | return CAIRO_STATUS_SUCCESS; |
891 | } |
892 | |
893 | static cairo_status_t |
894 | cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font) |
895 | { |
896 | cairo_status_t status; |
897 | unsigned char *table_buffer; |
898 | size_t table_buffer_length; |
899 | unsigned short search_range, entry_selector, range_shift; |
900 | |
901 | if (font->status) |
902 | return font->status; |
903 | |
904 | search_range = 1; |
905 | entry_selector = 0; |
906 | while (search_range * 2 <= font->num_tables) { |
907 | search_range *= 2; |
908 | entry_selector++; |
909 | } |
910 | search_range *= 16; |
911 | range_shift = font->num_tables * 16 - search_range; |
912 | |
913 | cairo_truetype_font_write_be32 (font, SFNT_VERSION0x00010000); |
914 | cairo_truetype_font_write_be16 (font, font->num_tables); |
915 | cairo_truetype_font_write_be16 (font, search_range); |
916 | cairo_truetype_font_write_be16 (font, entry_selector); |
917 | cairo_truetype_font_write_be16 (font, range_shift); |
918 | |
919 | /* Allocate space for the table directory. Each directory entry |
920 | * will be filled in by cairo_truetype_font_update_entry() after |
921 | * the table is written. */ |
922 | table_buffer_length = font->num_tables * 16; |
923 | status = cairo_truetype_font_allocate_write_buffer (font, table_buffer_length, |
924 | &table_buffer); |
925 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
926 | return _cairo_truetype_font_set_error (font, status); |
927 | |
928 | return CAIRO_STATUS_SUCCESS; |
929 | } |
930 | |
931 | static uint32_t |
932 | cairo_truetype_font_calculate_checksum (cairo_truetype_font_t *font, |
933 | unsigned long start, |
934 | unsigned long end) |
935 | { |
936 | uint32_t *padded_end; |
937 | uint32_t *p; |
938 | uint32_t checksum; |
939 | char *data; |
940 | |
941 | checksum = 0; |
942 | data = _cairo_array_index (&font->output, 0); |
943 | p = (uint32_t *) (data + start); |
944 | padded_end = (uint32_t *) (data + ((end + 3) & ~3)); |
945 | while (p < padded_end) |
946 | checksum += be32_to_cpu(*p++); |
947 | |
948 | return checksum; |
949 | } |
950 | |
951 | static void |
952 | cairo_truetype_font_update_entry (cairo_truetype_font_t *font, |
953 | int index, |
954 | unsigned long tag, |
955 | unsigned long start, |
956 | unsigned long end) |
957 | { |
958 | uint32_t *entry; |
959 | |
960 | entry = _cairo_array_index (&font->output, 12 + 16 * index); |
961 | entry[0] = cpu_to_be32 ((uint32_t)tag); |
962 | entry[1] = cpu_to_be32 (cairo_truetype_font_calculate_checksum (font, start, end)); |
963 | entry[2] = cpu_to_be32 ((uint32_t)start); |
964 | entry[3] = cpu_to_be32 ((uint32_t)(end - start)); |
965 | } |
966 | |
967 | static cairo_status_t |
968 | cairo_truetype_font_generate (cairo_truetype_font_t *font, |
969 | const char **data, |
970 | unsigned long *length, |
971 | const unsigned long **string_offsets, |
972 | unsigned long *num_strings) |
973 | { |
974 | cairo_status_t status; |
975 | unsigned long start, end, next; |
976 | uint32_t checksum, *checksum_location; |
977 | int i; |
978 | |
979 | if (font->status) |
980 | return font->status; |
981 | |
982 | status = cairo_truetype_font_write_offset_table (font); |
983 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
984 | goto FAIL; |
985 | |
986 | status = cairo_truetype_font_align_output (font, &start); |
987 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
988 | goto FAIL; |
989 | |
990 | end = 0; |
991 | for (i = 0; i < font->num_tables; i++) { |
992 | status = font->truetype_tables[i].write (font, font->truetype_tables[i].tag); |
993 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
994 | goto FAIL; |
995 | |
996 | end = _cairo_array_num_elements (&font->output); |
997 | status = cairo_truetype_font_align_output (font, &next); |
998 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
999 | goto FAIL; |
1000 | |
1001 | cairo_truetype_font_update_entry (font, font->truetype_tables[i].pos, |
1002 | font->truetype_tables[i].tag, start, end); |
1003 | status = cairo_truetype_font_check_boundary (font, next); |
1004 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
1005 | goto FAIL; |
1006 | |
1007 | start = next; |
1008 | } |
1009 | |
1010 | checksum = |
1011 | 0xb1b0afba - cairo_truetype_font_calculate_checksum (font, 0, end); |
1012 | checksum_location = _cairo_array_index (&font->output, font->checksum_index); |
1013 | *checksum_location = cpu_to_be32 (checksum); |
1014 | |
1015 | *data = _cairo_array_index (&font->output, 0); |
1016 | *length = _cairo_array_num_elements (&font->output); |
1017 | *num_strings = _cairo_array_num_elements (&font->string_offsets); |
1018 | if (*num_strings != 0) |
1019 | *string_offsets = _cairo_array_index (&font->string_offsets, 0); |
1020 | else |
1021 | *string_offsets = NULL((void*)0); |
1022 | |
1023 | FAIL: |
1024 | return _cairo_truetype_font_set_error (font, status); |
1025 | } |
1026 | |
1027 | static cairo_status_t |
1028 | cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, |
1029 | unsigned short glyph, |
1030 | unsigned short *out) |
1031 | { |
1032 | if (glyph >= font->base.num_glyphs_in_face) |
1033 | return CAIRO_INT_STATUS_UNSUPPORTED; |
1034 | |
1035 | if (font->parent_to_subset[glyph] == 0) { |
1036 | font->parent_to_subset[glyph] = font->num_glyphs; |
1037 | font->glyphs[font->num_glyphs].parent_index = glyph; |
1038 | font->num_glyphs++; |
1039 | } |
1040 | |
1041 | *out = font->parent_to_subset[glyph]; |
1042 | return CAIRO_STATUS_SUCCESS; |
1043 | } |
1044 | |
1045 | static void |
1046 | cairo_truetype_font_add_truetype_table (cairo_truetype_font_t *font, |
1047 | unsigned long tag, |
1048 | cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag), |
1049 | int pos) |
1050 | { |
1051 | font->truetype_tables[font->num_tables].tag = tag; |
1052 | font->truetype_tables[font->num_tables].write = write; |
1053 | font->truetype_tables[font->num_tables].pos = pos; |
1054 | font->num_tables++; |
1055 | } |
1056 | |
1057 | /* cairo_truetype_font_create_truetype_table_list() builds the list of |
1058 | * truetype tables to be embedded in the subsetted font. Each call to |
1059 | * cairo_truetype_font_add_truetype_table() adds a table, the callback |
1060 | * for generating the table, and the position in the table directory |
1061 | * to the truetype_tables array. |
1062 | * |
1063 | * As we write out the glyf table we remap composite glyphs. |
1064 | * Remapping composite glyphs will reference the sub glyphs the |
1065 | * composite glyph is made up of. The "glyf" table callback needs to |
1066 | * be called first so we have all the glyphs in the subset before |
1067 | * going further. |
1068 | * |
1069 | * The order in which tables are added to the truetype_table array |
1070 | * using cairo_truetype_font_add_truetype_table() specifies the order |
1071 | * in which the callback functions will be called. |
1072 | * |
1073 | * The tables in the table directory must be listed in alphabetical |
1074 | * order. The "cvt", "fpgm", and "prep" are optional tables. They |
1075 | * will only be embedded in the subset if they exist in the source |
1076 | * font. "cmap" is only embedded for latin fonts. The pos parameter of |
1077 | * cairo_truetype_font_add_truetype_table() specifies the position of |
1078 | * the table in the table directory. |
1079 | */ |
1080 | static void |
1081 | cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font) |
1082 | { |
1083 | cairo_bool_t has_cvt = FALSE0; |
1084 | cairo_bool_t has_fpgm = FALSE0; |
1085 | cairo_bool_t has_prep = FALSE0; |
1086 | unsigned long size; |
1087 | int pos; |
1088 | |
1089 | size = 0; |
1090 | if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1091 | TT_TAG_cvt((int)((uint32_t)'c'<<24 | 'v'<<16 | 't'<<8 | ' ')), 0, NULL((void*)0), |
1092 | &size) == CAIRO_INT_STATUS_SUCCESS) |
1093 | has_cvt = TRUE1; |
1094 | |
1095 | size = 0; |
1096 | if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1097 | TT_TAG_fpgm((int)((uint32_t)'f'<<24 | 'p'<<16 | 'g'<<8 | 'm')), 0, NULL((void*)0), |
1098 | &size) == CAIRO_INT_STATUS_SUCCESS) |
1099 | has_fpgm = TRUE1; |
1100 | |
1101 | size = 0; |
1102 | if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1103 | TT_TAG_prep((int)((uint32_t)'p'<<24 | 'r'<<16 | 'e'<<8 | 'p')), 0, NULL((void*)0), |
1104 | &size) == CAIRO_INT_STATUS_SUCCESS) |
1105 | has_prep = TRUE1; |
1106 | |
1107 | font->num_tables = 0; |
1108 | pos = 0; |
1109 | if (font->is_pdf && font->scaled_font_subset->is_latin) |
1110 | pos++; |
1111 | if (has_cvt) |
1112 | pos++; |
1113 | if (has_fpgm) |
1114 | pos++; |
1115 | cairo_truetype_font_add_truetype_table (font, TT_TAG_glyf((int)((uint32_t)'g'<<24 | 'l'<<16 | 'y'<<8 | 'f')), cairo_truetype_font_write_glyf_table, pos); |
1116 | |
1117 | pos = 0; |
1118 | if (font->is_pdf && font->scaled_font_subset->is_latin) |
1119 | cairo_truetype_font_add_truetype_table (font, TT_TAG_cmap((int)((uint32_t)'c'<<24 | 'm'<<16 | 'a'<<8 | 'p')), cairo_truetype_font_write_cmap_table, pos++); |
1120 | if (has_cvt) |
1121 | cairo_truetype_font_add_truetype_table (font, TT_TAG_cvt((int)((uint32_t)'c'<<24 | 'v'<<16 | 't'<<8 | ' ')), cairo_truetype_font_write_generic_table, pos++); |
1122 | if (has_fpgm) |
1123 | cairo_truetype_font_add_truetype_table (font, TT_TAG_fpgm((int)((uint32_t)'f'<<24 | 'p'<<16 | 'g'<<8 | 'm')), cairo_truetype_font_write_generic_table, pos++); |
1124 | pos++; |
1125 | cairo_truetype_font_add_truetype_table (font, TT_TAG_head((int)((uint32_t)'h'<<24 | 'e'<<16 | 'a'<<8 | 'd')), cairo_truetype_font_write_head_table, pos++); |
1126 | cairo_truetype_font_add_truetype_table (font, TT_TAG_hhea((int)((uint32_t)'h'<<24 | 'h'<<16 | 'e'<<8 | 'a')), cairo_truetype_font_write_hhea_table, pos++); |
1127 | cairo_truetype_font_add_truetype_table (font, TT_TAG_hmtx((int)((uint32_t)'h'<<24 | 'm'<<16 | 't'<<8 | 'x')), cairo_truetype_font_write_hmtx_table, pos++); |
1128 | cairo_truetype_font_add_truetype_table (font, TT_TAG_loca((int)((uint32_t)'l'<<24 | 'o'<<16 | 'c'<<8 | 'a')), cairo_truetype_font_write_loca_table, pos++); |
1129 | cairo_truetype_font_add_truetype_table (font, TT_TAG_maxp((int)((uint32_t)'m'<<24 | 'a'<<16 | 'x'<<8 | 'p')), cairo_truetype_font_write_maxp_table, pos++); |
1130 | if (has_prep) |
1131 | cairo_truetype_font_add_truetype_table (font, TT_TAG_prep((int)((uint32_t)'p'<<24 | 'r'<<16 | 'e'<<8 | 'p')), cairo_truetype_font_write_generic_table, pos); |
1132 | } |
1133 | |
1134 | static cairo_status_t |
1135 | cairo_truetype_subset_init_internal (cairo_truetype_subset_t *truetype_subset, |
1136 | cairo_scaled_font_subset_t *font_subset, |
1137 | cairo_bool_t is_pdf) |
1138 | { |
1139 | cairo_truetype_font_t *font = NULL((void*)0); |
1140 | cairo_status_t status; |
1141 | const char *data = NULL((void*)0); /* squelch bogus compiler warning */ |
1142 | unsigned long length = 0; /* squelch bogus compiler warning */ |
1143 | unsigned long offsets_length; |
1144 | unsigned int i; |
1145 | const unsigned long *string_offsets = NULL((void*)0); |
1146 | unsigned long num_strings = 0; |
1147 | |
1148 | status = _cairo_truetype_font_create (font_subset, is_pdf, &font); |
1149 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
1150 | return status; |
1151 | |
1152 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
1153 | unsigned short parent_glyph = font->scaled_font_subset->glyphs[i]; |
1154 | status = cairo_truetype_font_use_glyph (font, parent_glyph, &parent_glyph); |
1155 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
1156 | goto fail1; |
1157 | } |
1158 | |
1159 | cairo_truetype_font_create_truetype_table_list (font); |
1160 | status = cairo_truetype_font_generate (font, &data, &length, |
1161 | &string_offsets, &num_strings); |
1162 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
1163 | goto fail1; |
1164 | |
1165 | truetype_subset->ps_name = strdup (font->base.ps_name); |
1166 | if (unlikely (truetype_subset->ps_name == NULL)(__builtin_expect (!!(truetype_subset->ps_name == ((void*) 0)), 0))) { |
1167 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1168 | goto fail1; |
1169 | } |
1170 | |
1171 | if (font->base.font_name != NULL((void*)0)) { |
1172 | truetype_subset->family_name_utf8 = strdup (font->base.font_name); |
1173 | if (unlikely (truetype_subset->family_name_utf8 == NULL)(__builtin_expect (!!(truetype_subset->family_name_utf8 == ((void*)0)), 0))) { |
1174 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1175 | goto fail2; |
1176 | } |
1177 | } else { |
1178 | truetype_subset->family_name_utf8 = NULL((void*)0); |
1179 | } |
1180 | |
1181 | /* The widths array returned must contain only widths for the |
1182 | * glyphs in font_subset. Any subglyphs appended after |
1183 | * font_subset->num_glyphs are omitted. */ |
1184 | truetype_subset->widths = calloc (sizeof (double), |
1185 | font->scaled_font_subset->num_glyphs); |
1186 | if (unlikely (truetype_subset->widths == NULL)(__builtin_expect (!!(truetype_subset->widths == ((void*)0 )), 0))) { |
1187 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1188 | goto fail3; |
1189 | } |
1190 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) |
1191 | truetype_subset->widths[i] = (double)font->widths[i]/font->base.units_per_em; |
1192 | |
1193 | truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em; |
1194 | truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em; |
1195 | truetype_subset->x_max = (double)font->base.x_max/font->base.units_per_em; |
1196 | truetype_subset->y_max = (double)font->base.y_max/font->base.units_per_em; |
1197 | truetype_subset->ascent = (double)font->base.ascent/font->base.units_per_em; |
1198 | truetype_subset->descent = (double)font->base.descent/font->base.units_per_em; |
1199 | |
1200 | if (length) { |
1201 | truetype_subset->data = _cairo_malloc (length)((length) != 0 ? malloc(length) : ((void*)0)); |
1202 | if (unlikely (truetype_subset->data == NULL)(__builtin_expect (!!(truetype_subset->data == ((void*)0)) , 0))) { |
1203 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1204 | goto fail4; |
1205 | } |
1206 | |
1207 | memcpy (truetype_subset->data, data, length); |
1208 | } else |
1209 | truetype_subset->data = NULL((void*)0); |
1210 | truetype_subset->data_length = length; |
1211 | |
1212 | if (num_strings) { |
1213 | offsets_length = num_strings * sizeof (unsigned long); |
1214 | truetype_subset->string_offsets = _cairo_malloc (offsets_length)((offsets_length) != 0 ? malloc(offsets_length) : ((void*)0)); |
1215 | if (unlikely (truetype_subset->string_offsets == NULL)(__builtin_expect (!!(truetype_subset->string_offsets == ( (void*)0)), 0))) { |
1216 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1217 | goto fail5; |
1218 | } |
1219 | |
1220 | memcpy (truetype_subset->string_offsets, string_offsets, offsets_length); |
1221 | truetype_subset->num_string_offsets = num_strings; |
1222 | } else { |
1223 | truetype_subset->string_offsets = NULL((void*)0); |
1224 | truetype_subset->num_string_offsets = 0; |
1225 | } |
1226 | |
1227 | cairo_truetype_font_destroy (font); |
1228 | |
1229 | return CAIRO_STATUS_SUCCESS; |
1230 | |
1231 | fail5: |
1232 | free (truetype_subset->data); |
1233 | fail4: |
1234 | free (truetype_subset->widths); |
1235 | fail3: |
1236 | free (truetype_subset->family_name_utf8); |
1237 | fail2: |
1238 | free (truetype_subset->ps_name); |
1239 | fail1: |
1240 | cairo_truetype_font_destroy (font); |
1241 | |
1242 | return status; |
1243 | } |
1244 | |
1245 | cairo_status_t |
1246 | _cairo_truetype_subset_init_ps (cairo_truetype_subset_t *truetype_subset, |
1247 | cairo_scaled_font_subset_t *font_subset) |
1248 | { |
1249 | return cairo_truetype_subset_init_internal (truetype_subset, font_subset, FALSE0); |
1250 | } |
1251 | |
1252 | cairo_status_t |
1253 | _cairo_truetype_subset_init_pdf (cairo_truetype_subset_t *truetype_subset, |
1254 | cairo_scaled_font_subset_t *font_subset) |
1255 | { |
1256 | return cairo_truetype_subset_init_internal (truetype_subset, font_subset, TRUE1); |
1257 | } |
1258 | |
1259 | void |
1260 | _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset) |
1261 | { |
1262 | free (subset->ps_name); |
1263 | free (subset->family_name_utf8); |
1264 | free (subset->widths); |
1265 | free (subset->data); |
1266 | free (subset->string_offsets); |
1267 | } |
1268 | |
1269 | static cairo_int_status_t |
1270 | _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, |
1271 | unsigned long table_offset, |
1272 | unsigned long index, |
1273 | uint32_t *ucs4) |
1274 | { |
1275 | cairo_status_t status; |
1276 | const cairo_scaled_font_backend_t *backend; |
1277 | tt_segment_map_t *map; |
1278 | tt_segment_map_t map_header; |
1279 | unsigned int num_segments, i; |
1280 | unsigned long size; |
1281 | uint16_t *start_code; |
1282 | uint16_t *end_code; |
1283 | uint16_t *delta; |
1284 | uint16_t *range_offset; |
1285 | uint16_t c; |
1286 | |
1287 | backend = scaled_font->backend; |
1288 | size = 4; /* enough to read the two header fields we need */ |
1289 | status = backend->load_truetype_table (scaled_font, |
1290 | TT_TAG_cmap((int)((uint32_t)'c'<<24 | 'm'<<16 | 'a'<<8 | 'p')), table_offset, |
1291 | (unsigned char *) &map_header, |
1292 | &size); |
1293 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
1294 | return status; |
1295 | |
1296 | /* All table formats have the same first two words */ |
1297 | if (be16_to_cpu (map_header.format) != 4) |
1298 | return CAIRO_INT_STATUS_UNSUPPORTED; |
1299 | |
1300 | size = be16_to_cpu (map_header.length); |
1301 | /* minimum table size is 24 bytes */ |
1302 | if (size < 24) |
1303 | return CAIRO_INT_STATUS_UNSUPPORTED; |
1304 | |
1305 | map = _cairo_malloc (size)((size) != 0 ? malloc(size) : ((void*)0)); |
1306 | if (unlikely (map == NULL)(__builtin_expect (!!(map == ((void*)0)), 0))) |
1307 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1308 | |
1309 | status = backend->load_truetype_table (scaled_font, |
1310 | TT_TAG_cmap((int)((uint32_t)'c'<<24 | 'm'<<16 | 'a'<<8 | 'p')), table_offset, |
1311 | (unsigned char *) map, |
1312 | &size); |
1313 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
1314 | goto fail; |
1315 | |
1316 | num_segments = be16_to_cpu (map->segCountX2)/2; |
1317 | |
1318 | /* A Format 4 cmap contains 8 uint16_t numbers and 4 arrays of |
1319 | * uint16_t each num_segments long. */ |
1320 | if (size < (8 + 4*num_segments)*sizeof(uint16_t)) { |
1321 | status = CAIRO_INT_STATUS_UNSUPPORTED; |
1322 | goto fail; |
1323 | } |
1324 | |
1325 | end_code = map->endCount; |
1326 | start_code = &(end_code[num_segments + 1]); |
1327 | delta = &(start_code[num_segments]); |
1328 | range_offset = &(delta[num_segments]); |
1329 | |
1330 | /* search for glyph in segments with rangeOffset=0 */ |
1331 | for (i = 0; i < num_segments; i++) { |
1332 | uint16_t start = be16_to_cpu (start_code[i]); |
1333 | uint16_t end = be16_to_cpu (end_code[i]); |
1334 | |
1335 | if (start == 0xffff && end == 0xffff) |
1336 | break; |
1337 | |
1338 | c = index - be16_to_cpu (delta[i]); |
1339 | if (range_offset[i] == 0 && c >= start && c <= end) { |
1340 | *ucs4 = c; |
1341 | goto found; |
1342 | } |
1343 | } |
1344 | |
1345 | /* search for glyph in segments with rangeOffset=1 */ |
1346 | for (i = 0; i < num_segments; i++) { |
1347 | uint16_t start = be16_to_cpu (start_code[i]); |
1348 | uint16_t end = be16_to_cpu (end_code[i]); |
1349 | |
1350 | if (start == 0xffff && end == 0xffff) |
1351 | break; |
1352 | |
1353 | if (range_offset[i] != 0) { |
1354 | uint16_t *glyph_ids = &range_offset[i] + be16_to_cpu (range_offset[i])/2; |
1355 | int range_size = end - start + 1; |
1356 | uint16_t g_id_be = cpu_to_be16 (index); |
1357 | int j; |
1358 | |
1359 | if (range_size > 0) { |
1360 | if ((char*)glyph_ids + 2*range_size > (char*)map + size) { |
1361 | status = CAIRO_INT_STATUS_UNSUPPORTED; |
1362 | goto fail; |
1363 | } |
1364 | |
1365 | for (j = 0; j < range_size; j++) { |
1366 | if (glyph_ids[j] == g_id_be) { |
1367 | *ucs4 = start + j; |
1368 | goto found; |
1369 | } |
1370 | } |
1371 | } |
1372 | } |
1373 | } |
1374 | |
1375 | /* glyph not found */ |
1376 | *ucs4 = -1; |
1377 | |
1378 | found: |
1379 | status = CAIRO_STATUS_SUCCESS; |
1380 | |
1381 | fail: |
1382 | free (map); |
1383 | |
1384 | return status; |
1385 | } |
1386 | |
1387 | cairo_int_status_t |
1388 | _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font, |
1389 | unsigned long index, |
1390 | uint32_t *ucs4) |
1391 | { |
1392 | cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; |
1393 | const cairo_scaled_font_backend_t *backend; |
1394 | tt_cmap_t *cmap; |
1395 | tt_cmap_t cmap_header; |
1396 | int num_tables, i; |
1397 | unsigned long size; |
1398 | |
1399 | backend = scaled_font->backend; |
1400 | if (!backend->load_truetype_table) |
1401 | return CAIRO_INT_STATUS_UNSUPPORTED; |
1402 | |
1403 | size = 4; /* only read the header fields 'version' and 'num_tables' */ |
1404 | status = backend->load_truetype_table (scaled_font, |
1405 | TT_TAG_cmap((int)((uint32_t)'c'<<24 | 'm'<<16 | 'a'<<8 | 'p')), 0, |
1406 | (unsigned char *) &cmap_header, |
1407 | &size); |
1408 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
1409 | return status; |
1410 | |
1411 | num_tables = be16_to_cpu (cmap_header.num_tables); |
1412 | size = 4 + num_tables * sizeof (tt_cmap_index_t); |
1413 | cmap = _cairo_malloc_ab_plus_c (num_tables, sizeof (tt_cmap_index_t), 4); |
1414 | if (unlikely (cmap == NULL)(__builtin_expect (!!(cmap == ((void*)0)), 0))) |
1415 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1416 | |
1417 | status = backend->load_truetype_table (scaled_font, |
1418 | TT_TAG_cmap((int)((uint32_t)'c'<<24 | 'm'<<16 | 'a'<<8 | 'p')), 0, |
1419 | (unsigned char *) cmap, |
1420 | &size); |
1421 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
1422 | goto cleanup; |
1423 | |
1424 | /* Find a table with Unicode mapping */ |
1425 | for (i = 0; i < num_tables; i++) { |
1426 | if (be16_to_cpu (cmap->index[i].platform) == 3 && |
1427 | be16_to_cpu (cmap->index[i].encoding) == 1) { |
1428 | status = _cairo_truetype_reverse_cmap (scaled_font, |
1429 | be32_to_cpu (cmap->index[i].offset), |
1430 | index, |
1431 | ucs4); |
1432 | if (status != CAIRO_INT_STATUS_UNSUPPORTED) |
1433 | break; |
1434 | } |
1435 | } |
1436 | |
1437 | cleanup: |
1438 | free (cmap); |
1439 | |
1440 | return status; |
1441 | } |
1442 | |
1443 | /* |
1444 | * Sanity check on font name length as some broken fonts may return very long |
1445 | * strings of garbage. 127 is maximum length of a PS name. |
1446 | */ |
1447 | #define MAX_FONT_NAME_LENGTH127 127 |
1448 | |
1449 | static cairo_status_t |
1450 | find_name (tt_name_t *name, unsigned long size, int name_id, int platform, int encoding, int language, char **str_out) |
1451 | { |
1452 | tt_name_record_t *record; |
1453 | unsigned int i, len; |
1454 | char *str; |
1455 | char *p; |
1456 | cairo_bool_t has_tag; |
1457 | cairo_status_t status; |
1458 | |
1459 | str = NULL((void*)0); |
1460 | for (i = 0; i < MIN(be16_to_cpu (name->num_records), size / sizeof(name->records[0]))((be16_to_cpu (name->num_records)) < (size / sizeof(name ->records[0])) ? (be16_to_cpu (name->num_records)) : (size / sizeof(name->records[0]))); i++) { |
1461 | record = &(name->records[i]); |
1462 | if (be16_to_cpu (record->name) == name_id && |
1463 | be16_to_cpu (record->platform) == platform && |
1464 | be16_to_cpu (record->encoding) == encoding && |
1465 | (language == -1 || be16_to_cpu (record->language) == language)) { |
1466 | |
1467 | len = be16_to_cpu (record->length); |
1468 | if (platform == 3 && len > MAX_FONT_NAME_LENGTH127*2) /* UTF-16 name */ |
1469 | break; |
1470 | |
1471 | if (len > MAX_FONT_NAME_LENGTH127) |
1472 | break; |
1473 | |
1474 | uint16_t offset = be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset); |
1475 | if (offset + len > size) |
1476 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1477 | |
1478 | str = _cairo_malloc (len + 1)((len + 1) != 0 ? malloc(len + 1) : ((void*)0)); |
1479 | if (str == NULL((void*)0)) |
1480 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1481 | |
1482 | memcpy (str, |
1483 | ((char*)name) + offset, |
1484 | len); |
1485 | str[len] = 0; |
1486 | break; |
1487 | } |
1488 | } |
1489 | if (str == NULL((void*)0)) { |
1490 | *str_out = NULL((void*)0); |
1491 | return CAIRO_STATUS_SUCCESS; |
1492 | } |
1493 | |
1494 | if (platform == 3) { /* Win platform, unicode encoding */ |
1495 | /* convert to utf8 */ |
1496 | int size = 0; |
1497 | char *utf8; |
1498 | uint16_t *u = (uint16_t *) str; |
1499 | unsigned int u_len = len/2; |
1500 | |
1501 | for (i = 0; i < u_len; i++) |
1502 | size += _cairo_ucs4_to_utf8 (be16_to_cpu(u[i]), NULL((void*)0)); |
1503 | |
1504 | utf8 = _cairo_malloc (size + 1)((size + 1) != 0 ? malloc(size + 1) : ((void*)0)); |
1505 | if (utf8 == NULL((void*)0)) { |
1506 | status =_cairo_error (CAIRO_STATUS_NO_MEMORY); |
1507 | goto fail; |
1508 | } |
1509 | p = utf8; |
1510 | for (i = 0; i < u_len; i++) |
1511 | p += _cairo_ucs4_to_utf8 (be16_to_cpu(u[i]), p); |
1512 | *p = 0; |
1513 | free (str); |
1514 | str = utf8; |
1515 | } else if (platform == 1) { /* Mac platform, Mac Roman encoding */ |
1516 | /* Replace characters above 127 with underscores. We could use |
1517 | * a lookup table to convert to unicode but since most fonts |
1518 | * include a unicode name this is just a rarely used fallback. */ |
1519 | for (i = 0; i < len; i++) { |
1520 | if ((unsigned char)str[i] > 127) |
1521 | str[i] = '_'; |
1522 | } |
1523 | } |
1524 | |
1525 | /* If font name is prefixed with a PDF subset tag, strip it off. */ |
1526 | p = str; |
1527 | len = strlen (str); |
1528 | has_tag = FALSE0; |
1529 | if (len > 7 && p[6] == '+') { |
1530 | has_tag = TRUE1; |
1531 | for (i = 0; i < 6; i++) { |
1532 | if (p[i] < 'A' || p[i] > 'Z') { |
1533 | has_tag = FALSE0; |
1534 | break; |
1535 | } |
1536 | } |
1537 | } |
1538 | if (has_tag) { |
1539 | p = _cairo_strndupstrndup (str + 7, len - 7); |
1540 | free (str); |
1541 | str = p; |
1542 | } |
1543 | |
1544 | *str_out = str; |
1545 | |
1546 | return CAIRO_STATUS_SUCCESS; |
1547 | |
1548 | fail: |
1549 | free (str); |
1550 | |
1551 | return status; |
1552 | } |
1553 | |
1554 | cairo_int_status_t |
1555 | _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font, |
1556 | char **ps_name_out, |
1557 | char **font_name_out) |
1558 | { |
1559 | cairo_status_t status; |
1560 | const cairo_scaled_font_backend_t *backend; |
1561 | tt_name_t *name; |
1562 | unsigned long size; |
1563 | char *ps_name = NULL((void*)0); |
1564 | char *family_name = NULL((void*)0); |
1565 | |
1566 | backend = scaled_font->backend; |
1567 | if (!backend->load_truetype_table) |
1568 | return CAIRO_INT_STATUS_UNSUPPORTED; |
1569 | |
1570 | size = 0; |
1571 | status = backend->load_truetype_table (scaled_font, |
1572 | TT_TAG_name((int)((uint32_t)'n'<<24 | 'a'<<16 | 'm'<<8 | 'e')), 0, |
1573 | NULL((void*)0), |
1574 | &size); |
1575 | if (status) |
1576 | return status; |
1577 | |
1578 | name = _cairo_malloc (size)((size) != 0 ? malloc(size) : ((void*)0)); |
1579 | if (name == NULL((void*)0)) |
1580 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1581 | |
1582 | status = backend->load_truetype_table (scaled_font, |
1583 | TT_TAG_name((int)((uint32_t)'n'<<24 | 'a'<<16 | 'm'<<8 | 'e')), 0, |
1584 | (unsigned char *) name, |
1585 | &size); |
1586 | if (status) |
1587 | goto fail; |
1588 | |
1589 | /* Find PS Name (name_id = 6). OT spec says PS name must be one of |
1590 | * the following two encodings */ |
1591 | status = find_name (name, size, 6, 3, 1, 0x409, &ps_name); /* win, unicode, english-us */ |
1592 | if (unlikely(status)(__builtin_expect (!!(status), 0))) |
1593 | goto fail; |
1594 | |
1595 | if (!ps_name) { |
1596 | status = find_name (name, size, 6, 1, 0, 0, &ps_name); /* mac, roman, english */ |
1597 | if (unlikely(status)(__builtin_expect (!!(status), 0))) |
1598 | goto fail; |
1599 | } |
1600 | |
1601 | /* Find Family name (name_id = 1) */ |
1602 | status = find_name (name, size, 1, 3, 1, 0x409, &family_name); /* win, unicode, english-us */ |
1603 | if (unlikely(status)(__builtin_expect (!!(status), 0))) |
1604 | goto fail; |
1605 | |
1606 | if (!family_name) { |
1607 | status = find_name (name, size, 1, 3, 0, 0x409, &family_name); /* win, symbol, english-us */ |
1608 | if (unlikely(status)(__builtin_expect (!!(status), 0))) |
1609 | goto fail; |
1610 | } |
1611 | |
1612 | if (!family_name) { |
1613 | status = find_name (name, size, 1, 1, 0, 0, &family_name); /* mac, roman, english */ |
1614 | if (unlikely(status)(__builtin_expect (!!(status), 0))) |
1615 | goto fail; |
1616 | } |
1617 | |
1618 | if (!family_name) { |
1619 | status = find_name (name, size, 1, 3, 1, -1, &family_name); /* win, unicode, any language */ |
1620 | if (unlikely(status)(__builtin_expect (!!(status), 0))) |
1621 | goto fail; |
1622 | } |
1623 | |
1624 | status = _cairo_escape_ps_name (&ps_name); |
1625 | if (unlikely(status)(__builtin_expect (!!(status), 0))) |
1626 | goto fail; |
1627 | |
1628 | free (name); |
1629 | |
1630 | *ps_name_out = ps_name; |
1631 | *font_name_out = family_name; |
1632 | |
1633 | return CAIRO_STATUS_SUCCESS; |
1634 | |
1635 | fail: |
1636 | free (name); |
1637 | free (ps_name); |
1638 | free (family_name); |
1639 | *ps_name_out = NULL((void*)0); |
1640 | *font_name_out = NULL((void*)0); |
1641 | |
1642 | return status; |
1643 | } |
1644 | |
1645 | cairo_int_status_t |
1646 | _cairo_truetype_get_style (cairo_scaled_font_t *scaled_font, |
1647 | int *weight, |
1648 | cairo_bool_t *bold, |
1649 | cairo_bool_t *italic) |
1650 | { |
1651 | cairo_status_t status; |
1652 | const cairo_scaled_font_backend_t *backend; |
1653 | tt_os2_t os2; |
1654 | unsigned long size; |
1655 | uint16_t selection; |
1656 | |
1657 | backend = scaled_font->backend; |
1658 | if (!backend->load_truetype_table) |
1659 | return CAIRO_INT_STATUS_UNSUPPORTED; |
1660 | |
1661 | size = 0; |
1662 | status = backend->load_truetype_table (scaled_font, |
1663 | TT_TAG_OS2((int)((uint32_t)'O'<<24 | 'S'<<16 | '/'<<8 | '2')), 0, |
1664 | NULL((void*)0), |
1665 | &size); |
1666 | if (status) |
1667 | return status; |
1668 | |
1669 | if (size < sizeof(os2)) |
1670 | return CAIRO_INT_STATUS_UNSUPPORTED; |
1671 | |
1672 | size = sizeof (os2); |
1673 | status = backend->load_truetype_table (scaled_font, |
1674 | TT_TAG_OS2((int)((uint32_t)'O'<<24 | 'S'<<16 | '/'<<8 | '2')), 0, |
1675 | (unsigned char *) &os2, |
1676 | &size); |
1677 | if (status) |
1678 | return status; |
1679 | |
1680 | *weight = be16_to_cpu (os2.usWeightClass); |
1681 | selection = be16_to_cpu (os2.fsSelection); |
1682 | *bold = (selection & TT_FS_SELECTION_BOLD32) ? TRUE1 : FALSE0; |
1683 | *italic = (selection & TT_FS_SELECTION_ITALIC1) ? TRUE1 : FALSE0; |
1684 | |
1685 | return CAIRO_STATUS_SUCCESS; |
1686 | } |
1687 | |
1688 | #endif /* CAIRO_HAS_FONT_SUBSET */ |