Line data Source code
1 : /* cairo - a vector graphics library with display and print output
2 : *
3 : * Copyright © 2006 Adrian Johnson
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it either under the terms of the GNU Lesser General Public
7 : * License version 2.1 as published by the Free Software Foundation
8 : * (the "LGPL") or, at your option, under the terms of the Mozilla
9 : * Public License Version 1.1 (the "MPL"). If you do not alter this
10 : * notice, a recipient may use your version of this file under either
11 : * the MPL or the LGPL.
12 : *
13 : * You should have received a copy of the LGPL along with this library
14 : * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 : * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 : * You should have received a copy of the MPL along with this library
17 : * in the file COPYING-MPL-1.1
18 : *
19 : * The contents of this file are subject to the Mozilla Public License
20 : * Version 1.1 (the "License"); you may not use this file except in
21 : * compliance with the License. You may obtain a copy of the License at
22 : * http://www.mozilla.org/MPL/
23 : *
24 : * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 : * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 : * the specific language governing rights and limitations.
27 : *
28 : * The Original Code is the cairo graphics library.
29 : *
30 : * The Initial Developer of the Original Code is Adrian Johnson.
31 : *
32 : * Contributor(s):
33 : * Adrian Johnson <ajohnson@redneon.com>
34 : * Eugeniy Meshcheryakov <eugen@debian.org>
35 : */
36 :
37 : /*
38 : * Useful links:
39 : * http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf
40 : */
41 :
42 : #define _BSD_SOURCE /* for snprintf(), strdup() */
43 : #include "cairoint.h"
44 : #include "cairo-error-private.h"
45 :
46 : #if CAIRO_HAS_FONT_SUBSET
47 :
48 : #include "cairo-scaled-font-subsets-private.h"
49 : #include "cairo-truetype-subset-private.h"
50 : #include <string.h>
51 :
52 : /* CFF Dict Operators. If the high byte is 0 the command is encoded
53 : * with a single byte. */
54 : #define BASEFONTNAME_OP 0x0c16
55 : #define CIDCOUNT_OP 0x0c22
56 : #define CHARSET_OP 0x000f
57 : #define CHARSTRINGS_OP 0x0011
58 : #define COPYRIGHT_OP 0x0c00
59 : #define ENCODING_OP 0x0010
60 : #define FAMILYNAME_OP 0x0003
61 : #define FDARRAY_OP 0x0c24
62 : #define FDSELECT_OP 0x0c25
63 : #define FONTBBOX_OP 0x0005
64 : #define FONTNAME_OP 0x0c26
65 : #define FULLNAME_OP 0x0002
66 : #define LOCAL_SUB_OP 0x0013
67 : #define NOTICE_OP 0x0001
68 : #define POSTSCRIPT_OP 0x0c15
69 : #define PRIVATE_OP 0x0012
70 : #define ROS_OP 0x0c1e
71 : #define UNIQUEID_OP 0x000d
72 : #define VERSION_OP 0x0000
73 : #define WEIGHT_OP 0x0004
74 : #define XUID_OP 0x000e
75 :
76 : #define NUM_STD_STRINGS 391
77 :
78 : typedef struct _cff_header {
79 : uint8_t major;
80 : uint8_t minor;
81 : uint8_t header_size;
82 : uint8_t offset_size;
83 : } cff_header_t;
84 :
85 : typedef struct _cff_index_element {
86 : cairo_bool_t is_copy;
87 : unsigned char *data;
88 : int length;
89 : } cff_index_element_t;
90 :
91 : typedef struct _cff_dict_operator {
92 : cairo_hash_entry_t base;
93 :
94 : unsigned short operator;
95 : unsigned char *operand;
96 : int operand_length;
97 : int operand_offset;
98 : } cff_dict_operator_t;
99 :
100 : typedef struct _cairo_cff_font {
101 :
102 : cairo_scaled_font_subset_t *scaled_font_subset;
103 : const cairo_scaled_font_backend_t *backend;
104 :
105 : /* Font Data */
106 : unsigned char *data;
107 : unsigned long data_length;
108 : unsigned char *current_ptr;
109 : unsigned char *data_end;
110 : cff_header_t *header;
111 : char *font_name;
112 : char *ps_name;
113 : cairo_hash_table_t *top_dict;
114 : cairo_hash_table_t *private_dict;
115 : cairo_array_t strings_index;
116 : cairo_array_t charstrings_index;
117 : cairo_array_t global_sub_index;
118 : cairo_array_t local_sub_index;
119 : int num_glyphs;
120 : cairo_bool_t is_cid;
121 : int units_per_em;
122 :
123 : /* CID Font Data */
124 : int *fdselect;
125 : unsigned int num_fontdicts;
126 : cairo_hash_table_t **fd_dict;
127 : cairo_hash_table_t **fd_private_dict;
128 : cairo_array_t *fd_local_sub_index;
129 :
130 : /* Subsetted Font Data */
131 : char *subset_font_name;
132 : cairo_array_t charstrings_subset_index;
133 : cairo_array_t strings_subset_index;
134 : int *fdselect_subset;
135 : unsigned int num_subset_fontdicts;
136 : int *fd_subset_map;
137 : int *private_dict_offset;
138 : cairo_array_t output;
139 :
140 : /* Subset Metrics */
141 : int *widths;
142 : int x_min, y_min, x_max, y_max;
143 : int ascent, descent;
144 :
145 : } cairo_cff_font_t;
146 :
147 : /* Encoded integer using maximum sized encoding. This is required for
148 : * operands that are later modified after encoding. */
149 : static unsigned char *
150 0 : encode_integer_max (unsigned char *p, int i)
151 : {
152 0 : *p++ = 29;
153 0 : *p++ = i >> 24;
154 0 : *p++ = (i >> 16) & 0xff;
155 0 : *p++ = (i >> 8) & 0xff;
156 0 : *p++ = i & 0xff;
157 0 : return p;
158 : }
159 :
160 : static unsigned char *
161 0 : encode_integer (unsigned char *p, int i)
162 : {
163 0 : if (i >= -107 && i <= 107) {
164 0 : *p++ = i + 139;
165 0 : } else if (i >= 108 && i <= 1131) {
166 0 : i -= 108;
167 0 : *p++ = (i >> 8)+ 247;
168 0 : *p++ = i & 0xff;
169 0 : } else if (i >= -1131 && i <= -108) {
170 0 : i = -i - 108;
171 0 : *p++ = (i >> 8)+ 251;
172 0 : *p++ = i & 0xff;
173 0 : } else if (i >= -32768 && i <= 32767) {
174 0 : *p++ = 28;
175 0 : *p++ = (i >> 8) & 0xff;
176 0 : *p++ = i & 0xff;
177 : } else {
178 0 : p = encode_integer_max (p, i);
179 : }
180 0 : return p;
181 : }
182 :
183 : static unsigned char *
184 0 : decode_integer (unsigned char *p, int *integer)
185 : {
186 0 : if (*p == 28) {
187 0 : *integer = (int)(p[1]<<8 | p[2]);
188 0 : p += 3;
189 0 : } else if (*p == 29) {
190 0 : *integer = (int)((p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]);
191 0 : p += 5;
192 0 : } else if (*p >= 32 && *p <= 246) {
193 0 : *integer = *p++ - 139;
194 0 : } else if (*p <= 250) {
195 0 : *integer = (p[0] - 247) * 256 + p[1] + 108;
196 0 : p += 2;
197 0 : } else if (*p <= 254) {
198 0 : *integer = -(p[0] - 251) * 256 - p[1] - 108;
199 0 : p += 2;
200 : } else {
201 0 : *integer = 0;
202 0 : p += 1;
203 : }
204 0 : return p;
205 : }
206 :
207 : static unsigned char *
208 0 : decode_operator (unsigned char *p, unsigned short *operator)
209 : {
210 0 : unsigned short op = 0;
211 :
212 0 : op = *p++;
213 0 : if (op == 12) {
214 0 : op <<= 8;
215 0 : op |= *p++;
216 : }
217 0 : *operator = op;
218 0 : return p;
219 : }
220 :
221 : /* return 0 if not an operand */
222 : static int
223 0 : operand_length (unsigned char *p)
224 : {
225 0 : unsigned char *begin = p;
226 :
227 0 : if (*p == 28)
228 0 : return 3;
229 :
230 0 : if (*p == 29)
231 0 : return 5;
232 :
233 0 : if (*p >= 32 && *p <= 246)
234 0 : return 1;
235 :
236 0 : if (*p >= 247 && *p <= 254)
237 0 : return 2;
238 :
239 0 : if (*p == 30) {
240 0 : while ((*p & 0x0f) != 0x0f)
241 0 : p++;
242 0 : return p - begin + 1;
243 : }
244 :
245 0 : return 0;
246 : }
247 :
248 : static unsigned char *
249 0 : encode_index_offset (unsigned char *p, int offset_size, unsigned long offset)
250 : {
251 0 : while (--offset_size >= 0) {
252 0 : p[offset_size] = (unsigned char) (offset & 0xff);
253 0 : offset >>= 8;
254 : }
255 0 : return p + offset_size;
256 : }
257 :
258 : static unsigned long
259 0 : decode_index_offset(unsigned char *p, int off_size)
260 : {
261 0 : unsigned long offset = 0;
262 :
263 0 : while (off_size-- > 0)
264 0 : offset = offset*256 + *p++;
265 0 : return offset;
266 : }
267 :
268 : static void
269 0 : cff_index_init (cairo_array_t *index)
270 : {
271 0 : _cairo_array_init (index, sizeof (cff_index_element_t));
272 0 : }
273 :
274 : static cairo_int_status_t
275 0 : cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_ptr)
276 : {
277 : cff_index_element_t element;
278 : unsigned char *data, *p;
279 : cairo_status_t status;
280 : int offset_size, count, start, i;
281 0 : int end = 0;
282 :
283 0 : p = *ptr;
284 0 : if (p + 2 > end_ptr)
285 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
286 0 : count = be16_to_cpu( *((uint16_t *)p) );
287 0 : p += 2;
288 0 : if (count > 0) {
289 0 : offset_size = *p++;
290 0 : if (p + (count + 1)*offset_size > end_ptr)
291 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
292 0 : data = p + offset_size*(count + 1) - 1;
293 0 : start = decode_index_offset (p, offset_size);
294 0 : p += offset_size;
295 0 : for (i = 0; i < count; i++) {
296 0 : end = decode_index_offset (p, offset_size);
297 0 : p += offset_size;
298 0 : if (p > end_ptr)
299 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
300 0 : element.length = end - start;
301 0 : element.is_copy = FALSE;
302 0 : element.data = data + start;
303 0 : status = _cairo_array_append (index, &element);
304 0 : if (unlikely (status))
305 0 : return status;
306 0 : start = end;
307 : }
308 0 : p = data + end;
309 : }
310 0 : *ptr = p;
311 :
312 0 : return CAIRO_STATUS_SUCCESS;
313 : }
314 :
315 : static cairo_status_t
316 0 : cff_index_write (cairo_array_t *index, cairo_array_t *output)
317 : {
318 : int offset_size;
319 : int offset;
320 : int num_elem;
321 : int i;
322 : cff_index_element_t *element;
323 : uint16_t count;
324 : unsigned char buf[5];
325 : cairo_status_t status;
326 :
327 0 : num_elem = _cairo_array_num_elements (index);
328 0 : count = cpu_to_be16 ((uint16_t) num_elem);
329 0 : status = _cairo_array_append_multiple (output, &count, 2);
330 0 : if (unlikely (status))
331 0 : return status;
332 :
333 0 : if (num_elem == 0)
334 0 : return CAIRO_STATUS_SUCCESS;
335 :
336 : /* Find maximum offset to determine offset size */
337 0 : offset = 1;
338 0 : for (i = 0; i < num_elem; i++) {
339 0 : element = _cairo_array_index (index, i);
340 0 : offset += element->length;
341 : }
342 0 : if (offset < 0x100)
343 0 : offset_size = 1;
344 0 : else if (offset < 0x10000)
345 0 : offset_size = 2;
346 0 : else if (offset < 0x1000000)
347 0 : offset_size = 3;
348 : else
349 0 : offset_size = 4;
350 :
351 0 : buf[0] = (unsigned char) offset_size;
352 0 : status = _cairo_array_append (output, buf);
353 0 : if (unlikely (status))
354 0 : return status;
355 :
356 0 : offset = 1;
357 0 : encode_index_offset (buf, offset_size, offset);
358 0 : status = _cairo_array_append_multiple (output, buf, offset_size);
359 0 : if (unlikely (status))
360 0 : return status;
361 :
362 0 : for (i = 0; i < num_elem; i++) {
363 0 : element = _cairo_array_index (index, i);
364 0 : offset += element->length;
365 0 : encode_index_offset (buf, offset_size, offset);
366 0 : status = _cairo_array_append_multiple (output, buf, offset_size);
367 0 : if (unlikely (status))
368 0 : return status;
369 : }
370 :
371 0 : for (i = 0; i < num_elem; i++) {
372 0 : element = _cairo_array_index (index, i);
373 0 : status = _cairo_array_append_multiple (output,
374 0 : element->data,
375 : element->length);
376 0 : if (unlikely (status))
377 0 : return status;
378 : }
379 0 : return CAIRO_STATUS_SUCCESS;
380 : }
381 :
382 : static cairo_status_t
383 0 : cff_index_append (cairo_array_t *index, unsigned char *object , int length)
384 : {
385 : cff_index_element_t element;
386 :
387 0 : element.length = length;
388 0 : element.is_copy = FALSE;
389 0 : element.data = object;
390 :
391 0 : return _cairo_array_append (index, &element);
392 : }
393 :
394 : static cairo_status_t
395 0 : cff_index_append_copy (cairo_array_t *index,
396 : const unsigned char *object,
397 : unsigned int length)
398 : {
399 : cff_index_element_t element;
400 : cairo_status_t status;
401 :
402 0 : element.length = length;
403 0 : element.is_copy = TRUE;
404 0 : element.data = malloc (element.length);
405 0 : if (unlikely (element.data == NULL))
406 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
407 :
408 0 : memcpy (element.data, object, element.length);
409 :
410 0 : status = _cairo_array_append (index, &element);
411 0 : if (unlikely (status)) {
412 0 : free (element.data);
413 0 : return status;
414 : }
415 :
416 0 : return CAIRO_STATUS_SUCCESS;
417 : }
418 :
419 : static void
420 0 : cff_index_fini (cairo_array_t *index)
421 : {
422 : cff_index_element_t *element;
423 : int i;
424 :
425 0 : for (i = 0; i < _cairo_array_num_elements (index); i++) {
426 0 : element = _cairo_array_index (index, i);
427 0 : if (element->is_copy)
428 0 : free (element->data);
429 : }
430 0 : _cairo_array_fini (index);
431 0 : }
432 :
433 : static cairo_bool_t
434 0 : _cairo_cff_dict_equal (const void *key_a, const void *key_b)
435 : {
436 0 : const cff_dict_operator_t *op_a = key_a;
437 0 : const cff_dict_operator_t *op_b = key_b;
438 :
439 0 : return op_a->operator == op_b->operator;
440 : }
441 :
442 : static cairo_status_t
443 0 : cff_dict_init (cairo_hash_table_t **dict)
444 : {
445 0 : *dict = _cairo_hash_table_create (_cairo_cff_dict_equal);
446 0 : if (unlikely (*dict == NULL))
447 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
448 :
449 0 : return CAIRO_STATUS_SUCCESS;
450 : }
451 :
452 : static void
453 0 : _cairo_dict_init_key (cff_dict_operator_t *key, int operator)
454 : {
455 0 : key->base.hash = (unsigned long) operator;
456 0 : key->operator = operator;
457 0 : }
458 :
459 : static cairo_status_t
460 0 : cff_dict_create_operator (int operator,
461 : unsigned char *operand,
462 : int size,
463 : cff_dict_operator_t **out)
464 : {
465 : cff_dict_operator_t *op;
466 :
467 0 : op = malloc (sizeof (cff_dict_operator_t));
468 0 : if (unlikely (op == NULL))
469 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
470 :
471 0 : _cairo_dict_init_key (op, operator);
472 0 : op->operand = malloc (size);
473 0 : if (unlikely (op->operand == NULL)) {
474 0 : free (op);
475 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
476 : }
477 :
478 0 : memcpy (op->operand, operand, size);
479 0 : op->operand_length = size;
480 0 : op->operand_offset = -1;
481 :
482 0 : *out = op;
483 0 : return CAIRO_STATUS_SUCCESS;
484 : }
485 :
486 : static cairo_status_t
487 0 : cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size)
488 : {
489 : unsigned char *end;
490 : cairo_array_t operands;
491 : cff_dict_operator_t *op;
492 : unsigned short operator;
493 0 : cairo_status_t status = CAIRO_STATUS_SUCCESS;
494 : int size;
495 :
496 0 : end = p + dict_size;
497 0 : _cairo_array_init (&operands, 1);
498 0 : while (p < end) {
499 0 : size = operand_length (p);
500 0 : if (size != 0) {
501 0 : status = _cairo_array_append_multiple (&operands, p, size);
502 0 : if (unlikely (status))
503 0 : goto fail;
504 :
505 0 : p += size;
506 : } else {
507 0 : p = decode_operator (p, &operator);
508 0 : status = cff_dict_create_operator (operator,
509 0 : _cairo_array_index (&operands, 0),
510 : _cairo_array_num_elements (&operands),
511 : &op);
512 0 : if (unlikely (status))
513 0 : goto fail;
514 :
515 0 : status = _cairo_hash_table_insert (dict, &op->base);
516 0 : if (unlikely (status))
517 0 : goto fail;
518 :
519 0 : _cairo_array_truncate (&operands, 0);
520 : }
521 : }
522 :
523 : fail:
524 0 : _cairo_array_fini (&operands);
525 :
526 0 : return status;
527 : }
528 :
529 : static void
530 0 : cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
531 : {
532 : cff_dict_operator_t key, *op;
533 :
534 0 : _cairo_dict_init_key (&key, operator);
535 0 : op = _cairo_hash_table_lookup (dict, &key.base);
536 0 : if (op != NULL) {
537 0 : free (op->operand);
538 0 : _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
539 0 : free (op);
540 : }
541 0 : }
542 :
543 : static unsigned char *
544 0 : cff_dict_get_operands (cairo_hash_table_t *dict,
545 : unsigned short operator,
546 : int *size)
547 : {
548 : cff_dict_operator_t key, *op;
549 :
550 0 : _cairo_dict_init_key (&key, operator);
551 0 : op = _cairo_hash_table_lookup (dict, &key.base);
552 0 : if (op != NULL) {
553 0 : *size = op->operand_length;
554 0 : return op->operand;
555 : }
556 :
557 0 : return NULL;
558 : }
559 :
560 : static cairo_status_t
561 0 : cff_dict_set_operands (cairo_hash_table_t *dict,
562 : unsigned short operator,
563 : unsigned char *operand,
564 : int size)
565 : {
566 : cff_dict_operator_t key, *op;
567 : cairo_status_t status;
568 :
569 0 : _cairo_dict_init_key (&key, operator);
570 0 : op = _cairo_hash_table_lookup (dict, &key.base);
571 0 : if (op != NULL) {
572 0 : free (op->operand);
573 0 : op->operand = malloc (size);
574 0 : if (unlikely (op->operand == NULL))
575 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
576 :
577 0 : memcpy (op->operand, operand, size);
578 0 : op->operand_length = size;
579 : }
580 : else
581 : {
582 0 : status = cff_dict_create_operator (operator, operand, size, &op);
583 0 : if (unlikely (status))
584 0 : return status;
585 :
586 0 : status = _cairo_hash_table_insert (dict, &op->base);
587 0 : if (unlikely (status))
588 0 : return status;
589 : }
590 :
591 0 : return CAIRO_STATUS_SUCCESS;
592 : }
593 :
594 : static int
595 0 : cff_dict_get_location (cairo_hash_table_t *dict,
596 : unsigned short operator,
597 : int *size)
598 : {
599 : cff_dict_operator_t key, *op;
600 :
601 0 : _cairo_dict_init_key (&key, operator);
602 0 : op = _cairo_hash_table_lookup (dict, &key.base);
603 0 : if (op != NULL) {
604 0 : *size = op->operand_length;
605 0 : return op->operand_offset;
606 : }
607 :
608 0 : return -1;
609 : }
610 :
611 : typedef struct _dict_write_info {
612 : cairo_array_t *output;
613 : cairo_status_t status;
614 : } dict_write_info_t;
615 :
616 : static void
617 0 : cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info)
618 : {
619 : unsigned char data;
620 :
621 0 : op->operand_offset = _cairo_array_num_elements (write_info->output);
622 0 : write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length);
623 0 : if (write_info->status)
624 0 : return;
625 :
626 0 : if (op->operator & 0xff00) {
627 0 : data = op->operator >> 8;
628 0 : write_info->status = _cairo_array_append (write_info->output, &data);
629 0 : if (write_info->status)
630 0 : return;
631 : }
632 0 : data = op->operator & 0xff;
633 0 : write_info->status = _cairo_array_append (write_info->output, &data);
634 : }
635 :
636 : static void
637 0 : _cairo_dict_collect (void *entry, void *closure)
638 : {
639 0 : dict_write_info_t *write_info = closure;
640 0 : cff_dict_operator_t *op = entry;
641 :
642 0 : if (write_info->status)
643 0 : return;
644 :
645 : /* The ROS operator is handled separately in cff_dict_write() */
646 0 : if (op->operator != ROS_OP)
647 0 : cairo_dict_write_operator (op, write_info);
648 : }
649 :
650 : static cairo_status_t
651 0 : cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output)
652 : {
653 : dict_write_info_t write_info;
654 : cff_dict_operator_t key, *op;
655 :
656 0 : write_info.output = output;
657 0 : write_info.status = CAIRO_STATUS_SUCCESS;
658 :
659 : /* The CFF specification requires that the Top Dict of CID fonts
660 : * begin with the ROS operator. */
661 0 : _cairo_dict_init_key (&key, ROS_OP);
662 0 : op = _cairo_hash_table_lookup (dict, &key.base);
663 0 : if (op != NULL)
664 0 : cairo_dict_write_operator (op, &write_info);
665 :
666 0 : _cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info);
667 :
668 0 : return write_info.status;
669 : }
670 :
671 : static void
672 0 : _cff_dict_entry_pluck (void *_entry, void *dict)
673 : {
674 0 : cff_dict_operator_t *entry = _entry;
675 :
676 0 : _cairo_hash_table_remove (dict, &entry->base);
677 0 : free (entry->operand);
678 0 : free (entry);
679 0 : }
680 :
681 : static void
682 0 : cff_dict_fini (cairo_hash_table_t *dict)
683 : {
684 0 : _cairo_hash_table_foreach (dict, _cff_dict_entry_pluck, dict);
685 0 : _cairo_hash_table_destroy (dict);
686 0 : }
687 :
688 : static cairo_int_status_t
689 0 : cairo_cff_font_read_header (cairo_cff_font_t *font)
690 : {
691 0 : if (font->data_length < sizeof (cff_header_t))
692 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
693 :
694 0 : font->header = (cff_header_t *) font->data;
695 0 : font->current_ptr = font->data + font->header->header_size;
696 :
697 0 : return CAIRO_STATUS_SUCCESS;
698 : }
699 :
700 : static cairo_int_status_t
701 0 : cairo_cff_font_read_name (cairo_cff_font_t *font)
702 : {
703 : cairo_array_t index;
704 : cairo_int_status_t status;
705 :
706 : /* The original font name is not used in the subset. Read the name
707 : * index to skip over it. */
708 0 : cff_index_init (&index);
709 0 : status = cff_index_read (&index, &font->current_ptr, font->data_end);
710 0 : cff_index_fini (&index);
711 :
712 0 : return status;
713 : }
714 :
715 : static cairo_int_status_t
716 0 : cairo_cff_font_read_private_dict (cairo_cff_font_t *font,
717 : cairo_hash_table_t *private_dict,
718 : cairo_array_t *local_sub_index,
719 : unsigned char *ptr,
720 : int size)
721 : {
722 : cairo_int_status_t status;
723 : unsigned char buf[10];
724 : unsigned char *end_buf;
725 : int offset;
726 : int i;
727 : unsigned char *operand;
728 : unsigned char *p;
729 :
730 0 : status = cff_dict_read (private_dict, ptr, size);
731 0 : if (unlikely (status))
732 0 : return status;
733 :
734 0 : operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
735 0 : if (operand) {
736 0 : decode_integer (operand, &offset);
737 0 : p = ptr + offset;
738 0 : status = cff_index_read (local_sub_index, &p, font->data_end);
739 0 : if (unlikely (status))
740 0 : return status;
741 :
742 : /* Use maximum sized encoding to reserve space for later modification. */
743 0 : end_buf = encode_integer_max (buf, 0);
744 0 : status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
745 0 : if (unlikely (status))
746 0 : return status;
747 : }
748 :
749 0 : return CAIRO_STATUS_SUCCESS;
750 : }
751 :
752 : static cairo_int_status_t
753 0 : cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p)
754 : {
755 : int type, num_ranges, first, last, fd, i, j;
756 :
757 0 : font->fdselect = calloc (font->num_glyphs, sizeof (int));
758 0 : if (unlikely (font->fdselect == NULL))
759 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
760 :
761 0 : type = *p++;
762 0 : if (type == 0)
763 : {
764 0 : for (i = 0; i < font->num_glyphs; i++)
765 0 : font->fdselect[i] = *p++;
766 0 : } else if (type == 3) {
767 0 : num_ranges = be16_to_cpu( *((uint16_t *)p) );
768 0 : p += 2;
769 0 : for (i = 0; i < num_ranges; i++)
770 : {
771 0 : first = be16_to_cpu( *((uint16_t *)p) );
772 0 : p += 2;
773 0 : fd = *p++;
774 0 : last = be16_to_cpu( *((uint16_t *)p) );
775 0 : for (j = first; j < last; j++)
776 0 : font->fdselect[j] = fd;
777 : }
778 : } else {
779 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
780 : }
781 :
782 0 : return CAIRO_STATUS_SUCCESS;
783 : }
784 :
785 : static cairo_int_status_t
786 0 : cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
787 : {
788 : cairo_array_t index;
789 : cff_index_element_t *element;
790 : unsigned int i;
791 : int size;
792 : unsigned char *operand;
793 : int offset;
794 : cairo_int_status_t status;
795 : unsigned char buf[100];
796 : unsigned char *end_buf;
797 :
798 0 : cff_index_init (&index);
799 0 : status = cff_index_read (&index, &ptr, font->data_end);
800 0 : if (unlikely (status))
801 0 : goto fail;
802 :
803 0 : font->num_fontdicts = _cairo_array_num_elements (&index);
804 :
805 0 : font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
806 0 : if (unlikely (font->fd_dict == NULL)) {
807 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
808 0 : goto fail;
809 : }
810 :
811 0 : font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
812 0 : if (unlikely (font->fd_private_dict == NULL)) {
813 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
814 0 : goto fail;
815 : }
816 :
817 0 : font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts);
818 0 : if (unlikely (font->fd_local_sub_index == NULL)) {
819 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
820 0 : goto fail;
821 : }
822 :
823 0 : for (i = 0; i < font->num_fontdicts; i++) {
824 0 : status = cff_dict_init (&font->fd_dict[i]);
825 0 : if (unlikely (status))
826 0 : goto fail;
827 :
828 0 : element = _cairo_array_index (&index, i);
829 0 : status = cff_dict_read (font->fd_dict[i], element->data, element->length);
830 0 : if (unlikely (status))
831 0 : goto fail;
832 :
833 0 : operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size);
834 0 : if (operand == NULL) {
835 0 : status = CAIRO_INT_STATUS_UNSUPPORTED;
836 0 : goto fail;
837 : }
838 0 : operand = decode_integer (operand, &size);
839 0 : decode_integer (operand, &offset);
840 0 : status = cff_dict_init (&font->fd_private_dict[i]);
841 0 : if (unlikely (status))
842 0 : goto fail;
843 :
844 0 : cff_index_init (&font->fd_local_sub_index[i]);
845 0 : status = cairo_cff_font_read_private_dict (font,
846 0 : font->fd_private_dict[i],
847 0 : &font->fd_local_sub_index[i],
848 0 : font->data + offset,
849 : size);
850 0 : if (unlikely (status))
851 0 : goto fail;
852 :
853 : /* Set integer operand to max value to use max size encoding to reserve
854 : * space for any value later */
855 0 : end_buf = encode_integer_max (buf, 0);
856 0 : end_buf = encode_integer_max (end_buf, 0);
857 0 : status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf);
858 0 : if (unlikely (status))
859 0 : goto fail;
860 : }
861 :
862 0 : return CAIRO_STATUS_SUCCESS;
863 :
864 : fail:
865 0 : cff_index_fini (&index);
866 :
867 0 : return status;
868 : }
869 :
870 : static cairo_int_status_t
871 0 : cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
872 : {
873 : cairo_array_t index;
874 : cff_index_element_t *element;
875 : unsigned char buf[20];
876 : unsigned char *end_buf;
877 : unsigned char *operand;
878 : cairo_int_status_t status;
879 : unsigned char *p;
880 : int size;
881 : int offset;
882 :
883 0 : cff_index_init (&index);
884 0 : status = cff_index_read (&index, &font->current_ptr, font->data_end);
885 0 : if (unlikely (status))
886 0 : goto fail;
887 :
888 0 : element = _cairo_array_index (&index, 0);
889 0 : status = cff_dict_read (font->top_dict, element->data, element->length);
890 0 : if (unlikely (status))
891 0 : goto fail;
892 :
893 0 : if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL)
894 0 : font->is_cid = TRUE;
895 : else
896 0 : font->is_cid = FALSE;
897 :
898 0 : operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size);
899 0 : decode_integer (operand, &offset);
900 0 : p = font->data + offset;
901 0 : status = cff_index_read (&font->charstrings_index, &p, font->data_end);
902 0 : if (unlikely (status))
903 0 : goto fail;
904 0 : font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index);
905 :
906 0 : if (font->is_cid) {
907 0 : operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
908 0 : decode_integer (operand, &offset);
909 0 : status = cairo_cff_font_read_fdselect (font, font->data + offset);
910 0 : if (unlikely (status))
911 0 : goto fail;
912 :
913 0 : operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
914 0 : decode_integer (operand, &offset);
915 0 : status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
916 0 : if (unlikely (status))
917 0 : goto fail;
918 : } else {
919 0 : operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
920 0 : operand = decode_integer (operand, &size);
921 0 : decode_integer (operand, &offset);
922 0 : status = cairo_cff_font_read_private_dict (font,
923 : font->private_dict,
924 : &font->local_sub_index,
925 0 : font->data + offset,
926 : size);
927 0 : if (unlikely (status))
928 0 : goto fail;
929 : }
930 :
931 : /* Use maximum sized encoding to reserve space for later modification. */
932 0 : end_buf = encode_integer_max (buf, 0);
933 0 : status = cff_dict_set_operands (font->top_dict,
934 0 : CHARSTRINGS_OP, buf, end_buf - buf);
935 0 : if (unlikely (status))
936 0 : goto fail;
937 :
938 0 : status = cff_dict_set_operands (font->top_dict,
939 0 : FDSELECT_OP, buf, end_buf - buf);
940 0 : if (unlikely (status))
941 0 : goto fail;
942 :
943 0 : status = cff_dict_set_operands (font->top_dict,
944 0 : FDARRAY_OP, buf, end_buf - buf);
945 0 : if (unlikely (status))
946 0 : goto fail;
947 :
948 0 : status = cff_dict_set_operands (font->top_dict,
949 0 : CHARSET_OP, buf, end_buf - buf);
950 0 : if (unlikely (status))
951 0 : goto fail;
952 :
953 0 : cff_dict_remove (font->top_dict, ENCODING_OP);
954 0 : cff_dict_remove (font->top_dict, PRIVATE_OP);
955 :
956 : /* Remove the unique identifier operators as the subsetted font is
957 : * not the same is the original font. */
958 0 : cff_dict_remove (font->top_dict, UNIQUEID_OP);
959 0 : cff_dict_remove (font->top_dict, XUID_OP);
960 :
961 : fail:
962 0 : cff_index_fini (&index);
963 :
964 0 : return status;
965 : }
966 :
967 : static cairo_int_status_t
968 0 : cairo_cff_font_read_strings (cairo_cff_font_t *font)
969 : {
970 0 : return cff_index_read (&font->strings_index, &font->current_ptr, font->data_end);
971 : }
972 :
973 : static cairo_int_status_t
974 0 : cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font)
975 : {
976 0 : return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end);
977 : }
978 :
979 : typedef cairo_int_status_t
980 : (*font_read_t) (cairo_cff_font_t *font);
981 :
982 : static const font_read_t font_read_funcs[] = {
983 : cairo_cff_font_read_header,
984 : cairo_cff_font_read_name,
985 : cairo_cff_font_read_top_dict,
986 : cairo_cff_font_read_strings,
987 : cairo_cff_font_read_global_subroutines,
988 : };
989 :
990 : static cairo_int_status_t
991 0 : cairo_cff_font_read_font (cairo_cff_font_t *font)
992 : {
993 : cairo_int_status_t status;
994 : unsigned int i;
995 :
996 0 : for (i = 0; i < ARRAY_LENGTH (font_read_funcs); i++) {
997 0 : status = font_read_funcs[i] (font);
998 0 : if (unlikely (status))
999 0 : return status;
1000 : }
1001 :
1002 0 : return CAIRO_STATUS_SUCCESS;
1003 : }
1004 :
1005 : static cairo_status_t
1006 0 : cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
1007 : {
1008 : cairo_status_t status;
1009 : unsigned char buf[30];
1010 : unsigned char *p;
1011 : int sid1, sid2;
1012 0 : const char *registry = "Adobe";
1013 0 : const char *ordering = "Identity";
1014 :
1015 0 : sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
1016 0 : status = cff_index_append_copy (&font->strings_subset_index,
1017 : (unsigned char *)registry,
1018 0 : strlen(registry));
1019 0 : if (unlikely (status))
1020 0 : return status;
1021 :
1022 0 : sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
1023 0 : status = cff_index_append_copy (&font->strings_subset_index,
1024 : (unsigned char *)ordering,
1025 0 : strlen(ordering));
1026 0 : if (unlikely (status))
1027 0 : return status;
1028 :
1029 0 : p = encode_integer (buf, sid1);
1030 0 : p = encode_integer (p, sid2);
1031 0 : p = encode_integer (p, 0);
1032 0 : status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
1033 0 : if (unlikely (status))
1034 0 : return status;
1035 :
1036 0 : p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
1037 0 : status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
1038 0 : if (unlikely (status))
1039 0 : return status;
1040 :
1041 0 : return CAIRO_STATUS_SUCCESS;
1042 : }
1043 :
1044 : static cairo_status_t
1045 0 : cairo_cff_font_subset_dict_string(cairo_cff_font_t *font,
1046 : cairo_hash_table_t *dict,
1047 : int operator)
1048 : {
1049 : int size;
1050 : unsigned char *p;
1051 : int sid;
1052 : unsigned char buf[100];
1053 : cff_index_element_t *element;
1054 : cairo_status_t status;
1055 :
1056 0 : p = cff_dict_get_operands (dict, operator, &size);
1057 0 : if (!p)
1058 0 : return CAIRO_STATUS_SUCCESS;
1059 :
1060 0 : decode_integer (p, &sid);
1061 0 : if (sid < NUM_STD_STRINGS)
1062 0 : return CAIRO_STATUS_SUCCESS;
1063 :
1064 0 : element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS);
1065 0 : sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
1066 0 : status = cff_index_append (&font->strings_subset_index, element->data, element->length);
1067 0 : if (unlikely (status))
1068 0 : return status;
1069 :
1070 0 : p = encode_integer (buf, sid);
1071 0 : status = cff_dict_set_operands (dict, operator, buf, p - buf);
1072 0 : if (unlikely (status))
1073 0 : return status;
1074 :
1075 0 : return CAIRO_STATUS_SUCCESS;
1076 : }
1077 :
1078 : static const int dict_strings[] = {
1079 : VERSION_OP,
1080 : NOTICE_OP,
1081 : COPYRIGHT_OP,
1082 : FULLNAME_OP,
1083 : FAMILYNAME_OP,
1084 : WEIGHT_OP,
1085 : POSTSCRIPT_OP,
1086 : BASEFONTNAME_OP,
1087 : FONTNAME_OP,
1088 : };
1089 :
1090 : static cairo_status_t
1091 0 : cairo_cff_font_subset_dict_strings (cairo_cff_font_t *font,
1092 : cairo_hash_table_t *dict)
1093 : {
1094 : cairo_status_t status;
1095 : unsigned int i;
1096 :
1097 0 : for (i = 0; i < ARRAY_LENGTH (dict_strings); i++) {
1098 0 : status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]);
1099 0 : if (unlikely (status))
1100 0 : return status;
1101 : }
1102 :
1103 0 : return CAIRO_STATUS_SUCCESS;
1104 : }
1105 :
1106 : static cairo_status_t
1107 0 : cairo_cff_font_subset_charstrings (cairo_cff_font_t *font)
1108 : {
1109 : cff_index_element_t *element;
1110 : unsigned int i;
1111 : cairo_status_t status;
1112 :
1113 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
1114 0 : element = _cairo_array_index (&font->charstrings_index,
1115 0 : font->scaled_font_subset->glyphs[i]);
1116 0 : status = cff_index_append (&font->charstrings_subset_index,
1117 : element->data,
1118 : element->length);
1119 0 : if (unlikely (status))
1120 0 : return status;
1121 : }
1122 :
1123 0 : return CAIRO_STATUS_SUCCESS;
1124 : }
1125 :
1126 : static cairo_status_t
1127 0 : cairo_cff_font_subset_fontdict (cairo_cff_font_t *font)
1128 : {
1129 : unsigned int i;
1130 : int fd;
1131 : int *reverse_map;
1132 :
1133 0 : font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs,
1134 : sizeof (int));
1135 0 : if (unlikely (font->fdselect_subset == NULL))
1136 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1137 :
1138 0 : font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int));
1139 0 : if (unlikely (font->fd_subset_map == NULL))
1140 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1141 :
1142 0 : font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int));
1143 0 : if (unlikely (font->private_dict_offset == NULL))
1144 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1145 :
1146 0 : reverse_map = calloc (font->num_fontdicts, sizeof (int));
1147 0 : if (unlikely (reverse_map == NULL))
1148 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1149 :
1150 0 : for (i = 0; i < font->num_fontdicts; i++)
1151 0 : reverse_map[i] = -1;
1152 :
1153 0 : font->num_subset_fontdicts = 0;
1154 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
1155 0 : fd = font->fdselect[font->scaled_font_subset->glyphs[i]];
1156 0 : if (reverse_map[fd] < 0) {
1157 0 : font->fd_subset_map[font->num_subset_fontdicts] = fd;
1158 0 : reverse_map[fd] = font->num_subset_fontdicts++;
1159 : }
1160 0 : font->fdselect_subset[i] = reverse_map[fd];
1161 : }
1162 :
1163 0 : free (reverse_map);
1164 :
1165 0 : return CAIRO_STATUS_SUCCESS;
1166 : }
1167 :
1168 : static cairo_status_t
1169 0 : cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
1170 : {
1171 : unsigned char buf[100];
1172 : unsigned char *end_buf;
1173 : cairo_status_t status;
1174 :
1175 0 : font->num_fontdicts = 1;
1176 0 : font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
1177 0 : if (unlikely (font->fd_dict == NULL))
1178 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1179 :
1180 0 : if (cff_dict_init (&font->fd_dict[0])) {
1181 0 : free (font->fd_dict);
1182 0 : font->fd_dict = NULL;
1183 0 : font->num_fontdicts = 0;
1184 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1185 : }
1186 :
1187 0 : font->fd_subset_map = malloc (sizeof (int));
1188 0 : if (unlikely (font->fd_subset_map == NULL))
1189 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1190 :
1191 0 : font->private_dict_offset = malloc (sizeof (int));
1192 0 : if (unlikely (font->private_dict_offset == NULL))
1193 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1194 :
1195 0 : font->fd_subset_map[0] = 0;
1196 0 : font->num_subset_fontdicts = 1;
1197 :
1198 : /* Set integer operand to max value to use max size encoding to reserve
1199 : * space for any value later */
1200 0 : end_buf = encode_integer_max (buf, 0);
1201 0 : end_buf = encode_integer_max (end_buf, 0);
1202 0 : status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
1203 0 : if (unlikely (status))
1204 0 : return status;
1205 :
1206 0 : return CAIRO_STATUS_SUCCESS;
1207 : }
1208 :
1209 : static cairo_status_t
1210 0 : cairo_cff_font_subset_strings (cairo_cff_font_t *font)
1211 : {
1212 : cairo_status_t status;
1213 : unsigned int i;
1214 :
1215 0 : status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
1216 0 : if (unlikely (status))
1217 0 : return status;
1218 :
1219 0 : if (font->is_cid) {
1220 0 : for (i = 0; i < font->num_subset_fontdicts; i++) {
1221 0 : status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
1222 0 : if (unlikely (status))
1223 0 : return status;
1224 :
1225 0 : status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]);
1226 0 : if (unlikely (status))
1227 0 : return status;
1228 : }
1229 : } else {
1230 0 : status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
1231 : }
1232 :
1233 0 : return status;
1234 : }
1235 :
1236 : static cairo_status_t
1237 0 : cairo_cff_font_subset_font (cairo_cff_font_t *font)
1238 : {
1239 : cairo_status_t status;
1240 :
1241 0 : status = cairo_cff_font_set_ros_strings (font);
1242 0 : if (unlikely (status))
1243 0 : return status;
1244 :
1245 0 : status = cairo_cff_font_subset_charstrings (font);
1246 0 : if (unlikely (status))
1247 0 : return status;
1248 :
1249 0 : if (font->is_cid)
1250 0 : status = cairo_cff_font_subset_fontdict (font);
1251 : else
1252 0 : status = cairo_cff_font_create_cid_fontdict (font);
1253 0 : if (unlikely (status))
1254 0 : return status;
1255 :
1256 0 : status = cairo_cff_font_subset_strings (font);
1257 0 : if (unlikely (status))
1258 0 : return status;
1259 :
1260 0 : return status;
1261 : }
1262 :
1263 : /* Set the operand of the specified operator in the (already written)
1264 : * top dict to point to the current position in the output
1265 : * array. Operands updated with this function must have previously
1266 : * been encoded with the 5-byte (max) integer encoding. */
1267 : static void
1268 0 : cairo_cff_font_set_topdict_operator_to_cur_pos (cairo_cff_font_t *font,
1269 : int operator)
1270 : {
1271 : int cur_pos;
1272 : int offset;
1273 : int size;
1274 : unsigned char buf[10];
1275 : unsigned char *buf_end;
1276 : unsigned char *op_ptr;
1277 :
1278 0 : cur_pos = _cairo_array_num_elements (&font->output);
1279 0 : buf_end = encode_integer_max (buf, cur_pos);
1280 0 : offset = cff_dict_get_location (font->top_dict, operator, &size);
1281 0 : assert (offset > 0);
1282 0 : op_ptr = _cairo_array_index (&font->output, offset);
1283 0 : memcpy (op_ptr, buf, buf_end - buf);
1284 0 : }
1285 :
1286 : static cairo_status_t
1287 0 : cairo_cff_font_write_header (cairo_cff_font_t *font)
1288 : {
1289 0 : return _cairo_array_append_multiple (&font->output,
1290 0 : font->header,
1291 0 : font->header->header_size);
1292 : }
1293 :
1294 : static cairo_status_t
1295 0 : cairo_cff_font_write_name (cairo_cff_font_t *font)
1296 : {
1297 0 : cairo_status_t status = CAIRO_STATUS_SUCCESS;
1298 : cairo_array_t index;
1299 :
1300 0 : cff_index_init (&index);
1301 :
1302 0 : status = cff_index_append_copy (&index,
1303 0 : (unsigned char *) font->subset_font_name,
1304 0 : strlen(font->subset_font_name));
1305 0 : if (unlikely (status))
1306 0 : goto FAIL;
1307 :
1308 0 : status = cff_index_write (&index, &font->output);
1309 0 : if (unlikely (status))
1310 0 : goto FAIL;
1311 :
1312 : FAIL:
1313 0 : cff_index_fini (&index);
1314 :
1315 0 : return status;
1316 : }
1317 :
1318 : static cairo_status_t
1319 0 : cairo_cff_font_write_top_dict (cairo_cff_font_t *font)
1320 : {
1321 : uint16_t count;
1322 : unsigned char buf[10];
1323 : unsigned char *p;
1324 : int offset_index;
1325 : int dict_start, dict_size;
1326 0 : int offset_size = 4;
1327 : cairo_status_t status;
1328 :
1329 : /* Write an index containing the top dict */
1330 :
1331 0 : count = cpu_to_be16 (1);
1332 0 : status = _cairo_array_append_multiple (&font->output, &count, 2);
1333 0 : if (unlikely (status))
1334 0 : return status;
1335 0 : buf[0] = offset_size;
1336 0 : status = _cairo_array_append (&font->output, buf);
1337 0 : if (unlikely (status))
1338 0 : return status;
1339 0 : encode_index_offset (buf, offset_size, 1);
1340 0 : status = _cairo_array_append_multiple (&font->output, buf, offset_size);
1341 0 : if (unlikely (status))
1342 0 : return status;
1343 :
1344 : /* Reserve space for last element of offset array and update after
1345 : * dict is written */
1346 0 : offset_index = _cairo_array_num_elements (&font->output);
1347 0 : status = _cairo_array_append_multiple (&font->output, buf, offset_size);
1348 0 : if (unlikely (status))
1349 0 : return status;
1350 :
1351 0 : dict_start = _cairo_array_num_elements (&font->output);
1352 0 : status = cff_dict_write (font->top_dict, &font->output);
1353 0 : if (unlikely (status))
1354 0 : return status;
1355 0 : dict_size = _cairo_array_num_elements (&font->output) - dict_start;
1356 :
1357 0 : encode_index_offset (buf, offset_size, dict_size + 1);
1358 0 : p = _cairo_array_index (&font->output, offset_index);
1359 0 : memcpy (p, buf, offset_size);
1360 :
1361 0 : return CAIRO_STATUS_SUCCESS;
1362 : }
1363 :
1364 : static cairo_status_t
1365 0 : cairo_cff_font_write_strings (cairo_cff_font_t *font)
1366 : {
1367 0 : return cff_index_write (&font->strings_subset_index, &font->output);
1368 : }
1369 :
1370 : static cairo_status_t
1371 0 : cairo_cff_font_write_global_subrs (cairo_cff_font_t *font)
1372 : {
1373 0 : return cff_index_write (&font->global_sub_index, &font->output);
1374 : }
1375 :
1376 : static cairo_status_t
1377 0 : cairo_cff_font_write_fdselect (cairo_cff_font_t *font)
1378 : {
1379 : unsigned char data;
1380 : unsigned int i;
1381 : cairo_int_status_t status;
1382 :
1383 0 : cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP);
1384 :
1385 0 : if (font->is_cid) {
1386 0 : data = 0;
1387 0 : status = _cairo_array_append (&font->output, &data);
1388 0 : if (unlikely (status))
1389 0 : return status;
1390 :
1391 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
1392 0 : data = font->fdselect_subset[i];
1393 0 : status = _cairo_array_append (&font->output, &data);
1394 0 : if (unlikely (status))
1395 0 : return status;
1396 : }
1397 : } else {
1398 : unsigned char byte;
1399 : uint16_t word;
1400 :
1401 0 : status = _cairo_array_grow_by (&font->output, 9);
1402 0 : if (unlikely (status))
1403 0 : return status;
1404 :
1405 0 : byte = 3;
1406 0 : status = _cairo_array_append (&font->output, &byte);
1407 0 : assert (status == CAIRO_STATUS_SUCCESS);
1408 :
1409 0 : word = cpu_to_be16 (1);
1410 0 : status = _cairo_array_append_multiple (&font->output, &word, 2);
1411 0 : assert (status == CAIRO_STATUS_SUCCESS);
1412 :
1413 0 : word = cpu_to_be16 (0);
1414 0 : status = _cairo_array_append_multiple (&font->output, &word, 2);
1415 0 : assert (status == CAIRO_STATUS_SUCCESS);
1416 :
1417 0 : byte = 0;
1418 0 : status = _cairo_array_append (&font->output, &byte);
1419 0 : assert (status == CAIRO_STATUS_SUCCESS);
1420 :
1421 0 : word = cpu_to_be16 (font->scaled_font_subset->num_glyphs);
1422 0 : status = _cairo_array_append_multiple (&font->output, &word, 2);
1423 0 : assert (status == CAIRO_STATUS_SUCCESS);
1424 : }
1425 :
1426 0 : return CAIRO_STATUS_SUCCESS;
1427 : }
1428 :
1429 : static cairo_status_t
1430 0 : cairo_cff_font_write_charset (cairo_cff_font_t *font)
1431 : {
1432 : unsigned char byte;
1433 : uint16_t word;
1434 : cairo_status_t status;
1435 :
1436 0 : cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
1437 0 : status = _cairo_array_grow_by (&font->output, 5);
1438 0 : if (unlikely (status))
1439 0 : return status;
1440 :
1441 0 : byte = 2;
1442 0 : status = _cairo_array_append (&font->output, &byte);
1443 0 : assert (status == CAIRO_STATUS_SUCCESS);
1444 :
1445 0 : word = cpu_to_be16 (1);
1446 0 : status = _cairo_array_append_multiple (&font->output, &word, 2);
1447 0 : assert (status == CAIRO_STATUS_SUCCESS);
1448 :
1449 0 : word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2);
1450 0 : status = _cairo_array_append_multiple (&font->output, &word, 2);
1451 0 : assert (status == CAIRO_STATUS_SUCCESS);
1452 :
1453 0 : return CAIRO_STATUS_SUCCESS;
1454 : }
1455 :
1456 : static cairo_status_t
1457 0 : cairo_cff_font_write_charstrings (cairo_cff_font_t *font)
1458 : {
1459 0 : cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP);
1460 :
1461 0 : return cff_index_write (&font->charstrings_subset_index, &font->output);
1462 : }
1463 :
1464 : static cairo_status_t
1465 0 : cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
1466 : {
1467 : unsigned int i;
1468 : cairo_int_status_t status;
1469 : unsigned int offset_array;
1470 : uint32_t *offset_array_ptr;
1471 : int offset_base;
1472 : uint16_t count;
1473 0 : uint8_t offset_size = 4;
1474 :
1475 0 : cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP);
1476 0 : count = cpu_to_be16 (font->num_subset_fontdicts);
1477 0 : status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t));
1478 0 : if (unlikely (status))
1479 0 : return status;
1480 0 : status = _cairo_array_append (&font->output, &offset_size);
1481 0 : if (unlikely (status))
1482 0 : return status;
1483 :
1484 0 : offset_array = _cairo_array_num_elements (&font->output);
1485 0 : status = _cairo_array_allocate (&font->output,
1486 0 : (font->num_subset_fontdicts + 1)*offset_size,
1487 : (void **) &offset_array_ptr);
1488 0 : if (unlikely (status))
1489 0 : return status;
1490 0 : offset_base = _cairo_array_num_elements (&font->output) - 1;
1491 0 : *offset_array_ptr = cpu_to_be32(1);
1492 0 : offset_array += sizeof(uint32_t);
1493 0 : for (i = 0; i < font->num_subset_fontdicts; i++) {
1494 0 : status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
1495 : &font->output);
1496 0 : if (unlikely (status))
1497 0 : return status;
1498 :
1499 0 : offset_array_ptr = (uint32_t *) _cairo_array_index (&font->output, offset_array);
1500 0 : *offset_array_ptr = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
1501 0 : offset_array += sizeof(uint32_t);
1502 : }
1503 :
1504 0 : return CAIRO_STATUS_SUCCESS;
1505 : }
1506 :
1507 : static cairo_status_t
1508 0 : cairo_cff_font_write_private_dict (cairo_cff_font_t *font,
1509 : int dict_num,
1510 : cairo_hash_table_t *parent_dict,
1511 : cairo_hash_table_t *private_dict)
1512 : {
1513 : int offset;
1514 : int size;
1515 : unsigned char buf[10];
1516 : unsigned char *buf_end;
1517 : unsigned char *p;
1518 : cairo_status_t status;
1519 :
1520 : /* Write private dict and update offset and size in top dict */
1521 0 : font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output);
1522 0 : status = cff_dict_write (private_dict, &font->output);
1523 0 : if (unlikely (status))
1524 0 : return status;
1525 :
1526 0 : size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
1527 : /* private entry has two operands - size and offset */
1528 0 : buf_end = encode_integer_max (buf, size);
1529 0 : buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]);
1530 0 : offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size);
1531 0 : assert (offset > 0);
1532 0 : p = _cairo_array_index (&font->output, offset);
1533 0 : memcpy (p, buf, buf_end - buf);
1534 :
1535 0 : return CAIRO_STATUS_SUCCESS;
1536 : }
1537 :
1538 : static cairo_status_t
1539 0 : cairo_cff_font_write_local_sub (cairo_cff_font_t *font,
1540 : int dict_num,
1541 : cairo_hash_table_t *private_dict,
1542 : cairo_array_t *local_sub_index)
1543 : {
1544 : int offset;
1545 : int size;
1546 : unsigned char buf[10];
1547 : unsigned char *buf_end;
1548 : unsigned char *p;
1549 : cairo_status_t status;
1550 :
1551 0 : if (_cairo_array_num_elements (local_sub_index) > 0) {
1552 : /* Write local subroutines and update offset in private
1553 : * dict. Local subroutines offset is relative to start of
1554 : * private dict */
1555 0 : offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
1556 0 : buf_end = encode_integer_max (buf, offset);
1557 0 : offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size);
1558 0 : assert (offset > 0);
1559 0 : p = _cairo_array_index (&font->output, offset);
1560 0 : memcpy (p, buf, buf_end - buf);
1561 0 : status = cff_index_write (local_sub_index, &font->output);
1562 0 : if (unlikely (status))
1563 0 : return status;
1564 : }
1565 :
1566 0 : return CAIRO_STATUS_SUCCESS;
1567 : }
1568 :
1569 :
1570 : static cairo_status_t
1571 0 : cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font)
1572 : {
1573 : unsigned int i;
1574 : cairo_int_status_t status;
1575 :
1576 0 : if (font->is_cid) {
1577 0 : for (i = 0; i < font->num_subset_fontdicts; i++) {
1578 0 : status = cairo_cff_font_write_private_dict (
1579 : font,
1580 : i,
1581 0 : font->fd_dict[font->fd_subset_map[i]],
1582 0 : font->fd_private_dict[font->fd_subset_map[i]]);
1583 0 : if (unlikely (status))
1584 0 : return status;
1585 : }
1586 :
1587 0 : for (i = 0; i < font->num_subset_fontdicts; i++) {
1588 0 : status = cairo_cff_font_write_local_sub (
1589 : font,
1590 : i,
1591 0 : font->fd_private_dict[font->fd_subset_map[i]],
1592 0 : &font->fd_local_sub_index[font->fd_subset_map[i]]);
1593 0 : if (unlikely (status))
1594 0 : return status;
1595 : }
1596 : } else {
1597 0 : status = cairo_cff_font_write_private_dict (font,
1598 : 0,
1599 0 : font->fd_dict[0],
1600 : font->private_dict);
1601 0 : if (unlikely (status))
1602 0 : return status;
1603 :
1604 0 : status = cairo_cff_font_write_local_sub (font,
1605 : 0,
1606 : font->private_dict,
1607 : &font->local_sub_index);
1608 0 : if (unlikely (status))
1609 0 : return status;
1610 : }
1611 :
1612 0 : return CAIRO_STATUS_SUCCESS;
1613 : }
1614 :
1615 : typedef cairo_status_t
1616 : (*font_write_t) (cairo_cff_font_t *font);
1617 :
1618 : static const font_write_t font_write_funcs[] = {
1619 : cairo_cff_font_write_header,
1620 : cairo_cff_font_write_name,
1621 : cairo_cff_font_write_top_dict,
1622 : cairo_cff_font_write_strings,
1623 : cairo_cff_font_write_global_subrs,
1624 : cairo_cff_font_write_charset,
1625 : cairo_cff_font_write_fdselect,
1626 : cairo_cff_font_write_charstrings,
1627 : cairo_cff_font_write_cid_fontdict,
1628 : cairo_cff_font_write_cid_private_dict_and_local_sub,
1629 : };
1630 :
1631 : static cairo_status_t
1632 0 : cairo_cff_font_write_subset (cairo_cff_font_t *font)
1633 : {
1634 : cairo_int_status_t status;
1635 : unsigned int i;
1636 :
1637 0 : for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) {
1638 0 : status = font_write_funcs[i] (font);
1639 0 : if (unlikely (status))
1640 0 : return status;
1641 : }
1642 :
1643 0 : return CAIRO_STATUS_SUCCESS;
1644 : }
1645 :
1646 : static cairo_int_status_t
1647 0 : cairo_cff_font_generate (cairo_cff_font_t *font,
1648 : const char **data,
1649 : unsigned long *length)
1650 : {
1651 : cairo_int_status_t status;
1652 :
1653 0 : status = cairo_cff_font_read_font (font);
1654 0 : if (unlikely (status))
1655 0 : return status;
1656 :
1657 0 : status = cairo_cff_font_subset_font (font);
1658 0 : if (unlikely (status))
1659 0 : return status;
1660 :
1661 0 : status = cairo_cff_font_write_subset (font);
1662 0 : if (unlikely (status))
1663 0 : return status;
1664 :
1665 0 : *data = _cairo_array_index (&font->output, 0);
1666 0 : *length = _cairo_array_num_elements (&font->output);
1667 :
1668 0 : return CAIRO_STATUS_SUCCESS;
1669 : }
1670 :
1671 : static cairo_int_status_t
1672 0 : cairo_cff_font_create_set_widths (cairo_cff_font_t *font)
1673 : {
1674 : unsigned long size;
1675 : unsigned long long_entry_size;
1676 : unsigned long short_entry_size;
1677 : unsigned int i;
1678 : tt_hhea_t hhea;
1679 : int num_hmetrics;
1680 : unsigned char buf[10];
1681 : int glyph_index;
1682 : cairo_int_status_t status;
1683 :
1684 0 : size = sizeof (tt_hhea_t);
1685 0 : status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
1686 : TT_TAG_hhea, 0,
1687 : (unsigned char*) &hhea, &size);
1688 0 : if (unlikely (status))
1689 0 : return status;
1690 0 : num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
1691 :
1692 0 : for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
1693 0 : glyph_index = font->scaled_font_subset->glyphs[i];
1694 0 : long_entry_size = 2 * sizeof (int16_t);
1695 0 : short_entry_size = sizeof (int16_t);
1696 0 : if (glyph_index < num_hmetrics) {
1697 0 : status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
1698 : TT_TAG_hmtx,
1699 0 : glyph_index * long_entry_size,
1700 : buf, &short_entry_size);
1701 0 : if (unlikely (status))
1702 0 : return status;
1703 : }
1704 : else
1705 : {
1706 0 : status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
1707 : TT_TAG_hmtx,
1708 0 : (num_hmetrics - 1) * long_entry_size,
1709 : buf, &short_entry_size);
1710 0 : if (unlikely (status))
1711 0 : return status;
1712 : }
1713 0 : font->widths[i] = be16_to_cpu (*((int16_t*)buf));
1714 : }
1715 :
1716 0 : return CAIRO_STATUS_SUCCESS;
1717 : }
1718 :
1719 : static cairo_int_status_t
1720 0 : _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
1721 : cairo_cff_font_t **font_return,
1722 : const char *subset_name)
1723 : {
1724 : const cairo_scaled_font_backend_t *backend;
1725 : cairo_status_t status;
1726 : cairo_cff_font_t *font;
1727 : tt_head_t head;
1728 : tt_hhea_t hhea;
1729 : unsigned long size, data_length;
1730 :
1731 0 : backend = scaled_font_subset->scaled_font->backend;
1732 0 : if (!backend->load_truetype_table)
1733 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
1734 :
1735 0 : data_length = 0;
1736 0 : status = backend->load_truetype_table( scaled_font_subset->scaled_font,
1737 : TT_TAG_CFF, 0, NULL, &data_length);
1738 0 : if (unlikely (status))
1739 0 : return status;
1740 :
1741 0 : size = sizeof (tt_head_t);
1742 0 : status = backend->load_truetype_table (scaled_font_subset->scaled_font,
1743 : TT_TAG_head, 0,
1744 : (unsigned char *) &head, &size);
1745 0 : if (unlikely (status))
1746 0 : return status;
1747 :
1748 0 : size = sizeof (tt_hhea_t);
1749 0 : status = backend->load_truetype_table (scaled_font_subset->scaled_font,
1750 : TT_TAG_hhea, 0,
1751 : (unsigned char *) &hhea, &size);
1752 0 : if (unlikely (status))
1753 0 : return status;
1754 :
1755 0 : size = 0;
1756 0 : status = backend->load_truetype_table (scaled_font_subset->scaled_font,
1757 : TT_TAG_hmtx, 0, NULL, &size);
1758 0 : if (unlikely (status))
1759 0 : return status;
1760 :
1761 0 : font = malloc (sizeof (cairo_cff_font_t));
1762 0 : if (unlikely (font == NULL))
1763 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1764 :
1765 0 : font->backend = backend;
1766 0 : font->scaled_font_subset = scaled_font_subset;
1767 :
1768 0 : _cairo_array_init (&font->output, sizeof (char));
1769 0 : status = _cairo_array_grow_by (&font->output, 4096);
1770 0 : if (unlikely (status))
1771 0 : goto fail2;
1772 :
1773 0 : font->subset_font_name = strdup (subset_name);
1774 0 : if (unlikely (font->subset_font_name == NULL)) {
1775 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1776 0 : goto fail2;
1777 : }
1778 0 : font->x_min = (int16_t) be16_to_cpu (head.x_min);
1779 0 : font->y_min = (int16_t) be16_to_cpu (head.y_min);
1780 0 : font->x_max = (int16_t) be16_to_cpu (head.x_max);
1781 0 : font->y_max = (int16_t) be16_to_cpu (head.y_max);
1782 0 : font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
1783 0 : font->descent = (int16_t) be16_to_cpu (hhea.descender);
1784 0 : font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
1785 0 : if (font->units_per_em == 0)
1786 0 : font->units_per_em = 1000;
1787 :
1788 0 : font->font_name = NULL;
1789 0 : status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
1790 : &font->ps_name,
1791 : &font->font_name);
1792 0 : if (_cairo_status_is_error (status))
1793 0 : goto fail3;
1794 :
1795 : /* If the PS name is not found, create a CairoFont-x-y name. */
1796 0 : if (font->ps_name == NULL) {
1797 0 : font->ps_name = malloc (30);
1798 0 : if (unlikely (font->ps_name == NULL)) {
1799 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1800 0 : goto fail3;
1801 : }
1802 :
1803 0 : snprintf(font->ps_name, 30, "CairoFont-%u-%u",
1804 : scaled_font_subset->font_id,
1805 : scaled_font_subset->subset_id);
1806 : }
1807 :
1808 0 : font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
1809 0 : if (unlikely (font->widths == NULL)) {
1810 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1811 0 : goto fail4;
1812 : }
1813 :
1814 0 : status = cairo_cff_font_create_set_widths (font);
1815 0 : if (unlikely (status))
1816 0 : goto fail5;
1817 :
1818 0 : font->data_length = data_length;
1819 0 : font->data = malloc (data_length);
1820 0 : if (unlikely (font->data == NULL)) {
1821 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1822 0 : goto fail5;
1823 : }
1824 0 : status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font,
1825 : TT_TAG_CFF, 0, font->data,
1826 : &font->data_length);
1827 0 : if (unlikely (status))
1828 0 : goto fail6;
1829 :
1830 0 : font->data_end = font->data + font->data_length;
1831 :
1832 0 : status = cff_dict_init (&font->top_dict);
1833 0 : if (unlikely (status))
1834 0 : goto fail6;
1835 :
1836 0 : status = cff_dict_init (&font->private_dict);
1837 0 : if (unlikely (status))
1838 0 : goto fail7;
1839 :
1840 0 : cff_index_init (&font->strings_index);
1841 0 : cff_index_init (&font->charstrings_index);
1842 0 : cff_index_init (&font->global_sub_index);
1843 0 : cff_index_init (&font->local_sub_index);
1844 0 : cff_index_init (&font->charstrings_subset_index);
1845 0 : cff_index_init (&font->strings_subset_index);
1846 0 : font->fdselect = NULL;
1847 0 : font->fd_dict = NULL;
1848 0 : font->fd_private_dict = NULL;
1849 0 : font->fd_local_sub_index = NULL;
1850 0 : font->fdselect_subset = NULL;
1851 0 : font->fd_subset_map = NULL;
1852 0 : font->private_dict_offset = NULL;
1853 :
1854 0 : *font_return = font;
1855 :
1856 0 : return CAIRO_STATUS_SUCCESS;
1857 :
1858 : fail7:
1859 0 : _cairo_hash_table_destroy (font->top_dict);
1860 : fail6:
1861 0 : free (font->data);
1862 : fail5:
1863 0 : free (font->widths);
1864 : fail4:
1865 0 : if (font->font_name)
1866 0 : free (font->font_name);
1867 : fail3:
1868 0 : free (font->subset_font_name);
1869 : fail2:
1870 0 : _cairo_array_fini (&font->output);
1871 0 : free (font);
1872 :
1873 0 : return status;
1874 : }
1875 :
1876 : static void
1877 0 : cairo_cff_font_destroy (cairo_cff_font_t *font)
1878 : {
1879 : unsigned int i;
1880 :
1881 0 : free (font->widths);
1882 0 : if (font->font_name)
1883 0 : free (font->font_name);
1884 0 : free (font->ps_name);
1885 0 : free (font->subset_font_name);
1886 0 : _cairo_array_fini (&font->output);
1887 0 : cff_dict_fini (font->top_dict);
1888 0 : cff_dict_fini (font->private_dict);
1889 0 : cff_index_fini (&font->strings_index);
1890 0 : cff_index_fini (&font->charstrings_index);
1891 0 : cff_index_fini (&font->global_sub_index);
1892 0 : cff_index_fini (&font->local_sub_index);
1893 0 : cff_index_fini (&font->charstrings_subset_index);
1894 0 : cff_index_fini (&font->strings_subset_index);
1895 :
1896 : /* If we bailed out early as a result of an error some of the
1897 : * following cairo_cff_font_t members may still be NULL */
1898 0 : if (font->fd_dict) {
1899 0 : for (i = 0; i < font->num_fontdicts; i++) {
1900 0 : if (font->fd_dict[i])
1901 0 : cff_dict_fini (font->fd_dict[i]);
1902 : }
1903 0 : free (font->fd_dict);
1904 : }
1905 0 : if (font->fd_subset_map)
1906 0 : free (font->fd_subset_map);
1907 0 : if (font->private_dict_offset)
1908 0 : free (font->private_dict_offset);
1909 :
1910 0 : if (font->is_cid) {
1911 0 : if (font->fdselect)
1912 0 : free (font->fdselect);
1913 0 : if (font->fdselect_subset)
1914 0 : free (font->fdselect_subset);
1915 0 : if (font->fd_private_dict) {
1916 0 : for (i = 0; i < font->num_fontdicts; i++) {
1917 0 : if (font->fd_private_dict[i])
1918 0 : cff_dict_fini (font->fd_private_dict[i]);
1919 : }
1920 0 : free (font->fd_private_dict);
1921 : }
1922 0 : if (font->fd_local_sub_index) {
1923 0 : for (i = 0; i < font->num_fontdicts; i++)
1924 0 : cff_index_fini (&font->fd_local_sub_index[i]);
1925 0 : free (font->fd_local_sub_index);
1926 : }
1927 : }
1928 :
1929 0 : if (font->data)
1930 0 : free (font->data);
1931 :
1932 0 : free (font);
1933 0 : }
1934 :
1935 : cairo_status_t
1936 0 : _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
1937 : const char *subset_name,
1938 : cairo_scaled_font_subset_t *font_subset)
1939 : {
1940 0 : cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
1941 : cairo_status_t status;
1942 0 : const char *data = NULL; /* squelch bogus compiler warning */
1943 0 : unsigned long length = 0; /* squelch bogus compiler warning */
1944 : unsigned int i;
1945 :
1946 0 : status = _cairo_cff_font_create (font_subset, &font, subset_name);
1947 0 : if (unlikely (status))
1948 0 : return status;
1949 :
1950 0 : status = cairo_cff_font_generate (font, &data, &length);
1951 0 : if (unlikely (status))
1952 0 : goto fail1;
1953 :
1954 0 : cff_subset->ps_name = strdup (font->ps_name);
1955 0 : if (unlikely (cff_subset->ps_name == NULL)) {
1956 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1957 0 : goto fail1;
1958 : }
1959 :
1960 0 : if (font->font_name) {
1961 0 : cff_subset->font_name = strdup (font->font_name);
1962 0 : if (cff_subset->font_name == NULL) {
1963 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1964 0 : goto fail2;
1965 : }
1966 : } else {
1967 0 : cff_subset->font_name = NULL;
1968 : }
1969 :
1970 0 : cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
1971 0 : if (unlikely (cff_subset->widths == NULL)) {
1972 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1973 0 : goto fail3;
1974 : }
1975 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
1976 0 : cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em;
1977 :
1978 0 : cff_subset->x_min = (double)font->x_min/font->units_per_em;
1979 0 : cff_subset->y_min = (double)font->y_min/font->units_per_em;
1980 0 : cff_subset->x_max = (double)font->x_max/font->units_per_em;
1981 0 : cff_subset->y_max = (double)font->y_max/font->units_per_em;
1982 0 : cff_subset->ascent = (double)font->ascent/font->units_per_em;
1983 0 : cff_subset->descent = (double)font->descent/font->units_per_em;
1984 :
1985 0 : cff_subset->data = malloc (length);
1986 0 : if (unlikely (cff_subset->data == NULL)) {
1987 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1988 0 : goto fail4;
1989 : }
1990 :
1991 0 : memcpy (cff_subset->data, data, length);
1992 0 : cff_subset->data_length = length;
1993 :
1994 0 : cairo_cff_font_destroy (font);
1995 :
1996 0 : return CAIRO_STATUS_SUCCESS;
1997 :
1998 : fail4:
1999 0 : free (cff_subset->widths);
2000 : fail3:
2001 0 : if (cff_subset->font_name)
2002 0 : free (cff_subset->font_name);
2003 : fail2:
2004 0 : free (cff_subset->ps_name);
2005 : fail1:
2006 0 : cairo_cff_font_destroy (font);
2007 :
2008 0 : return status;
2009 : }
2010 :
2011 : void
2012 0 : _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
2013 : {
2014 0 : free (subset->ps_name);
2015 0 : if (subset->font_name)
2016 0 : free (subset->font_name);
2017 0 : free (subset->widths);
2018 0 : free (subset->data);
2019 0 : }
2020 :
2021 : static cairo_int_status_t
2022 0 : _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset,
2023 : cairo_cff_font_t **font_return,
2024 : const char *subset_name)
2025 : {
2026 : cairo_status_t status;
2027 : cairo_cff_font_t *font;
2028 :
2029 0 : font = malloc (sizeof (cairo_cff_font_t));
2030 0 : if (unlikely (font == NULL))
2031 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2032 :
2033 0 : font->backend = NULL;
2034 0 : font->scaled_font_subset = scaled_font_subset;
2035 :
2036 0 : _cairo_array_init (&font->output, sizeof (char));
2037 0 : status = _cairo_array_grow_by (&font->output, 4096);
2038 0 : if (unlikely (status))
2039 0 : goto fail1;
2040 :
2041 0 : font->subset_font_name = strdup (subset_name);
2042 0 : if (unlikely (font->subset_font_name == NULL)) {
2043 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2044 0 : goto fail1;
2045 : }
2046 :
2047 0 : font->ps_name = strdup (subset_name);
2048 0 : if (unlikely (font->ps_name == NULL)) {
2049 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2050 0 : goto fail2;
2051 : }
2052 0 : font->font_name = NULL;
2053 :
2054 0 : font->x_min = 0;
2055 0 : font->y_min = 0;
2056 0 : font->x_max = 0;
2057 0 : font->y_max = 0;
2058 0 : font->ascent = 0;
2059 0 : font->descent = 0;
2060 :
2061 0 : font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
2062 0 : if (unlikely (font->widths == NULL)) {
2063 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2064 0 : goto fail3;
2065 : }
2066 :
2067 0 : font->data_length = 0;
2068 0 : font->data = NULL;
2069 0 : font->data_end = NULL;
2070 :
2071 0 : status = cff_dict_init (&font->top_dict);
2072 0 : if (unlikely (status))
2073 0 : goto fail4;
2074 :
2075 0 : status = cff_dict_init (&font->private_dict);
2076 0 : if (unlikely (status))
2077 0 : goto fail5;
2078 :
2079 0 : cff_index_init (&font->strings_index);
2080 0 : cff_index_init (&font->charstrings_index);
2081 0 : cff_index_init (&font->global_sub_index);
2082 0 : cff_index_init (&font->local_sub_index);
2083 0 : cff_index_init (&font->charstrings_subset_index);
2084 0 : cff_index_init (&font->strings_subset_index);
2085 0 : font->fdselect = NULL;
2086 0 : font->fd_dict = NULL;
2087 0 : font->fd_private_dict = NULL;
2088 0 : font->fd_local_sub_index = NULL;
2089 0 : font->fdselect_subset = NULL;
2090 0 : font->fd_subset_map = NULL;
2091 0 : font->private_dict_offset = NULL;
2092 :
2093 0 : *font_return = font;
2094 :
2095 0 : return CAIRO_STATUS_SUCCESS;
2096 :
2097 : fail5:
2098 0 : _cairo_hash_table_destroy (font->top_dict);
2099 : fail4:
2100 0 : free (font->widths);
2101 : fail3:
2102 0 : if (font->font_name)
2103 0 : free (font->font_name);
2104 0 : free (font->ps_name);
2105 : fail2:
2106 0 : free (font->subset_font_name);
2107 : fail1:
2108 0 : _cairo_array_fini (&font->output);
2109 0 : free (font);
2110 0 : return status;
2111 : }
2112 :
2113 : static cairo_int_status_t
2114 0 : cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
2115 : cairo_type2_charstrings_t *type2_subset,
2116 : const char **data,
2117 : unsigned long *length)
2118 : {
2119 : cairo_int_status_t status;
2120 : cff_header_t header;
2121 : cairo_array_t *charstring;
2122 : unsigned char buf[40];
2123 : unsigned char *end_buf;
2124 : unsigned int i;
2125 :
2126 : /* Create header */
2127 0 : header.major = 1;
2128 0 : header.minor = 0;
2129 0 : header.header_size = 4;
2130 0 : header.offset_size = 4;
2131 0 : font->header = &header;
2132 :
2133 : /* Create Top Dict */
2134 0 : font->is_cid = FALSE;
2135 0 : end_buf = encode_integer (buf, type2_subset->x_min);
2136 0 : end_buf = encode_integer (end_buf, type2_subset->y_min);
2137 0 : end_buf = encode_integer (end_buf, type2_subset->x_max);
2138 0 : end_buf = encode_integer (end_buf, type2_subset->y_max);
2139 0 : status = cff_dict_set_operands (font->top_dict,
2140 0 : FONTBBOX_OP, buf, end_buf - buf);
2141 0 : if (unlikely (status))
2142 0 : return status;
2143 :
2144 0 : end_buf = encode_integer_max (buf, 0);
2145 0 : status = cff_dict_set_operands (font->top_dict,
2146 0 : CHARSTRINGS_OP, buf, end_buf - buf);
2147 0 : if (unlikely (status))
2148 0 : return status;
2149 :
2150 0 : status = cff_dict_set_operands (font->top_dict,
2151 0 : FDSELECT_OP, buf, end_buf - buf);
2152 0 : if (unlikely (status))
2153 0 : return status;
2154 :
2155 0 : status = cff_dict_set_operands (font->top_dict,
2156 0 : FDARRAY_OP, buf, end_buf - buf);
2157 0 : if (unlikely (status))
2158 0 : return status;
2159 :
2160 0 : status = cff_dict_set_operands (font->top_dict,
2161 0 : CHARSET_OP, buf, end_buf - buf);
2162 0 : if (unlikely (status))
2163 0 : return status;
2164 :
2165 0 : status = cairo_cff_font_set_ros_strings (font);
2166 0 : if (unlikely (status))
2167 0 : return status;
2168 :
2169 : /* Create CID FD dictionary */
2170 0 : status = cairo_cff_font_create_cid_fontdict (font);
2171 0 : if (unlikely (status))
2172 0 : return status;
2173 :
2174 : /* Create charstrings */
2175 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
2176 0 : charstring = _cairo_array_index(&type2_subset->charstrings, i);
2177 :
2178 0 : status = cff_index_append (&font->charstrings_subset_index,
2179 0 : _cairo_array_index (charstring, 0),
2180 : _cairo_array_num_elements (charstring));
2181 :
2182 0 : if (unlikely (status))
2183 0 : return status;
2184 : }
2185 :
2186 0 : status = cairo_cff_font_write_subset (font);
2187 0 : if (unlikely (status))
2188 0 : return status;
2189 :
2190 0 : *data = _cairo_array_index (&font->output, 0);
2191 0 : *length = _cairo_array_num_elements (&font->output);
2192 :
2193 0 : return CAIRO_STATUS_SUCCESS;
2194 : }
2195 :
2196 : cairo_status_t
2197 0 : _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
2198 : const char *subset_name,
2199 : cairo_scaled_font_subset_t *font_subset)
2200 : {
2201 0 : cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
2202 : cairo_status_t status;
2203 0 : const char *data = NULL; /* squelch bogus compiler warning */
2204 0 : unsigned long length = 0; /* squelch bogus compiler warning */
2205 : unsigned int i;
2206 : cairo_type2_charstrings_t type2_subset;
2207 :
2208 0 : status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
2209 0 : if (unlikely (status))
2210 0 : return status;
2211 :
2212 0 : status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
2213 0 : if (unlikely (status))
2214 0 : goto fail1;
2215 :
2216 0 : status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
2217 0 : if (unlikely (status))
2218 0 : goto fail2;
2219 :
2220 0 : cff_subset->font_name = NULL;
2221 0 : cff_subset->ps_name = strdup (font->ps_name);
2222 0 : if (unlikely (cff_subset->ps_name == NULL)) {
2223 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2224 0 : goto fail2;
2225 : }
2226 :
2227 0 : cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
2228 0 : if (unlikely (cff_subset->widths == NULL)) {
2229 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2230 0 : goto fail3;
2231 : }
2232 :
2233 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
2234 0 : cff_subset->widths[i] = (double)type2_subset.widths[i]/1000;
2235 :
2236 0 : cff_subset->x_min = (double)type2_subset.x_min/1000;
2237 0 : cff_subset->y_min = (double)type2_subset.y_min/1000;
2238 0 : cff_subset->x_max = (double)type2_subset.x_max/1000;
2239 0 : cff_subset->y_max = (double)type2_subset.y_max/1000;
2240 0 : cff_subset->ascent = (double)type2_subset.y_max/1000;
2241 0 : cff_subset->descent = (double)type2_subset.y_min/1000;
2242 :
2243 0 : cff_subset->data = malloc (length);
2244 0 : if (unlikely (cff_subset->data == NULL)) {
2245 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2246 0 : goto fail4;
2247 : }
2248 :
2249 0 : memcpy (cff_subset->data, data, length);
2250 0 : cff_subset->data_length = length;
2251 0 : cff_subset->data_length = length;
2252 :
2253 0 : _cairo_type2_charstrings_fini (&type2_subset);
2254 0 : cairo_cff_font_destroy (font);
2255 :
2256 0 : return CAIRO_STATUS_SUCCESS;
2257 :
2258 : fail4:
2259 0 : free (cff_subset->widths);
2260 : fail3:
2261 0 : free (cff_subset->ps_name);
2262 : fail2:
2263 0 : _cairo_type2_charstrings_fini (&type2_subset);
2264 : fail1:
2265 0 : cairo_cff_font_destroy (font);
2266 :
2267 0 : return status;
2268 : }
2269 :
2270 : void
2271 0 : _cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
2272 : {
2273 0 : free (subset->ps_name);
2274 0 : free (subset->widths);
2275 0 : free (subset->data);
2276 0 : }
2277 :
2278 : #endif /* CAIRO_HAS_FONT_SUBSET */
|