Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c
Warning:line 3367, column 2
Value stored to 'status' is never read

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-cff-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-cff-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 © 2006 Adrian Johnson
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 Adrian Johnson.
32 *
33 * Contributor(s):
34 * Adrian Johnson <ajohnson@redneon.com>
35 * Eugeniy Meshcheryakov <eugen@debian.org>
36 */
37
38/*
39 * Useful links:
40 * http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5176.CFF.pdf
41 * http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5177.Type2.pdf
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#include <string.h>
55#include <locale.h>
56
57/* CFF Dict Operators. If the high byte is 0 the command is encoded
58 * with a single byte. */
59#define BASEFONTNAME_OP0x0c16 0x0c16
60#define CIDCOUNT_OP0x0c22 0x0c22
61#define CHARSET_OP0x000f 0x000f
62#define CHARSTRINGS_OP0x0011 0x0011
63#define COPYRIGHT_OP0x0c00 0x0c00
64#define DEFAULTWIDTH_OP0x0014 0x0014
65#define ENCODING_OP0x0010 0x0010
66#define FAMILYNAME_OP0x0003 0x0003
67#define FDARRAY_OP0x0c24 0x0c24
68#define FDSELECT_OP0x0c25 0x0c25
69#define FONTBBOX_OP0x0005 0x0005
70#define FONTMATRIX_OP0x0c07 0x0c07
71#define FONTNAME_OP0x0c26 0x0c26
72#define FULLNAME_OP0x0002 0x0002
73#define LOCAL_SUB_OP0x0013 0x0013
74#define NOMINALWIDTH_OP0x0015 0x0015
75#define NOTICE_OP0x0001 0x0001
76#define POSTSCRIPT_OP0x0c15 0x0c15
77#define PRIVATE_OP0x0012 0x0012
78#define ROS_OP0x0c1e 0x0c1e
79#define UNIQUEID_OP0x000d 0x000d
80#define VERSION_OP0x0000 0x0000
81#define WEIGHT_OP0x0004 0x0004
82#define XUID_OP0x000e 0x000e
83#define BLUEVALUES_OP0x0006 0x0006
84#define OTHERBLUES_OP0x0007 0x0007
85#define FAMILYBLUES_OP0x0008 0x0008
86#define FAMILYOTHERBLUES_OP0x0009 0x0009
87#define STEMSNAPH_OP0x0c0c 0x0c0c
88#define STEMSNAPV_OP0x0c0d 0x0c0d
89
90#define NUM_STD_STRINGS391 391
91
92/* Type 2 Charstring operators */
93#define TYPE2_hstem0x0001 0x0001
94#define TYPE2_vstem0x0003 0x0003
95#define TYPE2_callsubr0x000a 0x000a
96
97#define TYPE2_return0x000b 0x000b
98#define TYPE2_endchar0x000e 0x000e
99
100#define TYPE2_hstemhm0x0012 0x0012
101#define TYPE2_hintmask0x0013 0x0013
102#define TYPE2_cntrmask0x0014 0x0014
103#define TYPE2_vstemhm0x0017 0x0017
104#define TYPE2_callgsubr0x001d 0x001d
105
106#define TYPE2_rmoveto0x0015 0x0015
107#define TYPE2_hmoveto0x0016 0x0016
108#define TYPE2_vmoveto0x0004 0x0004
109
110
111#define MAX_SUBROUTINE_NESTING10 10 /* From Type2 Charstring spec */
112
113
114typedef struct _cff_header {
115 uint8_t major;
116 uint8_t minor;
117 uint8_t header_size;
118 uint8_t offset_size;
119} cff_header_t;
120
121typedef struct _cff_index_element {
122 cairo_bool_t is_copy;
123 unsigned char *data;
124 int length;
125} cff_index_element_t;
126
127typedef struct _cff_dict_operator {
128 cairo_hash_entry_t base;
129
130 unsigned short operator;
131 unsigned char *operand;
132 int operand_length;
133 int operand_offset;
134} cff_dict_operator_t;
135
136typedef struct _cairo_cff_font {
137
138 cairo_scaled_font_subset_t *scaled_font_subset;
139 const cairo_scaled_font_backend_t *backend;
140
141 /* Font Data */
142 unsigned char *data;
143 unsigned long data_length;
144 unsigned char *current_ptr;
145 unsigned char *data_end;
146 cff_header_t *header;
147 char *font_name;
148 char *ps_name;
149 cairo_hash_table_t *top_dict;
150 cairo_hash_table_t *private_dict;
151 cairo_array_t strings_index;
152 cairo_array_t charstrings_index;
153 cairo_array_t global_sub_index;
154 cairo_array_t local_sub_index;
155 unsigned char *charset;
156 int num_glyphs;
157 cairo_bool_t is_cid;
158 cairo_bool_t is_opentype;
159 int units_per_em;
160 int global_sub_bias;
161 int local_sub_bias;
162 double default_width;
163 double nominal_width;
164
165 /* CID Font Data */
166 int *fdselect;
167 unsigned int num_fontdicts;
168 cairo_hash_table_t **fd_dict;
169 cairo_hash_table_t **fd_private_dict;
170 cairo_array_t *fd_local_sub_index;
171 int *fd_local_sub_bias;
172 double *fd_default_width;
173 double *fd_nominal_width;
174
175 /* Subsetted Font Data */
176 char *subset_font_name;
177 cairo_array_t charstrings_subset_index;
178 cairo_array_t strings_subset_index;
179 int euro_sid;
180 int *fdselect_subset;
181 unsigned int num_subset_fontdicts;
182 int *fd_subset_map;
183 int *private_dict_offset;
184 cairo_bool_t subset_subroutines;
185 cairo_bool_t *global_subs_used;
186 cairo_bool_t *local_subs_used;
187 cairo_bool_t **fd_local_subs_used;
188 cairo_array_t output;
189
190 /* Subset Metrics */
191 int *widths;
192 int x_min, y_min, x_max, y_max;
193 int ascent, descent;
194
195 /* Type 2 charstring data */
196 int type2_stack_size;
197 int type2_stack_top_value;
198 cairo_bool_t type2_stack_top_is_int;
199 int type2_num_hints;
200 int type2_hintmask_bytes;
201 int type2_nesting_level;
202 cairo_bool_t type2_seen_first_int;
203 cairo_bool_t type2_find_width;
204 cairo_bool_t type2_found_width;
205 int type2_width;
206 cairo_bool_t type2_has_path;
207
208} cairo_cff_font_t;
209
210/* Encoded integer using maximum sized encoding. This is required for
211 * operands that are later modified after encoding. */
212static unsigned char *
213encode_integer_max (unsigned char *p, int i)
214{
215 *p++ = 29;
216 *p++ = i >> 24;
217 *p++ = (i >> 16) & 0xff;
218 *p++ = (i >> 8) & 0xff;
219 *p++ = i & 0xff;
220 return p;
221}
222
223static unsigned char *
224encode_integer (unsigned char *p, int i)
225{
226 if (i >= -107 && i <= 107) {
227 *p++ = i + 139;
228 } else if (i >= 108 && i <= 1131) {
229 i -= 108;
230 *p++ = (i >> 8)+ 247;
231 *p++ = i & 0xff;
232 } else if (i >= -1131 && i <= -108) {
233 i = -i - 108;
234 *p++ = (i >> 8)+ 251;
235 *p++ = i & 0xff;
236 } else if (i >= -32768 && i <= 32767) {
237 *p++ = 28;
238 *p++ = (i >> 8) & 0xff;
239 *p++ = i & 0xff;
240 } else {
241 p = encode_integer_max (p, i);
242 }
243 return p;
244}
245
246static unsigned char *
247decode_integer (unsigned char *p, int *integer)
248{
249 if (*p == 28) {
250 *integer = (int16_t)(p[1]<<8 | p[2]);
251 p += 3;
252 } else if (*p == 29) {
253 *integer = (int32_t)(((uint32_t)p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]);
254 p += 5;
255 } else if (*p >= 32 && *p <= 246) {
256 *integer = *p++ - 139;
257 } else if (*p <= 250) {
258 *integer = (p[0] - 247) * 256 + p[1] + 108;
259 p += 2;
260 } else if (*p <= 254) {
261 *integer = -(p[0] - 251) * 256 - p[1] - 108;
262 p += 2;
263 } else {
264 *integer = 0;
265 p += 1;
266 }
267 return p;
268}
269
270static char *
271decode_nibble (int n, char *buf)
272{
273 switch (n)
274 {
275 case 0xa:
276 *buf++ = '.';
277 break;
278 case 0xb:
279 *buf++ = 'E';
280 break;
281 case 0xc:
282 *buf++ = 'E';
283 *buf++ = '-';
284 break;
285 case 0xd:
286 *buf++ = '-';
287 break;
288 case 0xe:
289 *buf++ = '-';
290 break;
291 case 0xf:
292 break;
293 default:
294 *buf++ = '0' + n;
295 break;
296 }
297
298 return buf;
299}
300
301static unsigned char *
302decode_real (unsigned char *p, double *real)
303{
304 char buffer[100];
305 char *buf = buffer;
306 char *buf_end = buffer + sizeof (buffer);
307 char *end;
308 int n;
309
310 p++;
311 while (buf + 2 < buf_end) {
312 n = *p >> 4;
313 buf = decode_nibble (n, buf);
314 n = *p & 0x0f;
315 buf = decode_nibble (n, buf);
316 if ((*p & 0x0f) == 0x0f) {
317 p++;
318 break;
319 }
320 p++;
321 };
322 *buf = 0;
323
324 *real = _cairo_strtod (buffer, &end);
325
326 return p;
327}
328
329static unsigned char *
330decode_number (unsigned char *p, double *number)
331{
332 if (*p == 30) {
333 p = decode_real (p, number);
334 } else {
335 int i;
336 p = decode_integer (p, &i);
337 *number = i;
338 }
339 return p;
340}
341
342static unsigned char *
343decode_operator (unsigned char *p, unsigned short *operator)
344{
345 unsigned short op = 0;
346
347 op = *p++;
348 if (op == 12) {
349 op <<= 8;
350 op |= *p++;
351 }
352 *operator = op;
353 return p;
354}
355
356/* return 0 if not an operand */
357static int
358operand_length (unsigned char *p)
359{
360 unsigned char *begin = p;
361
362 if (*p == 28)
363 return 3;
364
365 if (*p == 29)
366 return 5;
367
368 if (*p >= 32 && *p <= 246)
369 return 1;
370
371 if (*p >= 247 && *p <= 254)
372 return 2;
373
374 if (*p == 30) {
375 while ((*p & 0x0f) != 0x0f)
376 p++;
377 return p - begin + 1;
378 }
379
380 return 0;
381}
382
383static unsigned char *
384encode_index_offset (unsigned char *p, int offset_size, unsigned long offset)
385{
386 while (--offset_size >= 0) {
387 p[offset_size] = (unsigned char) (offset & 0xff);
388 offset >>= 8;
389 }
390 return p + offset_size;
391}
392
393static size_t
394decode_index_offset(unsigned char *p, int off_size)
395{
396 unsigned long offset = 0;
397
398 while (off_size-- > 0)
399 offset = offset*256 + *p++;
400 return offset;
401}
402
403static void
404cff_index_init (cairo_array_t *index)
405{
406 _cairo_array_init (index, sizeof (cff_index_element_t));
407}
408
409static cairo_int_status_t
410cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_ptr)
411{
412 cff_index_element_t element;
413 unsigned char *data, *p;
414 cairo_status_t status;
415 int offset_size, count, i;
416 size_t start, end = 0;
417
418 p = *ptr;
419 if (p + 2 > end_ptr)
420 return CAIRO_INT_STATUS_UNSUPPORTED;
421 count = get_unaligned_be16 (p);
422 p += 2;
423 if (count > 0) {
424 offset_size = *p++;
425 if (p + (count + 1)*offset_size > end_ptr || offset_size > 4)
426 return CAIRO_INT_STATUS_UNSUPPORTED;
427 data = p + offset_size*(count + 1) - 1;
428 start = decode_index_offset (p, offset_size);
429 p += offset_size;
430 for (i = 0; i < count; i++) {
431 end = decode_index_offset (p, offset_size);
432 p += offset_size;
433 if (p > end_ptr || end < start || data + end > end_ptr)
434 return CAIRO_INT_STATUS_UNSUPPORTED;
435 element.length = end - start;
436 element.is_copy = FALSE0;
437 element.data = data + start;
438 status = _cairo_array_append (index, &element);
439 if (unlikely (status)(__builtin_expect (!!(status), 0)))
440 return status;
441 start = end;
442 }
443 p = data + end;
444 }
445 *ptr = p;
446
447 return CAIRO_STATUS_SUCCESS;
448}
449
450static cairo_status_t
451cff_index_write (cairo_array_t *index, cairo_array_t *output)
452{
453 int offset_size;
454 int offset;
455 int num_elem;
456 int i;
457 cff_index_element_t *element;
458 uint16_t count;
459 unsigned char buf[5];
460 cairo_status_t status;
461
462 num_elem = _cairo_array_num_elements (index);
463 count = cpu_to_be16 ((uint16_t) num_elem);
464 status = _cairo_array_append_multiple (output, &count, 2);
465 if (unlikely (status)(__builtin_expect (!!(status), 0)))
466 return status;
467
468 if (num_elem == 0)
469 return CAIRO_STATUS_SUCCESS;
470
471 /* Find maximum offset to determine offset size */
472 offset = 1;
473 for (i = 0; i < num_elem; i++) {
474 element = _cairo_array_index (index, i);
475 offset += element->length;
476 }
477 if (offset < 0x100)
478 offset_size = 1;
479 else if (offset < 0x10000)
480 offset_size = 2;
481 else if (offset < 0x1000000)
482 offset_size = 3;
483 else
484 offset_size = 4;
485
486 buf[0] = (unsigned char) offset_size;
487 status = _cairo_array_append (output, buf);
488 if (unlikely (status)(__builtin_expect (!!(status), 0)))
489 return status;
490
491 offset = 1;
492 encode_index_offset (buf, offset_size, offset);
493 status = _cairo_array_append_multiple (output, buf, offset_size);
494 if (unlikely (status)(__builtin_expect (!!(status), 0)))
495 return status;
496
497 for (i = 0; i < num_elem; i++) {
498 element = _cairo_array_index (index, i);
499 offset += element->length;
500 encode_index_offset (buf, offset_size, offset);
501 status = _cairo_array_append_multiple (output, buf, offset_size);
502 if (unlikely (status)(__builtin_expect (!!(status), 0)))
503 return status;
504 }
505
506 for (i = 0; i < num_elem; i++) {
507 element = _cairo_array_index (index, i);
508 if (element->length > 0) {
509 status = _cairo_array_append_multiple (output,
510 element->data,
511 element->length);
512 }
513 if (unlikely (status)(__builtin_expect (!!(status), 0)))
514 return status;
515 }
516 return CAIRO_STATUS_SUCCESS;
517}
518
519static void
520cff_index_set_object (cairo_array_t *index, int obj_index,
521 unsigned char *object , int length)
522{
523 cff_index_element_t *element;
524
525 element = _cairo_array_index (index, obj_index);
526 if (element->is_copy)
527 free (element->data);
528
529 element->data = object;
530 element->length = length;
531 element->is_copy = FALSE0;
532}
533
534static cairo_status_t
535cff_index_append (cairo_array_t *index, unsigned char *object , int length)
536{
537 cff_index_element_t element;
538
539 element.length = length;
540 element.is_copy = FALSE0;
541 element.data = object;
542
543 return _cairo_array_append (index, &element);
544}
545
546static cairo_status_t
547cff_index_append_copy (cairo_array_t *index,
548 const unsigned char *object,
549 unsigned int length)
550{
551 cff_index_element_t element;
552 cairo_status_t status;
553
554 element.length = length;
555 element.is_copy = TRUE1;
556 element.data = _cairo_malloc (element.length)((element.length) != 0 ? malloc(element.length) : ((void*)0));
557 if (unlikely (element.data == NULL && length != 0)(__builtin_expect (!!(element.data == ((void*)0) && length
!= 0), 0))
)
558 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
559
560 memcpy (element.data, object, element.length);
561
562 status = _cairo_array_append (index, &element);
563 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
564 free (element.data);
565 return status;
566 }
567
568 return CAIRO_STATUS_SUCCESS;
569}
570
571static void
572cff_index_fini (cairo_array_t *index)
573{
574 cff_index_element_t *element;
575 unsigned int i;
576
577 for (i = 0; i < _cairo_array_num_elements (index); i++) {
578 element = _cairo_array_index (index, i);
579 if (element->is_copy && element->data)
580 free (element->data);
581 }
582 _cairo_array_fini (index);
583}
584
585static cairo_bool_t
586_cairo_cff_dict_equal (const void *key_a, const void *key_b)
587{
588 const cff_dict_operator_t *op_a = key_a;
589 const cff_dict_operator_t *op_b = key_b;
590
591 return op_a->operator == op_b->operator;
592}
593
594static cairo_status_t
595cff_dict_init (cairo_hash_table_t **dict)
596{
597 *dict = _cairo_hash_table_create (_cairo_cff_dict_equal);
598 if (unlikely (*dict == NULL)(__builtin_expect (!!(*dict == ((void*)0)), 0)))
599 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
600
601 return CAIRO_STATUS_SUCCESS;
602}
603
604static void
605_cairo_dict_init_key (cff_dict_operator_t *key, int operator)
606{
607 key->base.hash = (unsigned long) operator;
608 key->operator = operator;
609}
610
611static cairo_status_t
612cff_dict_create_operator (int operator,
613 unsigned char *operand,
614 int size,
615 cff_dict_operator_t **out)
616{
617 cff_dict_operator_t *op;
618
619 op = _cairo_malloc (sizeof (cff_dict_operator_t))((sizeof (cff_dict_operator_t)) != 0 ? malloc(sizeof (cff_dict_operator_t
)) : ((void*)0))
;
620 if (unlikely (op == NULL)(__builtin_expect (!!(op == ((void*)0)), 0)))
621 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
622
623 _cairo_dict_init_key (op, operator);
624 if (size != 0) {
625 op->operand = _cairo_malloc (size)((size) != 0 ? malloc(size) : ((void*)0));
626 if (unlikely (op->operand == NULL)(__builtin_expect (!!(op->operand == ((void*)0)), 0))) {
627 free (op);
628 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
629 }
630 memcpy (op->operand, operand, size);
631 } else {
632 op->operand = NULL((void*)0);
633 /* Delta-encoded arrays can be empty. */
634 if (operator != BLUEVALUES_OP0x0006 &&
635 operator != OTHERBLUES_OP0x0007 &&
636 operator != FAMILYBLUES_OP0x0008 &&
637 operator != FAMILYOTHERBLUES_OP0x0009 &&
638 operator != STEMSNAPH_OP0x0c0c &&
639 operator != STEMSNAPV_OP0x0c0d) {
640 free (op);
641 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
642 }
643 }
644
645 op->operand_length = size;
646 op->operand_offset = -1;
647
648 *out = op;
649 return CAIRO_STATUS_SUCCESS;
650}
651
652static cairo_status_t
653cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size)
654{
655 unsigned char *end;
656 cairo_array_t operands;
657 cff_dict_operator_t *op;
658 unsigned short operator;
659 cairo_status_t status = CAIRO_STATUS_SUCCESS;
660 int size;
661
662 end = p + dict_size;
663 _cairo_array_init (&operands, 1);
664 while (p < end) {
665 size = operand_length (p);
666 if (size != 0) {
667 status = _cairo_array_append_multiple (&operands, p, size);
668 if (unlikely (status)(__builtin_expect (!!(status), 0)))
669 goto fail;
670
671 p += size;
672 } else {
673 p = decode_operator (p, &operator);
674 status = cff_dict_create_operator (operator,
675 _cairo_array_index (&operands, 0),
676 _cairo_array_num_elements (&operands),
677 &op);
678 if (unlikely (status)(__builtin_expect (!!(status), 0)))
679 goto fail;
680
681 status = _cairo_hash_table_insert (dict, &op->base);
682 if (unlikely (status)(__builtin_expect (!!(status), 0)))
683 goto fail;
684
685 _cairo_array_truncate (&operands, 0);
686 }
687 }
688
689fail:
690 _cairo_array_fini (&operands);
691
692 return status;
693}
694
695static void
696cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
697{
698 cff_dict_operator_t key, *op;
699
700 _cairo_dict_init_key (&key, operator);
701 op = _cairo_hash_table_lookup (dict, &key.base);
702 if (op != NULL((void*)0)) {
703 free (op->operand);
704 _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
705 free (op);
706 }
707}
708
709static unsigned char *
710cff_dict_get_operands (cairo_hash_table_t *dict,
711 unsigned short operator,
712 int *size)
713{
714 cff_dict_operator_t key, *op;
715
716 _cairo_dict_init_key (&key, operator);
717 op = _cairo_hash_table_lookup (dict, &key.base);
718 if (op != NULL((void*)0)) {
719 *size = op->operand_length;
720 return op->operand;
721 }
722
723 return NULL((void*)0);
724}
725
726static cairo_status_t
727cff_dict_set_operands (cairo_hash_table_t *dict,
728 unsigned short operator,
729 unsigned char *operand,
730 int size)
731{
732 cff_dict_operator_t key, *op;
733 cairo_status_t status;
734
735 _cairo_dict_init_key (&key, operator);
736 op = _cairo_hash_table_lookup (dict, &key.base);
737 if (op != NULL((void*)0)) {
738 free (op->operand);
739 op->operand = _cairo_malloc (size)((size) != 0 ? malloc(size) : ((void*)0));
740 if (unlikely (op->operand == NULL)(__builtin_expect (!!(op->operand == ((void*)0)), 0)))
741 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
742
743 memcpy (op->operand, operand, size);
744 op->operand_length = size;
745 }
746 else
747 {
748 status = cff_dict_create_operator (operator, operand, size, &op);
749 if (unlikely (status)(__builtin_expect (!!(status), 0)))
750 return status;
751
752 status = _cairo_hash_table_insert (dict, &op->base);
753 if (unlikely (status)(__builtin_expect (!!(status), 0)))
754 return status;
755 }
756
757 return CAIRO_STATUS_SUCCESS;
758}
759
760static int
761cff_dict_get_location (cairo_hash_table_t *dict,
762 unsigned short operator,
763 int *size)
764{
765 cff_dict_operator_t key, *op;
766
767 _cairo_dict_init_key (&key, operator);
768 op = _cairo_hash_table_lookup (dict, &key.base);
769 if (op != NULL((void*)0)) {
770 *size = op->operand_length;
771 return op->operand_offset;
772 }
773
774 return -1;
775}
776
777typedef struct _dict_write_info {
778 cairo_array_t *output;
779 cairo_status_t status;
780} dict_write_info_t;
781
782static void
783cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info)
784{
785 unsigned char data;
786
787 op->operand_offset = _cairo_array_num_elements (write_info->output);
788 write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length);
789 if (write_info->status)
790 return;
791
792 if (op->operator & 0xff00) {
793 data = op->operator >> 8;
794 write_info->status = _cairo_array_append (write_info->output, &data);
795 if (write_info->status)
796 return;
797 }
798 data = op->operator & 0xff;
799 write_info->status = _cairo_array_append (write_info->output, &data);
800}
801
802static void
803_cairo_dict_collect (void *entry, void *closure)
804{
805 dict_write_info_t *write_info = closure;
806 cff_dict_operator_t *op = entry;
807
808 if (write_info->status)
809 return;
810
811 /* The ROS operator is handled separately in cff_dict_write() */
812 if (op->operator != ROS_OP0x0c1e)
813 cairo_dict_write_operator (op, write_info);
814}
815
816static cairo_status_t
817cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output)
818{
819 dict_write_info_t write_info;
820 cff_dict_operator_t key, *op;
821
822 write_info.output = output;
823 write_info.status = CAIRO_STATUS_SUCCESS;
824
825 /* The CFF specification requires that the Top Dict of CID fonts
826 * begin with the ROS operator. */
827 _cairo_dict_init_key (&key, ROS_OP0x0c1e);
828 op = _cairo_hash_table_lookup (dict, &key.base);
829 if (op != NULL((void*)0))
830 cairo_dict_write_operator (op, &write_info);
831
832 _cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info);
833
834 return write_info.status;
835}
836
837static void
838_cff_dict_entry_pluck (void *_entry, void *dict)
839{
840 cff_dict_operator_t *entry = _entry;
841
842 _cairo_hash_table_remove (dict, &entry->base);
843 free (entry->operand);
844 free (entry);
845}
846
847static void
848cff_dict_fini (cairo_hash_table_t *dict)
849{
850 _cairo_hash_table_foreach (dict, _cff_dict_entry_pluck, dict);
851 _cairo_hash_table_destroy (dict);
852}
853
854static cairo_int_status_t
855cairo_cff_font_read_header (cairo_cff_font_t *font)
856{
857 if (font->data_length < sizeof (cff_header_t))
858 return CAIRO_INT_STATUS_UNSUPPORTED;
859
860
861 font->header = (cff_header_t *) font->data;
862 font->current_ptr = font->data + font->header->header_size;
863
864 return CAIRO_STATUS_SUCCESS;
865}
866
867static cairo_int_status_t
868cairo_cff_font_read_name (cairo_cff_font_t *font)
869{
870 cairo_array_t index;
871 cairo_int_status_t status;
872 cff_index_element_t *element;
873 unsigned char *p;
874 int i, len;
875
876 cff_index_init (&index);
877 status = cff_index_read (&index, &font->current_ptr, font->data_end);
878 if (status == CAIRO_INT_STATUS_SUCCESS && !font->is_opentype) {
879 element = _cairo_array_index (&index, 0);
880 p = element->data;
881 len = element->length;
882
883 /* If font name is prefixed with a subset tag, strip it off. */
884 if (len > 7 && p[6] == '+') {
885 for (i = 0; i < 6; i++)
886 if (p[i] < 'A' || p[i] > 'Z')
887 break;
888 if (i == 6) {
889 p += 7;
890 len -= 7;
891 }
892 }
893
894 font->ps_name = _cairo_strndupstrndup ((char*)p, len);
895 if (unlikely (font->ps_name == NULL)(__builtin_expect (!!(font->ps_name == ((void*)0)), 0)))
896 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
897
898 status = _cairo_escape_ps_name (&font->ps_name);
899 }
900 cff_index_fini (&index);
901
902 return status;
903}
904
905static cairo_int_status_t
906cairo_cff_font_read_private_dict (cairo_cff_font_t *font,
907 cairo_hash_table_t *private_dict,
908 cairo_array_t *local_sub_index,
909 int *local_sub_bias,
910 cairo_bool_t **local_subs_used,
911 double *default_width,
912 double *nominal_width,
913 unsigned char *ptr,
914 int size)
915{
916 cairo_int_status_t status;
917 unsigned char buf[10];
918 unsigned char *end_buf;
919 int offset;
920 int i;
921 unsigned char *operand;
922 unsigned char *p;
923 int num_subs;
924
925 status = cff_dict_read (private_dict, ptr, size);
926 if (unlikely (status)(__builtin_expect (!!(status), 0)))
927 return status;
928
929 operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP0x0013, &i);
930 if (operand) {
931 decode_integer (operand, &offset);
932 p = ptr + offset;
933 status = cff_index_read (local_sub_index, &p, font->data_end);
934 if (unlikely (status)(__builtin_expect (!!(status), 0)))
935 return status;
936
937 /* Use maximum sized encoding to reserve space for later modification. */
938 end_buf = encode_integer_max (buf, 0);
939 status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP0x0013, buf, end_buf - buf);
940 if (unlikely (status)(__builtin_expect (!!(status), 0)))
941 return status;
942 }
943
944 *default_width = 0;
945 operand = cff_dict_get_operands (private_dict, DEFAULTWIDTH_OP0x0014, &i);
946 if (operand)
947 decode_number (operand, default_width);
948
949 *nominal_width = 0;
950 operand = cff_dict_get_operands (private_dict, NOMINALWIDTH_OP0x0015, &i);
951 if (operand)
952 decode_number (operand, nominal_width);
953
954 num_subs = _cairo_array_num_elements (local_sub_index);
955 *local_subs_used = calloc (num_subs, sizeof (cairo_bool_t));
956 if (unlikely (*local_subs_used == NULL)(__builtin_expect (!!(*local_subs_used == ((void*)0)), 0)))
957 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
958
959 if (num_subs < 1240)
960 *local_sub_bias = 107;
961 else if (num_subs < 33900)
962 *local_sub_bias = 1131;
963 else
964 *local_sub_bias = 32768;
965
966 return CAIRO_STATUS_SUCCESS;
967}
968
969static cairo_int_status_t
970cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p)
971{
972 int type, num_ranges, first, last, fd, i, j;
973
974 font->fdselect = calloc (font->num_glyphs, sizeof (int));
975 if (unlikely (font->fdselect == NULL)(__builtin_expect (!!(font->fdselect == ((void*)0)), 0)))
976 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
977
978 type = *p++;
979 if (type == 0)
980 {
981 for (i = 0; i < font->num_glyphs; i++)
982 font->fdselect[i] = *p++;
983 } else if (type == 3) {
984 num_ranges = get_unaligned_be16 (p);
985 p += 2;
986 for (i = 0; i < num_ranges; i++)
987 {
988 first = get_unaligned_be16 (p);
989 p += 2;
990 fd = *p++;
991 last = get_unaligned_be16 (p);
992 if (last > font->num_glyphs)
993 return CAIRO_INT_STATUS_UNSUPPORTED;
994 for (j = first; j < last; j++)
995 font->fdselect[j] = fd;
996 }
997 } else {
998 return CAIRO_INT_STATUS_UNSUPPORTED;
999 }
1000
1001 return CAIRO_STATUS_SUCCESS;
1002}
1003
1004static cairo_int_status_t
1005cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
1006{
1007 cairo_array_t index;
1008 cff_index_element_t *element;
1009 unsigned int i;
1010 int size;
1011 unsigned char *operand;
1012 int offset;
1013 cairo_int_status_t status;
1014 unsigned char buf[100];
1015 unsigned char *end_buf;
1016
1017 cff_index_init (&index);
1018 status = cff_index_read (&index, &ptr, font->data_end);
1019 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1020 goto fail;
1021
1022 font->num_fontdicts = _cairo_array_num_elements (&index);
1023
1024 font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
1025 if (unlikely (font->fd_dict == NULL)(__builtin_expect (!!(font->fd_dict == ((void*)0)), 0))) {
1026 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1027 goto fail;
1028 }
1029
1030 font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
1031 if (unlikely (font->fd_private_dict == NULL)(__builtin_expect (!!(font->fd_private_dict == ((void*)0))
, 0))
) {
1032 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1033 goto fail;
1034 }
1035
1036 font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts);
1037 if (unlikely (font->fd_local_sub_index == NULL)(__builtin_expect (!!(font->fd_local_sub_index == ((void*)
0)), 0))
) {
1038 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1039 goto fail;
1040 }
1041
1042 font->fd_local_sub_bias = calloc (sizeof (int), font->num_fontdicts);
1043 if (unlikely (font->fd_local_sub_bias == NULL)(__builtin_expect (!!(font->fd_local_sub_bias == ((void*)0
)), 0))
) {
1044 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1045 goto fail;
1046 }
1047
1048 font->fd_local_subs_used = calloc (sizeof (cairo_bool_t *), font->num_fontdicts);
1049 if (unlikely (font->fd_local_subs_used == NULL)(__builtin_expect (!!(font->fd_local_subs_used == ((void*)
0)), 0))
) {
1050 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1051 goto fail;
1052 }
1053
1054 font->fd_default_width = calloc (font->num_fontdicts, sizeof (double));
1055 if (unlikely (font->fd_default_width == NULL)(__builtin_expect (!!(font->fd_default_width == ((void*)0)
), 0))
) {
1056 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1057 goto fail;
1058 }
1059
1060 font->fd_nominal_width = calloc (font->num_fontdicts, sizeof (double));
1061 if (unlikely (font->fd_nominal_width == NULL)(__builtin_expect (!!(font->fd_nominal_width == ((void*)0)
), 0))
) {
1062 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1063 goto fail;
1064 }
1065
1066 for (i = 0; i < font->num_fontdicts; i++) {
1067 status = cff_dict_init (&font->fd_dict[i]);
1068 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1069 goto fail;
1070
1071 element = _cairo_array_index (&index, i);
1072 status = cff_dict_read (font->fd_dict[i], element->data, element->length);
1073 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1074 goto fail;
1075
1076 operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP0x0012, &size);
1077 if (operand == NULL((void*)0)) {
1078 status = CAIRO_INT_STATUS_UNSUPPORTED;
1079 goto fail;
1080 }
1081 operand = decode_integer (operand, &size);
1082 decode_integer (operand, &offset);
1083 status = cff_dict_init (&font->fd_private_dict[i]);
1084 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1085 goto fail;
1086
1087 cff_index_init (&font->fd_local_sub_index[i]);
1088 status = cairo_cff_font_read_private_dict (font,
1089 font->fd_private_dict[i],
1090 &font->fd_local_sub_index[i],
1091 &font->fd_local_sub_bias[i],
1092 &font->fd_local_subs_used[i],
1093 &font->fd_default_width[i],
1094 &font->fd_nominal_width[i],
1095 font->data + offset,
1096 size);
1097 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1098 goto fail;
1099
1100 /* Set integer operand to max value to use max size encoding to reserve
1101 * space for any value later */
1102 end_buf = encode_integer_max (buf, 0);
1103 end_buf = encode_integer_max (end_buf, 0);
1104 status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP0x0012, buf, end_buf - buf);
1105 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1106 goto fail;
1107 }
1108
1109 status = CAIRO_STATUS_SUCCESS;
1110
1111fail:
1112 cff_index_fini (&index);
1113
1114 return status;
1115}
1116
1117static void
1118cairo_cff_font_read_font_metrics (cairo_cff_font_t *font, cairo_hash_table_t *top_dict)
1119{
1120 unsigned char *p;
1121 unsigned char *end;
1122 int size;
1123 double x_min, y_min, x_max, y_max;
1124 double xx, yx, xy, yy;
1125
1126 x_min = 0.0;
1127 y_min = 0.0;
1128 x_max = 0.0;
1129 y_max = 0.0;
1130 p = cff_dict_get_operands (font->top_dict, FONTBBOX_OP0x0005, &size);
1131 if (p) {
1132 end = p + size;
1133 if (p < end)
1134 p = decode_number (p, &x_min);
1135 if (p < end)
1136 p = decode_number (p, &y_min);
1137 if (p < end)
1138 p = decode_number (p, &x_max);
1139 if (p < end)
1140 p = decode_number (p, &y_max);
1141 }
1142 font->x_min = floor (x_min);
1143 font->y_min = floor (y_min);
1144 font->x_max = floor (x_max);
1145 font->y_max = floor (y_max);
1146 font->ascent = font->y_max;
1147 font->descent = font->y_min;
1148
1149 xx = 0.001;
1150 yx = 0.0;
1151 xy = 0.0;
1152 yy = 0.001;
1153 p = cff_dict_get_operands (font->top_dict, FONTMATRIX_OP0x0c07, &size);
1154 if (p) {
1155 end = p + size;
1156 if (p < end)
1157 p = decode_number (p, &xx);
1158 if (p < end)
1159 p = decode_number (p, &yx);
1160 if (p < end)
1161 p = decode_number (p, &xy);
1162 if (p < end)
1163 p = decode_number (p, &yy);
1164 }
1165 /* FreeType uses 1/abs(yy) to get units per EM */
1166 font->units_per_em = _cairo_round(1.0/fabs(yy));
1167}
1168
1169static cairo_int_status_t
1170cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
1171{
1172 cairo_array_t index;
1173 cff_index_element_t *element;
1174 unsigned char buf[20];
1175 unsigned char *end_buf;
1176 unsigned char *operand;
1177 cairo_int_status_t status;
1178 unsigned char *p;
1179 int size;
1180 int offset;
1181
1182 cff_index_init (&index);
1183 status = cff_index_read (&index, &font->current_ptr, font->data_end);
1184 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1185 goto fail;
1186
1187 element = _cairo_array_index (&index, 0);
1188 if (element == NULL((void*)0))
1189 return CAIRO_STATUS_NO_MEMORY;
1190 status = cff_dict_read (font->top_dict, element->data, element->length);
1191 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1192 goto fail;
1193
1194 if (cff_dict_get_operands (font->top_dict, ROS_OP0x0c1e, &size) != NULL((void*)0))
1195 font->is_cid = TRUE1;
1196 else
1197 font->is_cid = FALSE0;
1198
1199 operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP0x0011, &size);
1200 decode_integer (operand, &offset);
1201 p = font->data + offset;
1202 status = cff_index_read (&font->charstrings_index, &p, font->data_end);
1203 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1204 goto fail;
1205 font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index);
1206
1207 if (font->is_cid) {
1208 operand = cff_dict_get_operands (font->top_dict, CHARSET_OP0x000f, &size);
1209 if (!operand)
1210 return CAIRO_INT_STATUS_UNSUPPORTED;
1211
1212 decode_integer (operand, &offset);
1213 font->charset = font->data + offset;
1214 if (font->charset >= font->data_end)
1215 return CAIRO_INT_STATUS_UNSUPPORTED;
1216 }
1217
1218 if (!font->is_opentype)
1219 cairo_cff_font_read_font_metrics (font, font->top_dict);
1220
1221 if (font->is_cid) {
1222 operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP0x0c25, &size);
1223 decode_integer (operand, &offset);
1224 status = cairo_cff_font_read_fdselect (font, font->data + offset);
1225 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1226 goto fail;
1227
1228 operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP0x0c24, &size);
1229 decode_integer (operand, &offset);
1230 status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
1231 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1232 goto fail;
1233 } else {
1234 operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP0x0012, &size);
1235 operand = decode_integer (operand, &size);
1236 decode_integer (operand, &offset);
1237 status = cairo_cff_font_read_private_dict (font,
1238 font->private_dict,
1239 &font->local_sub_index,
1240 &font->local_sub_bias,
1241 &font->local_subs_used,
1242 &font->default_width,
1243 &font->nominal_width,
1244 font->data + offset,
1245 size);
1246 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1247 goto fail;
1248 }
1249
1250 /* Use maximum sized encoding to reserve space for later modification. */
1251 end_buf = encode_integer_max (buf, 0);
1252 status = cff_dict_set_operands (font->top_dict,
1253 CHARSTRINGS_OP0x0011, buf, end_buf - buf);
1254 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1255 goto fail;
1256
1257 status = cff_dict_set_operands (font->top_dict,
1258 CHARSET_OP0x000f, buf, end_buf - buf);
1259 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1260 goto fail;
1261
1262 if (font->scaled_font_subset->is_latin) {
1263 status = cff_dict_set_operands (font->top_dict,
1264 ENCODING_OP0x0010, buf, end_buf - buf);
1265 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1266 goto fail;
1267
1268 /* Private has two operands - size and offset */
1269 end_buf = encode_integer_max (end_buf, 0);
1270 cff_dict_set_operands (font->top_dict, PRIVATE_OP0x0012, buf, end_buf - buf);
1271 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1272 goto fail;
1273
1274 } else {
1275 status = cff_dict_set_operands (font->top_dict,
1276 FDSELECT_OP0x0c25, buf, end_buf - buf);
1277 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1278 goto fail;
1279
1280 status = cff_dict_set_operands (font->top_dict,
1281 FDARRAY_OP0x0c24, buf, end_buf - buf);
1282 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1283 goto fail;
1284
1285 cff_dict_remove (font->top_dict, ENCODING_OP0x0010);
1286 cff_dict_remove (font->top_dict, PRIVATE_OP0x0012);
1287 }
1288
1289 /* Remove the unique identifier operators as the subsetted font is
1290 * not the same is the original font. */
1291 cff_dict_remove (font->top_dict, UNIQUEID_OP0x000d);
1292 cff_dict_remove (font->top_dict, XUID_OP0x000e);
1293
1294fail:
1295 cff_index_fini (&index);
1296
1297 return status;
1298}
1299
1300static cairo_int_status_t
1301cairo_cff_font_read_strings (cairo_cff_font_t *font)
1302{
1303 return cff_index_read (&font->strings_index, &font->current_ptr, font->data_end);
1304}
1305
1306static cairo_int_status_t
1307cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font)
1308{
1309 cairo_int_status_t status;
1310 int num_subs;
1311
1312 status = cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end);
1313 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1314 return status;
1315
1316 num_subs = _cairo_array_num_elements (&font->global_sub_index);
1317 font->global_subs_used = calloc (num_subs, sizeof(cairo_bool_t));
1318 if (unlikely (font->global_subs_used == NULL)(__builtin_expect (!!(font->global_subs_used == ((void*)0)
), 0))
)
1319 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1320
1321 if (num_subs < 1240)
1322 font->global_sub_bias = 107;
1323 else if (num_subs < 33900)
1324 font->global_sub_bias = 1131;
1325 else
1326 font->global_sub_bias = 32768;
1327
1328 return CAIRO_STATUS_SUCCESS;
1329}
1330
1331typedef cairo_int_status_t
1332(*font_read_t) (cairo_cff_font_t *font);
1333
1334static const font_read_t font_read_funcs[] = {
1335 cairo_cff_font_read_header,
1336 cairo_cff_font_read_name,
1337 cairo_cff_font_read_top_dict,
1338 cairo_cff_font_read_strings,
1339 cairo_cff_font_read_global_subroutines,
1340};
1341
1342static cairo_int_status_t
1343cairo_cff_font_read_font (cairo_cff_font_t *font)
1344{
1345 cairo_int_status_t status;
1346 unsigned int i;
1347
1348 for (i = 0; i < ARRAY_LENGTH (font_read_funcs)((int) (sizeof (font_read_funcs) / sizeof (font_read_funcs[0]
)))
; i++) {
1349 status = font_read_funcs[i] (font);
1350 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1351 return status;
1352 }
1353
1354 return CAIRO_STATUS_SUCCESS;
1355}
1356
1357static cairo_status_t
1358cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
1359{
1360 cairo_status_t status;
1361 unsigned char buf[30];
1362 unsigned char *p;
1363 int sid1, sid2;
1364 const char *registry = "Adobe";
1365 const char *ordering = "Identity";
1366
1367 sid1 = NUM_STD_STRINGS391 + _cairo_array_num_elements (&font->strings_subset_index);
1368 status = cff_index_append_copy (&font->strings_subset_index,
1369 (unsigned char *)registry,
1370 strlen(registry));
1371 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1372 return status;
1373
1374 sid2 = NUM_STD_STRINGS391 + _cairo_array_num_elements (&font->strings_subset_index);
1375 status = cff_index_append_copy (&font->strings_subset_index,
1376 (unsigned char *)ordering,
1377 strlen(ordering));
1378 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1379 return status;
1380
1381 p = encode_integer (buf, sid1);
1382 p = encode_integer (p, sid2);
1383 p = encode_integer (p, 0);
1384 status = cff_dict_set_operands (font->top_dict, ROS_OP0x0c1e, buf, p - buf);
1385 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1386 return status;
1387
1388 p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
1389 status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP0x0c22, buf, p - buf);
1390 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1391 return status;
1392
1393 return CAIRO_STATUS_SUCCESS;
1394}
1395
1396static cairo_status_t
1397cairo_cff_font_subset_dict_string(cairo_cff_font_t *font,
1398 cairo_hash_table_t *dict,
1399 int operator)
1400{
1401 int size;
1402 unsigned char *p;
1403 int sid;
1404 unsigned char buf[100];
1405 cff_index_element_t *element;
1406 cairo_status_t status;
1407
1408 p = cff_dict_get_operands (dict, operator, &size);
1409 if (!p)
1410 return CAIRO_STATUS_SUCCESS;
1411
1412 decode_integer (p, &sid);
1413 if (sid < NUM_STD_STRINGS391)
1414 return CAIRO_STATUS_SUCCESS;
1415
1416 element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS391);
1417 sid = NUM_STD_STRINGS391 + _cairo_array_num_elements (&font->strings_subset_index);
1418 status = cff_index_append (&font->strings_subset_index, element->data, element->length);
1419 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1420 return status;
1421
1422 p = encode_integer (buf, sid);
1423 status = cff_dict_set_operands (dict, operator, buf, p - buf);
1424 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1425 return status;
1426
1427 return CAIRO_STATUS_SUCCESS;
1428}
1429
1430static const int dict_strings[] = {
1431 VERSION_OP0x0000,
1432 NOTICE_OP0x0001,
1433 COPYRIGHT_OP0x0c00,
1434 FULLNAME_OP0x0002,
1435 FAMILYNAME_OP0x0003,
1436 WEIGHT_OP0x0004,
1437 POSTSCRIPT_OP0x0c15,
1438 BASEFONTNAME_OP0x0c16,
1439 FONTNAME_OP0x0c26,
1440};
1441
1442static cairo_status_t
1443cairo_cff_font_subset_dict_strings (cairo_cff_font_t *font,
1444 cairo_hash_table_t *dict)
1445{
1446 cairo_status_t status;
1447 unsigned int i;
1448
1449 for (i = 0; i < ARRAY_LENGTH (dict_strings)((int) (sizeof (dict_strings) / sizeof (dict_strings[0]))); i++) {
1450 status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]);
1451 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1452 return status;
1453 }
1454
1455 return CAIRO_STATUS_SUCCESS;
1456}
1457
1458static unsigned char *
1459type2_decode_integer (unsigned char *p, int *integer)
1460{
1461 if (*p == 28) {
1462 *integer = p[1] << 8 | p[2];
1463 p += 3;
1464 } else if (*p <= 246) {
1465 *integer = *p++ - 139;
1466 } else if (*p <= 250) {
1467 *integer = (p[0] - 247) * 256 + p[1] + 108;
1468 p += 2;
1469 } else if (*p <= 254) {
1470 *integer = -(p[0] - 251) * 256 - p[1] - 108;
1471 p += 2;
1472 } else { /* *p == 255 */
1473 /* 16.16 fixed-point number. The fraction is ignored. */
1474 *integer = (int16_t)((p[1] << 8) | p[2]);
1475 p += 5;
1476 }
1477 return p;
1478}
1479
1480/* Type 2 charstring parser for finding calls to local or global
1481 * subroutines. For non Opentype CFF fonts it also gets the glyph
1482 * widths.
1483 *
1484 * When we find a subroutine operator, the subroutine is marked as in
1485 * use and recursively followed. The subroutine number is the value on
1486 * the top of the stack when the subroutine operator is executed. In
1487 * most fonts the subroutine number is encoded in an integer
1488 * immediately preceding the subroutine operator. However it is
1489 * possible for the subroutine number on the stack to be the result of
1490 * a computation (in which case there will be an operator preceding
1491 * the subroutine operator). If this occurs, subroutine subsetting is
1492 * disabled since we can't easily determine which subroutines are
1493 * used.
1494 *
1495 * The width, if present, is the first integer in the charstring. The
1496 * only way to confirm if the integer at the start of the charstring is
1497 * the width is when the first stack clearing operator is parsed,
1498 * check if there is an extra integer left over on the stack.
1499 *
1500 * When the first stack clearing operator is encountered
1501 * type2_find_width is set to FALSE and type2_found_width is set to
1502 * TRUE if an extra argument is found, otherwise FALSE.
1503 */
1504static cairo_status_t
1505cairo_cff_parse_charstring (cairo_cff_font_t *font,
1506 unsigned char *charstring, int length,
1507 int glyph_id,
1508 cairo_bool_t need_width)
1509{
1510 unsigned char *p = charstring;
1511 unsigned char *end = charstring + length;
1512 int integer;
1513 int hint_bytes;
1514 int sub_num;
1515 cff_index_element_t *element;
1516 int fd;
1517
1518 while (p < end) {
1519 if (*p == 28 || *p >= 32) {
1520 /* Integer value */
1521 p = type2_decode_integer (p, &integer);
1522 font->type2_stack_size++;
1523 font->type2_stack_top_value = integer;
1524 font->type2_stack_top_is_int = TRUE1;
1525 if (!font->type2_seen_first_int) {
1526 font->type2_width = integer;
1527 font->type2_seen_first_int = TRUE1;
1528 }
1529 } else if (*p == TYPE2_hstem0x0001 || *p == TYPE2_vstem0x0003 ||
1530 *p == TYPE2_hstemhm0x0012 || *p == TYPE2_vstemhm0x0017) {
1531 /* Hint operator. The number of hints declared by the
1532 * operator depends on the size of the stack. */
1533 font->type2_stack_top_is_int = FALSE0;
1534 font->type2_num_hints += font->type2_stack_size/2;
1535 if (font->type2_find_width && font->type2_stack_size % 2)
1536 font->type2_found_width = TRUE1;
1537
1538 font->type2_stack_size = 0;
1539 font->type2_find_width = FALSE0;
1540 p++;
1541 } else if (*p == TYPE2_hintmask0x0013 || *p == TYPE2_cntrmask0x0014) {
1542 /* Hintmask operator. These operators are followed by a
1543 * variable length mask where the length depends on the
1544 * number of hints declared. The first time this is called
1545 * it is also an implicit vstem if there are arguments on
1546 * the stack. */
1547 if (font->type2_hintmask_bytes == 0) {
1548 font->type2_stack_top_is_int = FALSE0;
1549 font->type2_num_hints += font->type2_stack_size/2;
1550 if (font->type2_find_width && font->type2_stack_size % 2)
1551 font->type2_found_width = TRUE1;
1552
1553 font->type2_stack_size = 0;
1554 font->type2_find_width = FALSE0;
1555 font->type2_hintmask_bytes = (font->type2_num_hints+7)/8;
1556 }
1557
1558 hint_bytes = font->type2_hintmask_bytes;
1559 p++;
1560 p += hint_bytes;
1561 } else if (*p == TYPE2_rmoveto0x0015) {
1562 if (font->type2_find_width && font->type2_stack_size > 2)
1563 font->type2_found_width = TRUE1;
1564
1565 font->type2_stack_size = 0;
1566 font->type2_find_width = FALSE0;
1567 font->type2_has_path = TRUE1;
1568 p++;
1569 } else if (*p == TYPE2_hmoveto0x0016 || *p == TYPE2_vmoveto0x0004) {
1570 if (font->type2_find_width && font->type2_stack_size > 1)
1571 font->type2_found_width = TRUE1;
1572
1573 font->type2_stack_size = 0;
1574 font->type2_find_width = FALSE0;
1575 font->type2_has_path = TRUE1;
1576 p++;
1577 } else if (*p == TYPE2_endchar0x000e) {
1578 if (!font->type2_has_path && font->type2_stack_size > 3)
1579 return CAIRO_INT_STATUS_UNSUPPORTED; /* seac (Ref Appendix C of Type 2 Charstring Format */
1580
1581 if (font->type2_find_width && font->type2_stack_size > 0)
1582 font->type2_found_width = TRUE1;
1583
1584 return CAIRO_STATUS_SUCCESS;
1585 } else if (*p == TYPE2_callsubr0x000a) {
1586 /* call to local subroutine */
1587 if (! font->type2_stack_top_is_int)
1588 return CAIRO_INT_STATUS_UNSUPPORTED;
1589
1590 if (++font->type2_nesting_level > MAX_SUBROUTINE_NESTING10)
1591 return CAIRO_INT_STATUS_UNSUPPORTED;
1592
1593 p++;
1594 font->type2_stack_top_is_int = FALSE0;
1595 font->type2_stack_size--;
1596 if (font->type2_find_width && font->type2_stack_size == 0)
1597 font->type2_seen_first_int = FALSE0;
1598
1599 if (font->is_cid) {
1600 fd = font->fdselect[glyph_id];
1601 sub_num = font->type2_stack_top_value + font->fd_local_sub_bias[fd];
1602 if (sub_num >= (int)_cairo_array_num_elements(&font->fd_local_sub_index[fd]))
1603 return CAIRO_INT_STATUS_UNSUPPORTED;
1604 element = _cairo_array_index (&font->fd_local_sub_index[fd], sub_num);
1605 if (! font->fd_local_subs_used[fd][sub_num]) {
1606 font->fd_local_subs_used[fd][sub_num] = TRUE1;
1607 cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width);
1608 }
1609 } else {
1610 sub_num = font->type2_stack_top_value + font->local_sub_bias;
1611 if (sub_num >= (int)_cairo_array_num_elements(&font->local_sub_index))
1612 return CAIRO_INT_STATUS_UNSUPPORTED;
1613 element = _cairo_array_index (&font->local_sub_index, sub_num);
1614 if (! font->local_subs_used[sub_num] ||
1615 (need_width && !font->type2_found_width))
1616 {
1617 font->local_subs_used[sub_num] = TRUE1;
1618 cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width);
1619 }
1620 }
1621 font->type2_nesting_level--;
1622 } else if (*p == TYPE2_callgsubr0x001d) {
1623 /* call to global subroutine */
1624 if (! font->type2_stack_top_is_int)
1625 return CAIRO_INT_STATUS_UNSUPPORTED;
1626
1627 if (++font->type2_nesting_level > MAX_SUBROUTINE_NESTING10)
1628 return CAIRO_INT_STATUS_UNSUPPORTED;
1629
1630 p++;
1631 font->type2_stack_size--;
1632 font->type2_stack_top_is_int = FALSE0;
1633 if (font->type2_find_width && font->type2_stack_size == 0)
1634 font->type2_seen_first_int = FALSE0;
1635
1636 sub_num = font->type2_stack_top_value + font->global_sub_bias;
1637 if (sub_num >= (int)_cairo_array_num_elements(&font->global_sub_index))
1638 return CAIRO_INT_STATUS_UNSUPPORTED;
1639 element = _cairo_array_index (&font->global_sub_index, sub_num);
1640 if (! font->global_subs_used[sub_num] ||
1641 (need_width && !font->type2_found_width))
1642 {
1643 font->global_subs_used[sub_num] = TRUE1;
1644 cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width);
1645 }
1646 font->type2_nesting_level--;
1647 } else if (*p == 12) {
1648 /* 2 byte instruction */
1649
1650 /* All the 2 byte operators are either not valid before a
1651 * stack clearing operator or they are one of the
1652 * arithmetic, storage, or conditional operators. */
1653 if (need_width && font->type2_find_width)
1654 return CAIRO_INT_STATUS_UNSUPPORTED;
1655
1656 p += 2;
1657 font->type2_stack_top_is_int = FALSE0;
1658 } else {
1659 /* 1 byte instruction */
1660 p++;
1661 font->type2_stack_top_is_int = FALSE0;
1662 }
1663 }
1664
1665 return CAIRO_STATUS_SUCCESS;
1666}
1667
1668static cairo_status_t
1669cairo_cff_find_width_and_subroutines_used (cairo_cff_font_t *font,
1670 unsigned char *charstring, int length,
1671 int glyph_id, int subset_id)
1672{
1673 cairo_status_t status;
1674 int width;
1675 int fd;
1676
1677 font->type2_stack_size = 0;
1678 font->type2_stack_top_value = 0;;
1679 font->type2_stack_top_is_int = FALSE0;
1680 font->type2_num_hints = 0;
1681 font->type2_hintmask_bytes = 0;
1682 font->type2_nesting_level = 0;
1683 font->type2_seen_first_int = FALSE0;
1684 font->type2_find_width = TRUE1;
1685 font->type2_found_width = FALSE0;
1686 font->type2_width = 0;
1687 font->type2_has_path = FALSE0;
1688
1689 status = cairo_cff_parse_charstring (font, charstring, length, glyph_id, TRUE1);
1690 if (status)
1691 return status;
1692
1693 if (!font->is_opentype) {
1694 if (font->is_cid) {
1695 fd = font->fdselect[glyph_id];
1696 if (font->type2_found_width)
1697 width = font->fd_nominal_width[fd] + font->type2_width;
1698 else
1699 width = font->fd_default_width[fd];
1700 } else {
1701 if (font->type2_found_width)
1702 width = font->nominal_width + font->type2_width;
1703 else
1704 width = font->default_width;
1705 }
1706 font->widths[subset_id] = width;
1707 }
1708
1709 return CAIRO_STATUS_SUCCESS;
1710}
1711
1712static cairo_int_status_t
1713cairo_cff_font_get_gid_for_cid (cairo_cff_font_t *font, unsigned long cid, unsigned long *gid)
1714{
1715 unsigned char *p;
1716 unsigned long first_gid;
1717 unsigned long first_cid;
1718 int num_left;
1719 unsigned long c, g;
1720
1721 if (cid == 0) {
1722 *gid = 0;
1723 return CAIRO_STATUS_SUCCESS;
1724 }
1725
1726 switch (font->charset[0]) {
1727 /* Format 0 */
1728 case 0:
1729 p = font->charset + 1;
1730 g = 1;
1731 while (g <= (unsigned)font->num_glyphs && p < font->data_end) {
1732 c = get_unaligned_be16 (p);
1733 if (c == cid) {
1734 *gid = g;
1735 return CAIRO_STATUS_SUCCESS;
1736 }
1737 g++;
1738 p += 2;
1739 }
1740 break;
1741
1742 /* Format 1 */
1743 case 1:
1744 first_gid = 1;
1745 p = font->charset + 1;
1746 while (first_gid <= (unsigned)font->num_glyphs && p + 2 < font->data_end) {
1747 first_cid = get_unaligned_be16 (p);
1748 num_left = p[2];
1749 if (cid >= first_cid && cid <= first_cid + num_left) {
1750 *gid = first_gid + cid - first_cid;
1751 return CAIRO_STATUS_SUCCESS;
1752 }
1753 first_gid += num_left + 1;
1754 p += 3;
1755 }
1756 break;
1757
1758 /* Format 2 */
1759 case 2:
1760 first_gid = 1;
1761 p = font->charset + 1;
1762 while (first_gid <= (unsigned)font->num_glyphs && p + 3 < font->data_end) {
1763 first_cid = get_unaligned_be16 (p);
1764 num_left = get_unaligned_be16 (p+2);
1765 if (cid >= first_cid && cid <= first_cid + num_left) {
1766 *gid = first_gid + cid - first_cid;
1767 return CAIRO_STATUS_SUCCESS;
1768 }
1769 first_gid += num_left + 1;
1770 p += 4;
1771 }
1772 break;
1773
1774 default:
1775 break;
1776 }
1777 return CAIRO_INT_STATUS_UNSUPPORTED;
1778}
1779
1780static cairo_int_status_t
1781cairo_cff_font_subset_charstrings_and_subroutines (cairo_cff_font_t *font)
1782{
1783 cff_index_element_t *element;
1784 unsigned int i;
1785 cairo_int_status_t status;
1786 unsigned long glyph, cid;
1787
1788 font->subset_subroutines = TRUE1;
1789 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
1790 if (font->is_cid && !font->is_opentype) {
1791 cid = font->scaled_font_subset->glyphs[i];
1792 status = cairo_cff_font_get_gid_for_cid (font, cid, &glyph);
1793 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1794 return status;
1795 } else {
1796 glyph = font->scaled_font_subset->glyphs[i];
1797 }
1798 element = _cairo_array_index (&font->charstrings_index, glyph);
1799 status = cff_index_append (&font->charstrings_subset_index,
1800 element->data,
1801 element->length);
1802 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1803 return status;
1804
1805 if (font->subset_subroutines) {
1806 status = cairo_cff_find_width_and_subroutines_used (font,
1807 element->data, element->length,
1808 glyph, i);
1809 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1810 /* If parsing the charstrings fails we embed all the
1811 * subroutines. But if the font is not opentype we
1812 * need to successfully parse all charstrings to get
1813 * the widths. */
1814 font->subset_subroutines = FALSE0;
1815 if (!font->is_opentype)
1816 return status;
1817 } else if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1818 return status;
1819 }
1820 }
1821 }
1822
1823 return CAIRO_STATUS_SUCCESS;
1824}
1825
1826static cairo_status_t
1827cairo_cff_font_subset_fontdict (cairo_cff_font_t *font)
1828{
1829 unsigned int i;
1830 int fd;
1831 int *reverse_map;
1832 unsigned long cid, gid;
1833 cairo_int_status_t status;
1834
1835 font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs,
1836 sizeof (int));
1837 if (unlikely (font->fdselect_subset == NULL)(__builtin_expect (!!(font->fdselect_subset == ((void*)0))
, 0))
)
1838 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1839
1840 font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int));
1841 if (unlikely (font->fd_subset_map == NULL)(__builtin_expect (!!(font->fd_subset_map == ((void*)0)), 0
))
)
1842 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1843
1844 font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int));
1845 if (unlikely (font->private_dict_offset == NULL)(__builtin_expect (!!(font->private_dict_offset == ((void*
)0)), 0))
)
1846 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1847
1848 reverse_map = calloc (font->num_fontdicts, sizeof (int));
1849 if (unlikely (reverse_map == NULL)(__builtin_expect (!!(reverse_map == ((void*)0)), 0)))
1850 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1851
1852 for (i = 0; i < font->num_fontdicts; i++)
1853 reverse_map[i] = -1;
1854
1855 font->num_subset_fontdicts = 0;
1856 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
1857 if (font->is_opentype) {
1858 gid = font->scaled_font_subset->glyphs[i];
1859 } else {
1860 cid = font->scaled_font_subset->glyphs[i];
1861 status = cairo_cff_font_get_gid_for_cid (font, cid, &gid);
1862 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1863 free (reverse_map);
1864 return status;
1865 }
1866 }
1867
1868 fd = font->fdselect[gid];
1869 if (reverse_map[fd] < 0) {
1870 font->fd_subset_map[font->num_subset_fontdicts] = fd;
1871 reverse_map[fd] = font->num_subset_fontdicts++;
1872 }
1873 font->fdselect_subset[i] = reverse_map[fd];
1874 }
1875
1876 free (reverse_map);
1877
1878 return CAIRO_STATUS_SUCCESS;
1879}
1880
1881static cairo_status_t
1882cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
1883{
1884 unsigned char buf[100];
1885 unsigned char *end_buf;
1886 cairo_status_t status;
1887
1888 font->num_fontdicts = 1;
1889 font->fd_dict = _cairo_malloc (sizeof (cairo_hash_table_t *))((sizeof (cairo_hash_table_t *)) != 0 ? malloc(sizeof (cairo_hash_table_t
*)) : ((void*)0))
;
1890 if (unlikely (font->fd_dict == NULL)(__builtin_expect (!!(font->fd_dict == ((void*)0)), 0)))
1891 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1892
1893 if (cff_dict_init (&font->fd_dict[0])) {
1894 free (font->fd_dict);
1895 font->fd_dict = NULL((void*)0);
1896 font->num_fontdicts = 0;
1897 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1898 }
1899
1900 font->fd_subset_map = _cairo_malloc (sizeof (int))((sizeof (int)) != 0 ? malloc(sizeof (int)) : ((void*)0));
1901 if (unlikely (font->fd_subset_map == NULL)(__builtin_expect (!!(font->fd_subset_map == ((void*)0)), 0
))
)
1902 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1903
1904 font->private_dict_offset = _cairo_malloc (sizeof (int))((sizeof (int)) != 0 ? malloc(sizeof (int)) : ((void*)0));
1905 if (unlikely (font->private_dict_offset == NULL)(__builtin_expect (!!(font->private_dict_offset == ((void*
)0)), 0))
)
1906 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1907
1908 font->fd_subset_map[0] = 0;
1909 font->num_subset_fontdicts = 1;
1910
1911 /* Set integer operand to max value to use max size encoding to reserve
1912 * space for any value later */
1913 end_buf = encode_integer_max (buf, 0);
1914 end_buf = encode_integer_max (end_buf, 0);
1915 status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP0x0012, buf, end_buf - buf);
1916 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1917 return status;
1918
1919 return CAIRO_STATUS_SUCCESS;
1920}
1921
1922static cairo_status_t
1923cairo_cff_font_subset_strings (cairo_cff_font_t *font)
1924{
1925 cairo_status_t status;
1926 unsigned int i;
1927
1928 status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
1929 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1930 return status;
1931
1932 if (font->is_cid) {
1933 for (i = 0; i < font->num_subset_fontdicts; i++) {
1934 status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
1935 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1936 return status;
1937
1938 status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]);
1939 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1940 return status;
1941 }
1942 } else {
1943 status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
1944 }
1945
1946 return status;
1947}
1948
1949/* The Euro is the only the only character in the winansi encoding
1950 * with a glyph name that is not a CFF standard string. As the strings
1951 * are written before the charset, we need to check during the
1952 * subsetting phase if the Euro glyph is required and add the
1953 * glyphname to the list of strings to write out.
1954 */
1955static cairo_status_t
1956cairo_cff_font_add_euro_charset_string (cairo_cff_font_t *font)
1957{
1958 cairo_status_t status;
1959 unsigned int i;
1960 int ch;
1961 const char *euro = "Euro";
1962
1963 for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
1964 ch = font->scaled_font_subset->to_latin_char[i];
1965 if (ch == 128) {
1966 font->euro_sid = NUM_STD_STRINGS391 + _cairo_array_num_elements (&font->strings_subset_index);
1967 status = cff_index_append_copy (&font->strings_subset_index,
1968 (unsigned char *)euro, strlen(euro));
1969 return status;
1970 }
1971 }
1972
1973 return CAIRO_STATUS_SUCCESS;
1974}
1975
1976static cairo_status_t
1977cairo_cff_font_subset_font (cairo_cff_font_t *font)
1978{
1979 cairo_status_t status;
1980
1981 if (!font->scaled_font_subset->is_latin) {
1982 status = cairo_cff_font_set_ros_strings (font);
1983 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1984 return status;
1985 }
1986
1987 status = cairo_cff_font_subset_charstrings_and_subroutines (font);
1988 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1989 return status;
1990
1991 if (!font->scaled_font_subset->is_latin) {
1992 if (font->is_cid)
1993 status = cairo_cff_font_subset_fontdict (font);
1994 else
1995 status = cairo_cff_font_create_cid_fontdict (font);
1996 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1997 return status;
1998 } else {
1999 font->private_dict_offset = _cairo_malloc (sizeof (int))((sizeof (int)) != 0 ? malloc(sizeof (int)) : ((void*)0));
2000 if (unlikely (font->private_dict_offset == NULL)(__builtin_expect (!!(font->private_dict_offset == ((void*
)0)), 0))
)
2001 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2002 }
2003
2004 status = cairo_cff_font_subset_strings (font);
2005 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2006 return status;
2007
2008 if (font->scaled_font_subset->is_latin)
2009 status = cairo_cff_font_add_euro_charset_string (font);
2010
2011 return status;
2012}
2013
2014/* Set the operand of the specified operator in the (already written)
2015 * top dict to point to the current position in the output
2016 * array. Operands updated with this function must have previously
2017 * been encoded with the 5-byte (max) integer encoding. */
2018static void
2019cairo_cff_font_set_topdict_operator_to_cur_pos (cairo_cff_font_t *font,
2020 int operator)
2021{
2022 int cur_pos;
2023 int offset;
2024 int size;
2025 unsigned char buf[10];
2026 unsigned char *buf_end;
2027 unsigned char *op_ptr;
2028
2029 cur_pos = _cairo_array_num_elements (&font->output);
2030 buf_end = encode_integer_max (buf, cur_pos);
2031 offset = cff_dict_get_location (font->top_dict, operator, &size);
2032 assert (offset > 0)((void) sizeof ((offset > 0) ? 1 : 0), __extension__ ({ if
(offset > 0) ; else __assert_fail ("offset > 0", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2032, __extension__ __PRETTY_FUNCTION__); }))
;
2033 op_ptr = _cairo_array_index (&font->output, offset);
2034 memcpy (op_ptr, buf, buf_end - buf);
2035}
2036
2037static cairo_status_t
2038cairo_cff_font_write_header (cairo_cff_font_t *font)
2039{
2040 return _cairo_array_append_multiple (&font->output,
2041 font->header,
2042 font->header->header_size);
2043}
2044
2045static cairo_status_t
2046cairo_cff_font_write_name (cairo_cff_font_t *font)
2047{
2048 cairo_status_t status = CAIRO_STATUS_SUCCESS;
2049 cairo_array_t index;
2050
2051 cff_index_init (&index);
2052
2053 status = cff_index_append_copy (&index,
2054 (unsigned char *) font->ps_name,
2055 strlen(font->ps_name));
2056 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2057 goto FAIL;
2058
2059 status = cff_index_write (&index, &font->output);
2060 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2061 goto FAIL;
2062
2063FAIL:
2064 cff_index_fini (&index);
2065
2066 return status;
2067}
2068
2069static cairo_status_t
2070cairo_cff_font_write_top_dict (cairo_cff_font_t *font)
2071{
2072 uint16_t count;
2073 unsigned char buf[10];
2074 unsigned char *p;
2075 int offset_index;
2076 int dict_start, dict_size;
2077 int offset_size = 4;
2078 cairo_status_t status;
2079
2080 /* Write an index containing the top dict */
2081
2082 count = cpu_to_be16 (1);
2083 status = _cairo_array_append_multiple (&font->output, &count, 2);
2084 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2085 return status;
2086 buf[0] = offset_size;
2087 status = _cairo_array_append (&font->output, buf);
2088 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2089 return status;
2090 encode_index_offset (buf, offset_size, 1);
2091 status = _cairo_array_append_multiple (&font->output, buf, offset_size);
2092 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2093 return status;
2094
2095 /* Reserve space for last element of offset array and update after
2096 * dict is written */
2097 offset_index = _cairo_array_num_elements (&font->output);
2098 status = _cairo_array_append_multiple (&font->output, buf, offset_size);
2099 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2100 return status;
2101
2102 dict_start = _cairo_array_num_elements (&font->output);
2103 status = cff_dict_write (font->top_dict, &font->output);
2104 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2105 return status;
2106 dict_size = _cairo_array_num_elements (&font->output) - dict_start;
2107
2108 encode_index_offset (buf, offset_size, dict_size + 1);
2109 p = _cairo_array_index (&font->output, offset_index);
2110 memcpy (p, buf, offset_size);
2111
2112 return CAIRO_STATUS_SUCCESS;
2113}
2114
2115static cairo_status_t
2116cairo_cff_font_write_strings (cairo_cff_font_t *font)
2117{
2118 return cff_index_write (&font->strings_subset_index, &font->output);
2119}
2120
2121static cairo_status_t
2122cairo_cff_font_write_global_subrs (cairo_cff_font_t *font)
2123{
2124 unsigned int i;
2125 unsigned char return_op = TYPE2_return0x000b;
2126
2127 /* poppler and fontforge don't like zero length subroutines so we
2128 * replace unused subroutines with a 'return' instruction. */
2129 if (font->subset_subroutines) {
2130 for (i = 0; i < _cairo_array_num_elements (&font->global_sub_index); i++) {
2131 if (! font->global_subs_used[i])
2132 cff_index_set_object (&font->global_sub_index, i, &return_op, 1);
2133 }
2134 }
2135
2136 return cff_index_write (&font->global_sub_index, &font->output);
2137}
2138
2139static cairo_status_t
2140cairo_cff_font_write_encoding (cairo_cff_font_t *font)
2141{
2142 unsigned char buf[2];
2143 cairo_status_t status;
2144 unsigned int i;
2145
2146 cairo_cff_font_set_topdict_operator_to_cur_pos (font, ENCODING_OP0x0010);
2147 buf[0] = 0; /* Format 0 */
2148 buf[1] = font->scaled_font_subset->num_glyphs - 1;
2149 status = _cairo_array_append_multiple (&font->output, buf, 2);
2150 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2151 return status;
2152
2153 for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
2154 unsigned char ch = font->scaled_font_subset->to_latin_char[i];
2155 status = _cairo_array_append (&font->output, &ch);
2156 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2157 return status;
2158 }
2159
2160 return CAIRO_STATUS_SUCCESS;
2161}
2162
2163static cairo_status_t
2164cairo_cff_font_write_fdselect (cairo_cff_font_t *font)
2165{
2166 unsigned char data;
2167 unsigned int i;
2168 cairo_int_status_t status;
2169
2170 cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP0x0c25);
2171
2172 if (font->is_cid) {
2173 data = 0;
2174 status = _cairo_array_append (&font->output, &data);
2175 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2176 return status;
2177
2178 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
2179 data = font->fdselect_subset[i];
2180 status = _cairo_array_append (&font->output, &data);
2181 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2182 return status;
2183 }
2184 } else {
2185 unsigned char byte;
2186 uint16_t word;
2187
2188 status = _cairo_array_grow_by (&font->output, 9);
2189 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2190 return status;
2191
2192 byte = 3;
2193 status = _cairo_array_append (&font->output, &byte);
2194 assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0)
, __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else
__assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2194, __extension__ __PRETTY_FUNCTION__); }))
;
2195
2196 word = cpu_to_be16 (1);
2197 status = _cairo_array_append_multiple (&font->output, &word, 2);
2198 assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0)
, __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else
__assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2198, __extension__ __PRETTY_FUNCTION__); }))
;
2199
2200 word = cpu_to_be16 (0);
2201 status = _cairo_array_append_multiple (&font->output, &word, 2);
2202 assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0)
, __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else
__assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2202, __extension__ __PRETTY_FUNCTION__); }))
;
2203
2204 byte = 0;
2205 status = _cairo_array_append (&font->output, &byte);
2206 assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0)
, __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else
__assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2206, __extension__ __PRETTY_FUNCTION__); }))
;
2207
2208 word = cpu_to_be16 (font->scaled_font_subset->num_glyphs);
2209 status = _cairo_array_append_multiple (&font->output, &word, 2);
2210 assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0)
, __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else
__assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2210, __extension__ __PRETTY_FUNCTION__); }))
;
2211 }
2212
2213 return CAIRO_STATUS_SUCCESS;
2214}
2215
2216/* Winansi to CFF standard strings mapping for characters 128 to 255 */
2217static const int winansi_to_cff_std_string[] = {
2218 /* 128 */
2219 0, 0, 117, 101, 118, 121, 112, 113,
2220 126, 122, 192, 107, 142, 0, 199, 0,
2221 /* 144 */
2222 0, 65, 8, 105, 119, 116, 111, 137,
2223 127, 153, 221, 108, 148, 0, 228, 198,
2224 /* 160 */
2225 0, 96, 97, 98, 103, 100, 160, 102,
2226 131, 170, 139, 106, 151, 0, 165, 128,
2227 /* 176 */
2228 161, 156, 164, 169, 125, 152, 115, 114,
2229 133, 150, 143, 120, 158, 155, 163, 123,
2230 /* 192 */
2231 174, 171, 172, 176, 173, 175, 138, 177,
2232 181, 178, 179, 180, 185, 182, 183, 184,
2233 /* 208 */
2234 154, 186, 190, 187, 188, 191, 189, 168,
2235 141, 196, 193, 194, 195, 197, 157, 149,
2236 /* 224 */
2237 203, 200, 201, 205, 202, 204, 144, 206,
2238 210, 207, 208, 209, 214, 211, 212, 213,
2239 /* 240 */
2240 167, 215, 219, 216, 217, 220, 218, 159,
2241 147, 225, 222, 223, 224, 226, 162, 227,
2242};
2243
2244static int
2245cairo_cff_font_get_sid_for_winansi_char (cairo_cff_font_t *font, int ch)
2246{
2247 int sid;
2248
2249 if (ch == 39) {
2250 sid = 104;
2251
2252 } else if (ch == 96) {
2253 sid = 124;
2254
2255 } else if (ch >= 32 && ch <= 126) {
2256 sid = ch - 31;
2257
2258 } else if (ch == 128) {
2259 assert (font->euro_sid >= NUM_STD_STRINGS)((void) sizeof ((font->euro_sid >= 391) ? 1 : 0), __extension__
({ if (font->euro_sid >= 391) ; else __assert_fail ("font->euro_sid >= NUM_STD_STRINGS"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2259, __extension__ __PRETTY_FUNCTION__); }))
;
2260 sid = font->euro_sid;
2261
2262 } else if (ch >= 128 && ch <= 255) {
2263 sid = winansi_to_cff_std_string[ch - 128];
2264
2265 } else {
2266 sid = 0;
2267 }
2268
2269 return sid;
2270}
2271
2272static cairo_status_t
2273cairo_cff_font_write_type1_charset (cairo_cff_font_t *font)
2274{
2275 unsigned char format = 0;
2276 unsigned int i;
2277 int ch, sid;
2278 cairo_status_t status;
2279 uint16_t sid_be16;
2280
2281 cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP0x000f);
2282 status = _cairo_array_append (&font->output, &format);
2283 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2284 return status;
2285
2286 for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
2287 ch = font->scaled_font_subset->to_latin_char[i];
2288 sid = cairo_cff_font_get_sid_for_winansi_char (font, ch);
2289 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2290 return status;
2291
2292 sid_be16 = cpu_to_be16(sid);
2293 status = _cairo_array_append_multiple (&font->output, &sid_be16, sizeof(sid_be16));
2294 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2295 return status;
2296 }
2297
2298 return CAIRO_STATUS_SUCCESS;
2299}
2300
2301static cairo_status_t
2302cairo_cff_font_write_cid_charset (cairo_cff_font_t *font)
2303{
2304 unsigned char byte;
2305 uint16_t word;
2306 cairo_status_t status;
2307
2308 cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP0x000f);
2309 status = _cairo_array_grow_by (&font->output, 5);
2310 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2311 return status;
2312
2313 byte = 2;
2314 status = _cairo_array_append (&font->output, &byte);
2315 assert (status == CAIRO_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_STATUS_SUCCESS) ? 1 : 0), __extension__
({ if (status == CAIRO_STATUS_SUCCESS) ; else __assert_fail (
"status == CAIRO_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2315, __extension__ __PRETTY_FUNCTION__); }))
;
2316
2317 word = cpu_to_be16 (1);
2318 status = _cairo_array_append_multiple (&font->output, &word, 2);
2319 assert (status == CAIRO_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_STATUS_SUCCESS) ? 1 : 0), __extension__
({ if (status == CAIRO_STATUS_SUCCESS) ; else __assert_fail (
"status == CAIRO_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2319, __extension__ __PRETTY_FUNCTION__); }))
;
2320
2321 word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2);
2322 status = _cairo_array_append_multiple (&font->output, &word, 2);
2323 assert (status == CAIRO_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_STATUS_SUCCESS) ? 1 : 0), __extension__
({ if (status == CAIRO_STATUS_SUCCESS) ; else __assert_fail (
"status == CAIRO_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2323, __extension__ __PRETTY_FUNCTION__); }))
;
2324
2325 return CAIRO_STATUS_SUCCESS;
2326}
2327
2328static cairo_status_t
2329cairo_cff_font_write_charstrings (cairo_cff_font_t *font)
2330{
2331 cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP0x0011);
2332
2333 return cff_index_write (&font->charstrings_subset_index, &font->output);
2334}
2335
2336static cairo_status_t
2337cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
2338{
2339 unsigned int i;
2340 cairo_int_status_t status;
2341 unsigned int offset_array;
2342 unsigned char *offset_array_ptr;
2343 int offset_base;
2344 uint16_t count;
2345 uint8_t offset_size = 4;
2346
2347 cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP0x0c24);
2348 count = cpu_to_be16 (font->num_subset_fontdicts);
2349 status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t));
2350 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2351 return status;
2352 status = _cairo_array_append (&font->output, &offset_size);
2353 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2354 return status;
2355
2356 offset_array = _cairo_array_num_elements (&font->output);
2357 status = _cairo_array_allocate (&font->output,
2358 (font->num_subset_fontdicts + 1)*offset_size,
2359 (void **) &offset_array_ptr);
2360 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2361 return status;
2362 offset_base = _cairo_array_num_elements (&font->output) - 1;
2363 put_unaligned_be32(1, offset_array_ptr);
2364 offset_array += sizeof(uint32_t);
2365 for (i = 0; i < font->num_subset_fontdicts; i++) {
2366 status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
2367 &font->output);
2368 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2369 return status;
2370
2371 offset_array_ptr = _cairo_array_index (&font->output, offset_array);
2372 put_unaligned_be32 (_cairo_array_num_elements (&font->output) - offset_base,
2373 offset_array_ptr);
2374 offset_array += sizeof(uint32_t);
2375 }
2376
2377 return CAIRO_STATUS_SUCCESS;
2378}
2379
2380static cairo_status_t
2381cairo_cff_font_write_private_dict (cairo_cff_font_t *font,
2382 int dict_num,
2383 cairo_hash_table_t *parent_dict,
2384 cairo_hash_table_t *private_dict)
2385{
2386 int offset;
2387 int size;
2388 unsigned char buf[10];
2389 unsigned char *buf_end;
2390 unsigned char *p;
2391 cairo_status_t status;
2392
2393 /* Write private dict and update offset and size in top dict */
2394 font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output);
2395 status = cff_dict_write (private_dict, &font->output);
2396 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2397 return status;
2398
2399 size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
2400 /* private entry has two operands - size and offset */
2401 buf_end = encode_integer_max (buf, size);
2402 buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]);
2403 offset = cff_dict_get_location (parent_dict, PRIVATE_OP0x0012, &size);
2404 assert (offset > 0)((void) sizeof ((offset > 0) ? 1 : 0), __extension__ ({ if
(offset > 0) ; else __assert_fail ("offset > 0", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2404, __extension__ __PRETTY_FUNCTION__); }))
;
2405 p = _cairo_array_index (&font->output, offset);
2406 memcpy (p, buf, buf_end - buf);
2407
2408 return CAIRO_STATUS_SUCCESS;
2409}
2410
2411static cairo_status_t
2412cairo_cff_font_write_local_sub (cairo_cff_font_t *font,
2413 int dict_num,
2414 cairo_hash_table_t *private_dict,
2415 cairo_array_t *local_sub_index,
2416 cairo_bool_t *local_subs_used)
2417{
2418 int offset;
2419 int size;
2420 unsigned char buf[10];
2421 unsigned char *buf_end;
2422 unsigned char *p;
2423 cairo_status_t status;
2424 unsigned int i;
2425 unsigned char return_op = TYPE2_return0x000b;
2426
2427 if (_cairo_array_num_elements (local_sub_index) > 0) {
2428 /* Write local subroutines and update offset in private
2429 * dict. Local subroutines offset is relative to start of
2430 * private dict */
2431 offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
2432 buf_end = encode_integer_max (buf, offset);
2433 offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP0x0013, &size);
2434 assert (offset > 0)((void) sizeof ((offset > 0) ? 1 : 0), __extension__ ({ if
(offset > 0) ; else __assert_fail ("offset > 0", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-cff-subset.c"
, 2434, __extension__ __PRETTY_FUNCTION__); }))
;
2435 p = _cairo_array_index (&font->output, offset);
2436 memcpy (p, buf, buf_end - buf);
2437
2438 /* poppler and fontforge don't like zero length subroutines so
2439 * we replace unused subroutines with a 'return' instruction.
2440 */
2441 if (font->subset_subroutines) {
2442 for (i = 0; i < _cairo_array_num_elements (local_sub_index); i++) {
2443 if (! local_subs_used[i])
2444 cff_index_set_object (local_sub_index, i, &return_op, 1);
2445 }
2446 }
2447 status = cff_index_write (local_sub_index, &font->output);
2448 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2449 return status;
2450 }
2451
2452 return CAIRO_STATUS_SUCCESS;
2453}
2454
2455
2456static cairo_status_t
2457cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font)
2458{
2459 unsigned int i;
2460 cairo_int_status_t status;
2461
2462 if (font->is_cid) {
2463 for (i = 0; i < font->num_subset_fontdicts; i++) {
2464 status = cairo_cff_font_write_private_dict (
2465 font,
2466 i,
2467 font->fd_dict[font->fd_subset_map[i]],
2468 font->fd_private_dict[font->fd_subset_map[i]]);
2469 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2470 return status;
2471 }
2472
2473 for (i = 0; i < font->num_subset_fontdicts; i++) {
2474 status = cairo_cff_font_write_local_sub (
2475 font,
2476 i,
2477 font->fd_private_dict[font->fd_subset_map[i]],
2478 &font->fd_local_sub_index[font->fd_subset_map[i]],
2479 font->fd_local_subs_used[font->fd_subset_map[i]]);
2480 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2481 return status;
2482 }
2483 } else {
2484 status = cairo_cff_font_write_private_dict (font,
2485 0,
2486 font->fd_dict[0],
2487 font->private_dict);
2488 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2489 return status;
2490
2491 status = cairo_cff_font_write_local_sub (font,
2492 0,
2493 font->private_dict,
2494 &font->local_sub_index,
2495 font->local_subs_used);
2496 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2497 return status;
2498 }
2499
2500 return CAIRO_STATUS_SUCCESS;
2501}
2502
2503static cairo_status_t
2504cairo_cff_font_write_type1_private_dict_and_local_sub (cairo_cff_font_t *font)
2505{
2506 cairo_int_status_t status;
2507
2508 status = cairo_cff_font_write_private_dict (font,
2509 0,
2510 font->top_dict,
2511 font->private_dict);
2512 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2513 return status;
2514
2515 status = cairo_cff_font_write_local_sub (font,
2516 0,
2517 font->private_dict,
2518 &font->local_sub_index,
2519 font->local_subs_used);
2520 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2521 return status;
2522
2523 return CAIRO_STATUS_SUCCESS;
2524}
2525
2526
2527typedef cairo_status_t
2528(*font_write_t) (cairo_cff_font_t *font);
2529
2530static const font_write_t font_write_cid_funcs[] = {
2531 cairo_cff_font_write_header,
2532 cairo_cff_font_write_name,
2533 cairo_cff_font_write_top_dict,
2534 cairo_cff_font_write_strings,
2535 cairo_cff_font_write_global_subrs,
2536 cairo_cff_font_write_cid_charset,
2537 cairo_cff_font_write_fdselect,
2538 cairo_cff_font_write_charstrings,
2539 cairo_cff_font_write_cid_fontdict,
2540 cairo_cff_font_write_cid_private_dict_and_local_sub,
2541};
2542
2543static const font_write_t font_write_type1_funcs[] = {
2544 cairo_cff_font_write_header,
2545 cairo_cff_font_write_name,
2546 cairo_cff_font_write_top_dict,
2547 cairo_cff_font_write_strings,
2548 cairo_cff_font_write_global_subrs,
2549 cairo_cff_font_write_encoding,
2550 cairo_cff_font_write_type1_charset,
2551 cairo_cff_font_write_charstrings,
2552 cairo_cff_font_write_type1_private_dict_and_local_sub,
2553};
2554
2555static cairo_status_t
2556cairo_cff_font_write_subset (cairo_cff_font_t *font)
2557{
2558 cairo_int_status_t status;
2559 unsigned int i;
2560
2561 if (font->scaled_font_subset->is_latin) {
2562 for (i = 0; i < ARRAY_LENGTH (font_write_type1_funcs)((int) (sizeof (font_write_type1_funcs) / sizeof (font_write_type1_funcs
[0])))
; i++) {
2563 status = font_write_type1_funcs[i] (font);
2564 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2565 return status;
2566 }
2567 } else {
2568 for (i = 0; i < ARRAY_LENGTH (font_write_cid_funcs)((int) (sizeof (font_write_cid_funcs) / sizeof (font_write_cid_funcs
[0])))
; i++) {
2569 status = font_write_cid_funcs[i] (font);
2570 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2571 return status;
2572 }
2573 }
2574
2575 return CAIRO_STATUS_SUCCESS;
2576}
2577
2578static cairo_int_status_t
2579cairo_cff_font_generate (cairo_cff_font_t *font,
2580 const char **data,
2581 unsigned long *length)
2582{
2583 cairo_int_status_t status;
2584
2585 status = cairo_cff_font_read_font (font);
2586 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2587 return status;
2588
2589 /* If the PS name is not found, create a CairoFont-x-y name. */
2590 if (font->ps_name == NULL((void*)0)) {
2591 font->ps_name = _cairo_malloc (30)((30) != 0 ? malloc(30) : ((void*)0));
2592 if (unlikely (font->ps_name == NULL)(__builtin_expect (!!(font->ps_name == ((void*)0)), 0)))
2593 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2594
2595 snprintf(font->ps_name, 30, "CairoFont-%u-%u",
2596 font->scaled_font_subset->font_id,
2597 font->scaled_font_subset->subset_id);
2598 }
2599
2600 status = cairo_cff_font_subset_font (font);
2601 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2602 return status;
2603
2604 status = cairo_cff_font_write_subset (font);
2605 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2606 return status;
2607
2608
2609 *data = _cairo_array_index (&font->output, 0);
2610 *length = _cairo_array_num_elements (&font->output);
2611
2612 return CAIRO_STATUS_SUCCESS;
2613}
2614
2615static cairo_int_status_t
2616cairo_cff_font_create_set_widths (cairo_cff_font_t *font)
2617{
2618 unsigned long size;
2619 unsigned long long_entry_size;
2620 unsigned long short_entry_size;
2621 unsigned int i;
2622 tt_hhea_t hhea;
2623 int num_hmetrics;
2624 uint16_t short_entry;
2625 int glyph_index;
2626 cairo_int_status_t status;
2627
2628 size = sizeof (tt_hhea_t);
2629 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
2630 TT_TAG_hhea((int)((uint32_t)'h'<<24 | 'h'<<16 | 'e'<<8
| 'a'))
, 0,
2631 (unsigned char*) &hhea, &size);
2632 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2633 return status;
2634 num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
2635
2636 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
2637 glyph_index = font->scaled_font_subset->glyphs[i];
2638 long_entry_size = 2 * sizeof (int16_t);
2639 short_entry_size = sizeof (int16_t);
2640 if (glyph_index < num_hmetrics) {
2641 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
2642 TT_TAG_hmtx((int)((uint32_t)'h'<<24 | 'm'<<16 | 't'<<8
| 'x'))
,
2643 glyph_index * long_entry_size,
2644 (unsigned char *) &short_entry,
2645 &short_entry_size);
2646 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2647 return status;
2648 }
2649 else
2650 {
2651 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
2652 TT_TAG_hmtx((int)((uint32_t)'h'<<24 | 'm'<<16 | 't'<<8
| 'x'))
,
2653 (num_hmetrics - 1) * long_entry_size,
2654 (unsigned char *) &short_entry,
2655 &short_entry_size);
2656 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2657 return status;
2658 }
2659 font->widths[i] = be16_to_cpu (short_entry);
2660 }
2661
2662 return CAIRO_STATUS_SUCCESS;
2663}
2664
2665static cairo_bool_t
2666check_fontdata_is_cff (const unsigned char *data, long length)
2667{
2668 cff_header_t *header;
2669
2670 if (length < (long)sizeof (cff_header_t))
2671 return FALSE0;
2672
2673 header = (cff_header_t *) data;
2674 if (header->major == 1 &&
2675 header->minor == 0 &&
2676 header->header_size == 4)
2677 {
2678 return TRUE1;
2679 }
2680
2681 return FALSE0;
2682}
2683
2684static cairo_int_status_t
2685_cairo_cff_font_load_opentype_cff (cairo_cff_font_t *font)
2686{
2687 const cairo_scaled_font_backend_t *backend = font->backend;
2688 cairo_status_t status;
2689 tt_head_t head;
2690 tt_hhea_t hhea;
2691 unsigned long size, data_length;
2692
2693 if (!backend->load_truetype_table)
2694 return CAIRO_INT_STATUS_UNSUPPORTED;
2695
2696 data_length = 0;
2697 status = backend->load_truetype_table (font->scaled_font_subset->scaled_font,
2698 TT_TAG_CFF((int)((uint32_t)'C'<<24 | 'F'<<16 | 'F'<<8
| ' '))
, 0, NULL((void*)0), &data_length);
2699 if (status)
2700 return status;
2701
2702 size = sizeof (tt_head_t);
2703 status = backend->load_truetype_table (font->scaled_font_subset->scaled_font,
2704 TT_TAG_head((int)((uint32_t)'h'<<24 | 'e'<<16 | 'a'<<8
| 'd'))
, 0,
2705 (unsigned char *) &head, &size);
2706 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2707 return status;
2708
2709 size = sizeof (tt_hhea_t);
2710 status = backend->load_truetype_table (font->scaled_font_subset->scaled_font,
2711 TT_TAG_hhea((int)((uint32_t)'h'<<24 | 'h'<<16 | 'e'<<8
| 'a'))
, 0,
2712 (unsigned char *) &hhea, &size);
2713 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2714 return status;
2715
2716 size = 0;
2717 status = backend->load_truetype_table (font->scaled_font_subset->scaled_font,
2718 TT_TAG_hmtx((int)((uint32_t)'h'<<24 | 'm'<<16 | 't'<<8
| 'x'))
, 0, NULL((void*)0), &size);
2719 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2720 return status;
2721
2722 font->x_min = (int16_t) be16_to_cpu (head.x_min);
2723 font->y_min = (int16_t) be16_to_cpu (head.y_min);
2724 font->x_max = (int16_t) be16_to_cpu (head.x_max);
2725 font->y_max = (int16_t) be16_to_cpu (head.y_max);
2726 font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
2727 font->descent = (int16_t) be16_to_cpu (hhea.descender);
2728 font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
2729 if (font->units_per_em == 0)
2730 font->units_per_em = 1000;
2731
2732 font->font_name = NULL((void*)0);
2733 status = _cairo_truetype_read_font_name (font->scaled_font_subset->scaled_font,
2734 &font->ps_name,
2735 &font->font_name);
2736 if (_cairo_status_is_error (status)((status) != CAIRO_STATUS_SUCCESS && (status) < CAIRO_STATUS_LAST_STATUS
)
)
2737 return status;
2738
2739 font->is_opentype = TRUE1;
2740 font->data_length = data_length;
2741 font->data = _cairo_malloc (data_length)((data_length) != 0 ? malloc(data_length) : ((void*)0));
2742 if (unlikely (font->data == NULL)(__builtin_expect (!!(font->data == ((void*)0)), 0)))
2743 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2744
2745 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
2746 TT_TAG_CFF((int)((uint32_t)'C'<<24 | 'F'<<16 | 'F'<<8
| ' '))
, 0, font->data,
2747 &font->data_length);
2748 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2749 return status;
2750
2751 if (!check_fontdata_is_cff (font->data, data_length))
2752 return CAIRO_INT_STATUS_UNSUPPORTED;
2753
2754 return CAIRO_STATUS_SUCCESS;
2755}
2756
2757static cairo_int_status_t
2758_cairo_cff_font_load_cff (cairo_cff_font_t *font)
2759{
2760 const cairo_scaled_font_backend_t *backend = font->backend;
2761 cairo_status_t status;
2762 unsigned long data_length;
2763
2764 if (!backend->load_type1_data)
2765 return CAIRO_INT_STATUS_UNSUPPORTED;
2766
2767 data_length = 0;
2768 status = backend->load_type1_data (font->scaled_font_subset->scaled_font,
2769 0, NULL((void*)0), &data_length);
2770 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2771 return status;
2772
2773 font->font_name = NULL((void*)0);
2774 font->is_opentype = FALSE0;
2775 font->data_length = data_length;
2776 font->data = _cairo_malloc (data_length)((data_length) != 0 ? malloc(data_length) : ((void*)0));
2777 if (unlikely (font->data == NULL)(__builtin_expect (!!(font->data == ((void*)0)), 0)))
2778 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2779
2780 status = font->backend->load_type1_data (font->scaled_font_subset->scaled_font,
2781 0, font->data, &font->data_length);
2782 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2783 return status;
2784
2785 if (!check_fontdata_is_cff (font->data, data_length))
2786 return CAIRO_INT_STATUS_UNSUPPORTED;
2787
2788 return CAIRO_STATUS_SUCCESS;
2789}
2790
2791static cairo_int_status_t
2792_cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
2793 cairo_cff_font_t **font_return,
2794 const char *subset_name)
2795{
2796 const cairo_scaled_font_backend_t *backend;
2797 cairo_int_status_t status;
2798 cairo_bool_t is_synthetic;
2799 cairo_cff_font_t *font;
2800
2801 backend = scaled_font_subset->scaled_font->backend;
2802
2803 /* We need to use a fallback font if this font differs from the CFF outlines. */
2804 if (backend->is_synthetic) {
2805 status = backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic);
2806 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2807 return status;
2808
2809 if (is_synthetic)
2810 return CAIRO_INT_STATUS_UNSUPPORTED;
2811 }
2812
2813 font = calloc (1, sizeof (cairo_cff_font_t));
2814 if (unlikely (font == NULL)(__builtin_expect (!!(font == ((void*)0)), 0)))
2815 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2816
2817 font->backend = backend;
2818 font->scaled_font_subset = scaled_font_subset;
2819
2820 status = _cairo_cff_font_load_opentype_cff (font);
2821 if (status == CAIRO_INT_STATUS_UNSUPPORTED)
2822 status = _cairo_cff_font_load_cff (font);
2823 if (status)
2824 goto fail1;
2825
2826 font->data_end = font->data + font->data_length;
2827 _cairo_array_init (&font->output, sizeof (char));
2828 status = _cairo_array_grow_by (&font->output, 4096);
2829 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2830 goto fail2;
2831
2832 font->subset_font_name = strdup (subset_name);
2833 if (unlikely (font->subset_font_name == NULL)(__builtin_expect (!!(font->subset_font_name == ((void*)0)
), 0))
) {
2834 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2835 goto fail2;
2836 }
2837
2838 font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
2839 if (unlikely (font->widths == NULL)(__builtin_expect (!!(font->widths == ((void*)0)), 0))) {
2840 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2841 goto fail3;
2842 }
2843
2844 if (font->is_opentype) {
2845 status = cairo_cff_font_create_set_widths (font);
2846 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2847 goto fail4;
2848 }
2849
2850 status = cff_dict_init (&font->top_dict);
2851 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2852 goto fail4;
2853
2854 status = cff_dict_init (&font->private_dict);
2855 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2856 goto fail5;
2857
2858 cff_index_init (&font->strings_index);
2859 cff_index_init (&font->charstrings_index);
2860 cff_index_init (&font->global_sub_index);
2861 cff_index_init (&font->local_sub_index);
2862 cff_index_init (&font->charstrings_subset_index);
2863 cff_index_init (&font->strings_subset_index);
2864 font->euro_sid = 0;
2865 font->fdselect = NULL((void*)0);
2866 font->fd_dict = NULL((void*)0);
2867 font->fd_private_dict = NULL((void*)0);
2868 font->fd_local_sub_index = NULL((void*)0);
2869 font->fd_local_sub_bias = NULL((void*)0);
2870 font->fdselect_subset = NULL((void*)0);
2871 font->fd_subset_map = NULL((void*)0);
2872 font->private_dict_offset = NULL((void*)0);
2873 font->global_subs_used = NULL((void*)0);
2874 font->local_subs_used = NULL((void*)0);
2875 font->fd_local_subs_used = NULL((void*)0);
2876
2877 *font_return = font;
2878
2879 return CAIRO_STATUS_SUCCESS;
2880
2881fail5:
2882 _cairo_hash_table_destroy (font->top_dict);
2883fail4:
2884 free (font->widths);
2885fail3:
2886 free (font->subset_font_name);
2887fail2:
2888 free (font->ps_name);
2889 _cairo_array_fini (&font->output);
2890fail1:
2891 free (font->data);
2892 free (font->font_name);
2893 free (font);
2894
2895 return status;
2896}
2897
2898static void
2899cairo_cff_font_destroy (cairo_cff_font_t *font)
2900{
2901 unsigned int i;
2902
2903 free (font->widths);
2904 free (font->font_name);
2905 free (font->ps_name);
2906 free (font->subset_font_name);
2907 _cairo_array_fini (&font->output);
2908 cff_dict_fini (font->top_dict);
2909 cff_dict_fini (font->private_dict);
2910 cff_index_fini (&font->strings_index);
2911 cff_index_fini (&font->charstrings_index);
2912 cff_index_fini (&font->global_sub_index);
2913 cff_index_fini (&font->local_sub_index);
2914 cff_index_fini (&font->charstrings_subset_index);
2915 cff_index_fini (&font->strings_subset_index);
2916
2917 /* If we bailed out early as a result of an error some of the
2918 * following cairo_cff_font_t members may still be NULL */
2919 if (font->fd_dict) {
2920 for (i = 0; i < font->num_fontdicts; i++) {
2921 if (font->fd_dict[i])
2922 cff_dict_fini (font->fd_dict[i]);
2923 }
2924 free (font->fd_dict);
2925 }
2926 free (font->global_subs_used);
2927 free (font->local_subs_used);
2928 free (font->fd_subset_map);
2929 free (font->private_dict_offset);
2930
2931 if (font->is_cid) {
2932 free (font->fdselect);
2933 free (font->fdselect_subset);
2934 if (font->fd_private_dict) {
2935 for (i = 0; i < font->num_fontdicts; i++) {
2936 if (font->fd_private_dict[i])
2937 cff_dict_fini (font->fd_private_dict[i]);
2938 }
2939 free (font->fd_private_dict);
2940 }
2941 if (font->fd_local_sub_index) {
2942 for (i = 0; i < font->num_fontdicts; i++)
2943 cff_index_fini (&font->fd_local_sub_index[i]);
2944 free (font->fd_local_sub_index);
2945 }
2946 free (font->fd_local_sub_bias);
2947 if (font->fd_local_subs_used) {
2948 for (i = 0; i < font->num_fontdicts; i++) {
2949 free (font->fd_local_subs_used[i]);
2950 }
2951 free (font->fd_local_subs_used);
2952 }
2953 free (font->fd_default_width);
2954 free (font->fd_nominal_width);
2955 }
2956
2957 free (font->data);
2958
2959 free (font);
2960}
2961
2962cairo_status_t
2963_cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
2964 const char *subset_name,
2965 cairo_scaled_font_subset_t *font_subset)
2966{
2967 cairo_cff_font_t *font = NULL((void*)0); /* squelch bogus compiler warning */
2968 cairo_status_t status;
2969 const char *data = NULL((void*)0); /* squelch bogus compiler warning */
2970 unsigned long length = 0; /* squelch bogus compiler warning */
2971 unsigned int i;
2972
2973 status = _cairo_cff_font_create (font_subset, &font, subset_name);
2974 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2975 return status;
2976
2977 status = cairo_cff_font_generate (font, &data, &length);
2978 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2979 goto fail1;
2980
2981 cff_subset->ps_name = strdup (font->ps_name);
2982 if (unlikely (cff_subset->ps_name == NULL)(__builtin_expect (!!(cff_subset->ps_name == ((void*)0)), 0
))
) {
2983 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2984 goto fail1;
2985 }
2986
2987 if (font->font_name) {
2988 cff_subset->family_name_utf8 = strdup (font->font_name);
2989 if (cff_subset->family_name_utf8 == NULL((void*)0)) {
2990 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2991 goto fail2;
2992 }
2993 } else {
2994 cff_subset->family_name_utf8 = NULL((void*)0);
2995 }
2996
2997 cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
2998 if (unlikely (cff_subset->widths == NULL)(__builtin_expect (!!(cff_subset->widths == ((void*)0)), 0
))
) {
2999 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3000 goto fail3;
3001 }
3002 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
3003 cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em;
3004
3005 cff_subset->x_min = (double)font->x_min/font->units_per_em;
3006 cff_subset->y_min = (double)font->y_min/font->units_per_em;
3007 cff_subset->x_max = (double)font->x_max/font->units_per_em;
3008 cff_subset->y_max = (double)font->y_max/font->units_per_em;
3009 cff_subset->ascent = (double)font->ascent/font->units_per_em;
3010 cff_subset->descent = (double)font->descent/font->units_per_em;
3011
3012 cff_subset->data = _cairo_malloc (length)((length) != 0 ? malloc(length) : ((void*)0));
3013 if (unlikely (cff_subset->data == NULL)(__builtin_expect (!!(cff_subset->data == ((void*)0)), 0))) {
3014 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3015 goto fail4;
3016 }
3017
3018 memcpy (cff_subset->data, data, length);
3019 cff_subset->data_length = length;
3020
3021 cairo_cff_font_destroy (font);
3022
3023 return CAIRO_STATUS_SUCCESS;
3024
3025 fail4:
3026 free (cff_subset->widths);
3027 fail3:
3028 free (cff_subset->family_name_utf8);
3029 fail2:
3030 free (cff_subset->ps_name);
3031 fail1:
3032 cairo_cff_font_destroy (font);
3033
3034 return status;
3035}
3036
3037void
3038_cairo_cff_subset_fini (cairo_cff_subset_t *subset)
3039{
3040 free (subset->ps_name);
3041 free (subset->family_name_utf8);
3042 free (subset->widths);
3043 free (subset->data);
3044}
3045
3046cairo_bool_t
3047_cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font)
3048{
3049 const cairo_scaled_font_backend_t *backend;
3050 cairo_int_status_t status;
3051 unsigned char *data;
3052 unsigned long data_length;
3053 unsigned char *current_ptr;
3054 unsigned char *data_end;
3055 cff_header_t *header;
3056 cff_index_element_t *element;
3057 cairo_hash_table_t *top_dict;
3058 cairo_array_t index;
3059 int size;
3060 cairo_bool_t is_cid = FALSE0;
3061
3062 backend = scaled_font->backend;
3063 data = NULL((void*)0);
3064 data_length = 0;
3065 status = CAIRO_INT_STATUS_UNSUPPORTED;
3066 /* Try to load an OpenType/CFF font */
3067 if (backend->load_truetype_table &&
3068 (status = backend->load_truetype_table (scaled_font, TT_TAG_CFF((int)((uint32_t)'C'<<24 | 'F'<<16 | 'F'<<8
| ' '))
,
3069 0, NULL((void*)0), &data_length)) == CAIRO_INT_STATUS_SUCCESS)
3070 {
3071 data = _cairo_malloc (data_length)((data_length) != 0 ? malloc(data_length) : ((void*)0));
3072 if (unlikely (data == NULL)(__builtin_expect (!!(data == ((void*)0)), 0))) {
3073 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3074 return FALSE0;
3075 }
3076
3077 status = backend->load_truetype_table (scaled_font, TT_TAG_CFF((int)((uint32_t)'C'<<24 | 'F'<<16 | 'F'<<8
| ' '))
,
3078 0, data, &data_length);
3079 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3080 goto fail1;
3081 }
3082 /* Try to load a CFF font */
3083 if (status == CAIRO_INT_STATUS_UNSUPPORTED &&
3084 backend->load_type1_data &&
3085 (status = backend->load_type1_data (scaled_font,
3086 0, NULL((void*)0), &data_length)) == CAIRO_INT_STATUS_SUCCESS)
3087 {
3088 data = _cairo_malloc (data_length)((data_length) != 0 ? malloc(data_length) : ((void*)0));
3089 if (unlikely (data == NULL)(__builtin_expect (!!(data == ((void*)0)), 0))) {
3090 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3091 return FALSE0;
3092 }
3093
3094 status = backend->load_type1_data (scaled_font, 0, data, &data_length);
3095 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3096 goto fail1;
3097 }
3098 if (status)
3099 goto fail1;
3100
3101 /* Check if it looks like a CFF font */
3102 if (!check_fontdata_is_cff (data, data_length))
3103 goto fail1;
3104
3105 data_end = data + data_length;
3106
3107 /* skip header */
3108 if (data_length < sizeof (cff_header_t))
3109 goto fail1;
3110
3111 header = (cff_header_t *) data;
3112 current_ptr = data + header->header_size;
3113
3114 /* skip name */
3115 cff_index_init (&index);
3116 status = cff_index_read (&index, &current_ptr, data_end);
3117 cff_index_fini (&index);
3118
3119 if (status)
3120 goto fail1;
3121
3122 /* read top dict */
3123 cff_index_init (&index);
3124 status = cff_index_read (&index, &current_ptr, data_end);
3125 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3126 goto fail2;
3127
3128 status = cff_dict_init (&top_dict);
3129 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3130 goto fail2;
3131
3132 element = _cairo_array_index (&index, 0);
3133 if (element == NULL((void*)0))
3134 goto fail3;
3135 status = cff_dict_read (top_dict, element->data, element->length);
3136 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3137 goto fail3;
3138
3139 /* check for ROS operator indicating a CID font */
3140 if (cff_dict_get_operands (top_dict, ROS_OP0x0c1e, &size) != NULL((void*)0))
3141 is_cid = TRUE1;
3142
3143fail3:
3144 cff_dict_fini (top_dict);
3145
3146fail2:
3147 cff_index_fini (&index);
3148
3149fail1:
3150 free (data);
3151
3152 return is_cid;
3153}
3154
3155static cairo_int_status_t
3156_cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset,
3157 cairo_cff_font_t **font_return,
3158 const char *subset_name)
3159{
3160 cairo_status_t status;
3161 cairo_cff_font_t *font;
3162
3163 font = calloc (1, sizeof (cairo_cff_font_t));
3164 if (unlikely (font == NULL)(__builtin_expect (!!(font == ((void*)0)), 0)))
3165 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3166
3167 font->backend = NULL((void*)0);
3168 font->scaled_font_subset = scaled_font_subset;
3169
3170 _cairo_array_init (&font->output, sizeof (char));
3171 status = _cairo_array_grow_by (&font->output, 4096);
3172 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3173 goto fail1;
3174
3175 font->subset_font_name = strdup (subset_name);
3176 if (unlikely (font->subset_font_name == NULL)(__builtin_expect (!!(font->subset_font_name == ((void*)0)
), 0))
) {
3177 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3178 goto fail1;
3179 }
3180
3181 font->ps_name = strdup (subset_name);
3182 if (unlikely (font->ps_name == NULL)(__builtin_expect (!!(font->ps_name == ((void*)0)), 0))) {
3183 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3184 goto fail2;
3185 }
3186 font->font_name = NULL((void*)0);
3187
3188 font->x_min = 0;
3189 font->y_min = 0;
3190 font->x_max = 0;
3191 font->y_max = 0;
3192 font->ascent = 0;
3193 font->descent = 0;
3194
3195 font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
3196 if (unlikely (font->widths == NULL)(__builtin_expect (!!(font->widths == ((void*)0)), 0))) {
3197 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3198 goto fail3;
3199 }
3200
3201 font->data_length = 0;
3202 font->data = NULL((void*)0);
3203 font->data_end = NULL((void*)0);
3204
3205 status = cff_dict_init (&font->top_dict);
3206 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3207 goto fail4;
3208
3209 status = cff_dict_init (&font->private_dict);
3210 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3211 goto fail5;
3212
3213 cff_index_init (&font->strings_index);
3214 cff_index_init (&font->charstrings_index);
3215 cff_index_init (&font->global_sub_index);
3216 cff_index_init (&font->local_sub_index);
3217 cff_index_init (&font->charstrings_subset_index);
3218 cff_index_init (&font->strings_subset_index);
3219 font->global_subs_used = NULL((void*)0);
3220 font->local_subs_used = NULL((void*)0);
3221 font->subset_subroutines = FALSE0;
3222 font->fdselect = NULL((void*)0);
3223 font->fd_dict = NULL((void*)0);
3224 font->fd_private_dict = NULL((void*)0);
3225 font->fd_local_sub_index = NULL((void*)0);
3226 font->fdselect_subset = NULL((void*)0);
3227 font->fd_subset_map = NULL((void*)0);
3228 font->private_dict_offset = NULL((void*)0);
3229
3230 *font_return = font;
3231
3232 return CAIRO_STATUS_SUCCESS;
3233
3234fail5:
3235 _cairo_hash_table_destroy (font->top_dict);
3236fail4:
3237 free (font->widths);
3238fail3:
3239 free (font->font_name);
3240 free (font->ps_name);
3241fail2:
3242 free (font->subset_font_name);
3243fail1:
3244 _cairo_array_fini (&font->output);
3245 free (font);
3246 return status;
3247}
3248
3249static cairo_int_status_t
3250cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
3251 cairo_type2_charstrings_t *type2_subset,
3252 const char **data,
3253 unsigned long *length)
3254{
3255 cairo_int_status_t status;
3256 cff_header_t header;
3257 cairo_array_t *charstring;
3258 unsigned char buf[40];
3259 unsigned char *end_buf, *end_buf2;
3260 unsigned int i;
3261 int sid;
3262
3263 /* Create header */
3264 header.major = 1;
3265 header.minor = 0;
3266 header.header_size = 4;
3267 header.offset_size = 4;
3268 font->header = &header;
3269
3270 /* Create Top Dict */
3271 font->is_cid = FALSE0;
3272
3273 snprintf((char*)buf, sizeof(buf), "CairoFont-%u-%u",
3274 font->scaled_font_subset->font_id,
3275 font->scaled_font_subset->subset_id);
3276 sid = NUM_STD_STRINGS391 + _cairo_array_num_elements (&font->strings_subset_index);
3277 status = cff_index_append_copy (&font->strings_subset_index,
3278 (unsigned char *)buf,
3279 strlen((char*)buf));
3280 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3281 return status;
3282
3283 end_buf = encode_integer (buf, sid);
3284 status = cff_dict_set_operands (font->top_dict, FULLNAME_OP0x0002,
3285 buf, end_buf - buf);
3286 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3287 return status;
3288
3289 status = cff_dict_set_operands (font->top_dict, FAMILYNAME_OP0x0003,
3290 buf, end_buf - buf);
3291 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3292 return status;
3293
3294 end_buf = encode_integer (buf, type2_subset->x_min);
3295 end_buf = encode_integer (end_buf, type2_subset->y_min);
3296 end_buf = encode_integer (end_buf, type2_subset->x_max);
3297 end_buf = encode_integer (end_buf, type2_subset->y_max);
3298 status = cff_dict_set_operands (font->top_dict,
3299 FONTBBOX_OP0x0005, buf, end_buf - buf);
3300 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3301 return status;
3302
3303 end_buf = encode_integer_max (buf, 0);
3304 status = cff_dict_set_operands (font->top_dict,
3305 CHARSTRINGS_OP0x0011, buf, end_buf - buf);
3306 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3307 return status;
3308
3309
3310 if (font->scaled_font_subset->is_latin) {
3311 status = cff_dict_set_operands (font->top_dict,
3312 ENCODING_OP0x0010, buf, end_buf - buf);
3313 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3314 return status;
3315
3316 /* Private has two operands - size and offset */
3317 end_buf2 = encode_integer_max (end_buf, 0);
3318 cff_dict_set_operands (font->top_dict, PRIVATE_OP0x0012, buf, end_buf2 - buf);
3319 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3320 return status;
3321
3322 } else {
3323 status = cff_dict_set_operands (font->top_dict,
3324 FDSELECT_OP0x0c25, buf, end_buf - buf);
3325 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3326 return status;
3327
3328 status = cff_dict_set_operands (font->top_dict,
3329 FDARRAY_OP0x0c24, buf, end_buf - buf);
3330 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3331 return status;
3332 }
3333
3334 status = cff_dict_set_operands (font->top_dict,
3335 CHARSET_OP0x000f, buf, end_buf - buf);
3336 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3337 return status;
3338
3339 if (!font->scaled_font_subset->is_latin) {
3340 status = cairo_cff_font_set_ros_strings (font);
3341 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3342 return status;
3343
3344 /* Create CID FD dictionary */
3345 status = cairo_cff_font_create_cid_fontdict (font);
3346 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3347 return status;
3348 } else {
3349 font->private_dict_offset = _cairo_malloc (sizeof (int))((sizeof (int)) != 0 ? malloc(sizeof (int)) : ((void*)0));
3350 if (unlikely (font->private_dict_offset == NULL)(__builtin_expect (!!(font->private_dict_offset == ((void*
)0)), 0))
)
3351 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3352 }
3353
3354 /* Create charstrings */
3355 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
3356 charstring = _cairo_array_index(&type2_subset->charstrings, i);
3357
3358 status = cff_index_append (&font->charstrings_subset_index,
3359 _cairo_array_index (charstring, 0),
3360 _cairo_array_num_elements (charstring));
3361
3362 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3363 return status;
3364 }
3365
3366 if (font->scaled_font_subset->is_latin)
3367 status = cairo_cff_font_add_euro_charset_string (font);
Value stored to 'status' is never read
3368
3369 status = cairo_cff_font_write_subset (font);
3370 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3371 return status;
3372
3373 *data = _cairo_array_index (&font->output, 0);
3374 *length = _cairo_array_num_elements (&font->output);
3375
3376 return CAIRO_STATUS_SUCCESS;
3377}
3378
3379cairo_status_t
3380_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
3381 const char *subset_name,
3382 cairo_scaled_font_subset_t *font_subset)
3383{
3384 cairo_cff_font_t *font = NULL((void*)0); /* squelch bogus compiler warning */
3385 cairo_status_t status;
3386 const char *data = NULL((void*)0); /* squelch bogus compiler warning */
3387 unsigned long length = 0; /* squelch bogus compiler warning */
3388 unsigned int i;
3389 cairo_type2_charstrings_t type2_subset;
3390
3391 status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
3392 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3393 return status;
3394
3395 status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
3396 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3397 goto fail1;
3398
3399 status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
3400 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3401 goto fail2;
3402
3403 cff_subset->family_name_utf8 = NULL((void*)0);
3404 cff_subset->ps_name = strdup (font->ps_name);
3405 if (unlikely (cff_subset->ps_name == NULL)(__builtin_expect (!!(cff_subset->ps_name == ((void*)0)), 0
))
) {
3406 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3407 goto fail2;
3408 }
3409
3410 cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
3411 if (unlikely (cff_subset->widths == NULL)(__builtin_expect (!!(cff_subset->widths == ((void*)0)), 0
))
) {
3412 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3413 goto fail3;
3414 }
3415
3416 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
3417 cff_subset->widths[i] = (double)type2_subset.widths[i]/1000;
3418
3419 cff_subset->x_min = (double)type2_subset.x_min/1000;
3420 cff_subset->y_min = (double)type2_subset.y_min/1000;
3421 cff_subset->x_max = (double)type2_subset.x_max/1000;
3422 cff_subset->y_max = (double)type2_subset.y_max/1000;
3423 cff_subset->ascent = (double)type2_subset.y_max/1000;
3424 cff_subset->descent = (double)type2_subset.y_min/1000;
3425
3426 cff_subset->data = _cairo_malloc (length)((length) != 0 ? malloc(length) : ((void*)0));
3427 if (unlikely (cff_subset->data == NULL)(__builtin_expect (!!(cff_subset->data == ((void*)0)), 0))) {
3428 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3429 goto fail4;
3430 }
3431
3432 memcpy (cff_subset->data, data, length);
3433 cff_subset->data_length = length;
3434
3435 _cairo_type2_charstrings_fini (&type2_subset);
3436 cairo_cff_font_destroy (font);
3437
3438 return CAIRO_STATUS_SUCCESS;
3439
3440 fail4:
3441 free (cff_subset->widths);
3442 fail3:
3443 free (cff_subset->ps_name);
3444 fail2:
3445 _cairo_type2_charstrings_fini (&type2_subset);
3446 fail1:
3447 cairo_cff_font_destroy (font);
3448
3449 return status;
3450}
3451
3452void
3453_cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
3454{
3455 free (subset->ps_name);
3456 free (subset->widths);
3457 free (subset->data);
3458}
3459
3460#endif /* CAIRO_HAS_FONT_SUBSET */