File: | root/firefox-clang/gfx/cairo/cairo/src/cairo-truetype-subset.c |
Warning: | line 1529, column 25 The left operand of '==' is a garbage value due to array index out of bounds |
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); | |||
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
| |||
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
| |||
1490 | *str_out = NULL((void*)0); | |||
1491 | return CAIRO_STATUS_SUCCESS; | |||
1492 | } | |||
1493 | ||||
1494 | if (platform
| |||
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 */ |