Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cairo-truetype-subset.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D HAVE_FT_LOAD_SFNT_TABLE -D PACKAGE_VERSION="moz" -D PACKAGE_BUGREPORT="http://bugzilla.mozilla.org/" -D CAIRO_HAS_PTHREAD -D _GNU_SOURCE -D MOZ_TREE_PIXMAN -D SIZEOF_VOID_P=__SIZEOF_POINTER__ -D SIZEOF_INT=__SIZEOF_INT__ -D SIZEOF_LONG=__SIZEOF_LONG__ -D SIZEOF_LONG_LONG=__SIZEOF_LONG_LONG__ -D HAVE_UINT64_T -D HAVE_CXX11_ATOMIC_PRIMITIVES -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/freetype2 -I /usr/include/libpng16 -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-enum-compare -Wno-int-to-pointer-cast -Wno-int-conversion -Wno-incompatible-pointer-types -Wno-sign-compare -Wno-type-limits -Wno-missing-field-initializers -Wno-conversion -Wno-narrowing -Wno-switch -Wno-unused -Wno-unused-variable -Wno-error=uninitialized -Wno-absolute-value -Wno-deprecated-register -Wno-incompatible-pointer-types -Wno-macro-redefined -Wno-shift-negative-value -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-unreachable-code -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-26-231904-1820671-1 -x c /root/firefox-clang/gfx/cairo/cairo/src/cairo-truetype-subset.c
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
56typedef struct subset_glyph subset_glyph_t;
57struct subset_glyph {
58 int parent_index;
59 unsigned long location;
60};
61
62typedef struct _cairo_truetype_font cairo_truetype_font_t;
63
64typedef struct table table_t;
65struct 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
71struct _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]
106check (tt_head_t, 54);
107check (tt_hhea_t, 36);
108check (tt_maxp_t, 32);
109check (tt_name_record_t, 12);
110check (tt_name_t, 18);
111check (tt_composite_glyph_t, 16);
112check (tt_glyph_data_t, 26);
113#undef check
114
115static cairo_status_t
116cairo_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
123static 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
136static 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)
3
Assuming field 'load_truetype_table' is non-null
4
Taking false branch
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) {
5
Assuming field 'is_synthetic' is null
6
Taking false branch
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)))
7
Assuming 'status' is 0
8
Taking false branch
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)))
9
Assuming 'status' is 0
10
Taking false branch
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)))
11
Assuming 'status' is 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))
;
12
'?' condition is true
198 if (unlikely (font == NULL)(__builtin_expect (!!(font == ((void*)0)), 0)))
13
Assuming 'font' is not equal to null
14
Taking false branch
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)))
15
Assuming 'status' is 0
16
Taking false branch
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))) {
17
Assuming field 'glyphs' is not equal to null
18
Taking false branch
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))
) {
19
Assuming field 'parent_to_subset' is not equal to null
20
Taking false branch
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)
21
Assuming field 'units_per_em' is not equal to 0
22
Taking false branch
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,
23
Calling '_cairo_truetype_read_font_name'
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
296static void
297cairo_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
309static cairo_status_t
310cairo_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
326static void
327cairo_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
341static void
342cairo_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
354static void
355cairo_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
367static cairo_status_t
368cairo_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
392static cairo_status_t
393cairo_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
415typedef struct _cmap_unicode_range {
416 unsigned int start;
417 unsigned int end;
418} cmap_unicode_range_t;
419
420static 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
437static cairo_status_t
438cairo_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
513static cairo_status_t
514cairo_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
542static cairo_status_t
543cairo_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
595static cairo_status_t
596cairo_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;
707FAIL:
708 free (u.bytes);
709
710 return _cairo_truetype_font_set_error (font, status);
711}
712
713static cairo_status_t
714cairo_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
746static cairo_status_t
747cairo_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
771static cairo_status_t
772cairo_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
836static cairo_status_t
837cairo_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
867static cairo_status_t
868cairo_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
893static cairo_status_t
894cairo_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
931static uint32_t
932cairo_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
951static void
952cairo_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
967static cairo_status_t
968cairo_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
1027static cairo_status_t
1028cairo_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
1045static void
1046cairo_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 */
1080static void
1081cairo_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
1134static cairo_status_t
1135cairo_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);
2
Calling '_cairo_truetype_font_create'
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
1245cairo_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
1252cairo_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);
1
Calling 'cairo_truetype_subset_init_internal'
1257}
1258
1259void
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
1269static 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
1378found:
1379 status = CAIRO_STATUS_SUCCESS;
1380
1381fail:
1382 free (map);
1383
1384 return status;
1385}
1386
1387cairo_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
1437cleanup:
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
1449static cairo_status_t
1450find_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++) {
35
Assuming the condition is false
36
'?' condition is false
37
Assuming the condition is true
38
Loop condition is true. Entering loop body
1461 record = &(name->records[i]);
1462 if (be16_to_cpu (record->name) == name_id &&
39
Assuming the condition is true
43
Taking true branch
1463 be16_to_cpu (record->platform) == platform &&
40
Assuming the condition is true
1464 be16_to_cpu (record->encoding) == encoding &&
41
Assuming the condition is true
1465 (language == -1 || be16_to_cpu (record->language) == language)) {
42
Assuming the condition is true
1466
1467 len = be16_to_cpu (record->length);
1468 if (platform
43.1
'platform' is equal to 3
== 3 && len > MAX_FONT_NAME_LENGTH127*2) /* UTF-16 name */
44
Assuming the condition is false
45
Taking false branch
1469 break;
1470
1471 if (len > MAX_FONT_NAME_LENGTH127)
46
Assuming 'len' is <= MAX_FONT_NAME_LENGTH
47
Taking false branch
1472 break;
1473
1474 uint16_t offset = be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset);
1475 if (offset + len > size)
48
Assuming the condition is false
1476 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1477
1478 str = _cairo_malloc (len + 1)((len + 1) != 0 ? malloc(len + 1) : ((void*)0));
49
Taking false branch
50
'?' condition is true
1479 if (str == NULL((void*)0))
51
Assuming 'str' is not equal to NULL
52
Taking false branch
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
53.1
'str' is not equal to NULL
== NULL((void*)0)) {
53
Execution continues on line 1489
54
Taking false branch
1490 *str_out = NULL((void*)0);
1491 return CAIRO_STATUS_SUCCESS;
1492 }
1493
1494 if (platform
54.1
'platform' is equal to 3
== 3) { /* Win platform, unicode encoding */
55
Taking true branch
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++)
56
Assuming 'i' is >= 'u_len'
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));
57
Loop condition is false. Execution continues on line 1504
58
'?' condition is true
59
Storing uninitialized value
1505 if (utf8 == NULL((void*)0)) {
60
Assuming 'utf8' is not equal to NULL
61
Taking false branch
1506 status =_cairo_error (CAIRO_STATUS_NO_MEMORY);
1507 goto fail;
1508 }
1509 p = utf8;
1510 for (i = 0; i < u_len; i++)
62
Loop condition is false. Execution continues on line 1512
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] == '+') {
63
Assuming 'len' is > 7
64
The left operand of '==' is a garbage value due to array index out of bounds
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
1554cairo_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)
24
Assuming field 'load_truetype_table' is non-null
25
Taking false branch
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)
26
Assuming 'status' is 0
1576 return status;
1577
1578 name = _cairo_malloc (size)((size) != 0 ? malloc(size) : ((void*)0));
27
Taking false branch
28
Assuming 'size' is not equal to 0
29
'?' condition is true
1579 if (name == NULL((void*)0))
30
Assuming 'name' is not equal to NULL
31
Taking false branch
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)
32
Assuming 'status' is 0
33
Taking false branch
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 */
34
Calling 'find_name'
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
1635fail:
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
1645cairo_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 */