in class/System.Windows/System.Windows/:
[moon.git] / cairo / src / cairo-cff-subset.c
blob008cc68a34b85a541d2db2e03b9c0ccd7b120933
1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2006 Adrian Johnson
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
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/
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.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is Adrian Johnson.
32 * Contributor(s):
33 * Adrian Johnson <ajohnson@redneon.com>
34 * Eugeniy Meshcheryakov <eugen@debian.org>
38 * Useful links:
39 * http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf
42 #define _BSD_SOURCE /* for snprintf(), strdup() */
43 #include "cairoint.h"
45 #if CAIRO_HAS_FONT_SUBSET
47 #include "cairo-scaled-font-subsets-private.h"
48 #include "cairo-truetype-subset-private.h"
49 #include <string.h>
51 /* CFF Dict Operators. If the high byte is 0 the command is encoded
52 * with a single byte. */
53 #define BASEFONTNAME_OP 0x0c16
54 #define CIDCOUNT_OP 0x0c22
55 #define CHARSET_OP 0x000f
56 #define CHARSTRINGS_OP 0x0011
57 #define COPYRIGHT_OP 0x0c00
58 #define ENCODING_OP 0x0010
59 #define FAMILYNAME_OP 0x0003
60 #define FDARRAY_OP 0x0c24
61 #define FDSELECT_OP 0x0c25
62 #define FONTBBOX_OP 0x0005
63 #define FONTNAME_OP 0x0c26
64 #define FULLNAME_OP 0x0002
65 #define LOCAL_SUB_OP 0x0013
66 #define NOTICE_OP 0x0001
67 #define POSTSCRIPT_OP 0x0c15
68 #define PRIVATE_OP 0x0012
69 #define ROS_OP 0x0c1e
70 #define UNIQUEID_OP 0x000d
71 #define VERSION_OP 0x0000
72 #define WEIGHT_OP 0x0004
73 #define XUID_OP 0x000e
75 #define NUM_STD_STRINGS 391
77 typedef struct _cff_header {
78 uint8_t major;
79 uint8_t minor;
80 uint8_t header_size;
81 uint8_t offset_size;
82 } cff_header_t;
84 typedef struct _cff_index_element {
85 cairo_bool_t is_copy;
86 unsigned char *data;
87 int length;
88 } cff_index_element_t;
90 typedef struct _cff_dict_operator {
91 cairo_hash_entry_t base;
93 unsigned short operator;
94 unsigned char *operand;
95 int operand_length;
96 int operand_offset;
97 } cff_dict_operator_t;
99 typedef struct _cairo_cff_font {
101 cairo_scaled_font_subset_t *scaled_font_subset;
102 const cairo_scaled_font_backend_t *backend;
104 /* Font Data */
105 unsigned char *data;
106 unsigned long data_length;
107 unsigned char *current_ptr;
108 unsigned char *data_end;
109 cff_header_t *header;
110 char *font_name;
111 cairo_hash_table_t *top_dict;
112 cairo_hash_table_t *private_dict;
113 cairo_array_t strings_index;
114 cairo_array_t charstrings_index;
115 cairo_array_t global_sub_index;
116 cairo_array_t local_sub_index;
117 int num_glyphs;
118 cairo_bool_t is_cid;
120 /* CID Font Data */
121 int *fdselect;
122 unsigned int num_fontdicts;
123 cairo_hash_table_t **fd_dict;
124 cairo_hash_table_t **fd_private_dict;
125 cairo_array_t *fd_local_sub_index;
127 /* Subsetted Font Data */
128 char *subset_font_name;
129 cairo_array_t charstrings_subset_index;
130 cairo_array_t strings_subset_index;
131 int *fdselect_subset;
132 unsigned int num_subset_fontdicts;
133 int *fd_subset_map;
134 int *private_dict_offset;
135 cairo_array_t output;
137 /* Subset Metrics */
138 int *widths;
139 int x_min, y_min, x_max, y_max;
140 int ascent, descent;
142 } cairo_cff_font_t;
144 /* Encoded integer using maximum sized encoding. This is required for
145 * operands that are later modified after encoding. */
146 static unsigned char *
147 encode_integer_max (unsigned char *p, int i)
149 *p++ = 29;
150 *p++ = i >> 24;
151 *p++ = (i >> 16) & 0xff;
152 *p++ = (i >> 8) & 0xff;
153 *p++ = i & 0xff;
154 return p;
157 static unsigned char *
158 encode_integer (unsigned char *p, int i)
160 if (i >= -107 && i <= 107) {
161 *p++ = i + 139;
162 } else if (i >= 108 && i <= 1131) {
163 i -= 108;
164 *p++ = (i >> 8)+ 247;
165 *p++ = i & 0xff;
166 } else if (i >= -1131 && i <= -108) {
167 i = -i - 108;
168 *p++ = (i >> 8)+ 251;
169 *p++ = i & 0xff;
170 } else if (i >= -32768 && i <= 32767) {
171 *p++ = 28;
172 *p++ = (i >> 8) & 0xff;
173 *p++ = i & 0xff;
174 } else {
175 p = encode_integer_max (p, i);
177 return p;
180 static unsigned char *
181 decode_integer (unsigned char *p, int *integer)
183 if (*p == 28) {
184 *integer = (int)(p[1]<<8 | p[2]);
185 p += 3;
186 } else if (*p == 29) {
187 *integer = (int)((p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]);
188 p += 5;
189 } else if (*p >= 32 && *p <= 246) {
190 *integer = *p++ - 139;
191 } else if (*p <= 250) {
192 *integer = (p[0] - 247) * 256 + p[1] + 108;
193 p += 2;
194 } else if (*p <= 254) {
195 *integer = -(p[0] - 251) * 256 - p[1] - 108;
196 p += 2;
197 } else {
198 *integer = 0;
199 p += 1;
201 return p;
204 static unsigned char *
205 decode_operator (unsigned char *p, unsigned short *operator)
207 unsigned short op = 0;
209 op = *p++;
210 if (op == 12) {
211 op <<= 8;
212 op |= *p++;
214 *operator = op;
215 return p;
218 /* return 0 if not an operand */
219 static int
220 operand_length (unsigned char *p)
222 unsigned char *begin = p;
224 if (*p == 28)
225 return 3;
227 if (*p == 29)
228 return 5;
230 if (*p >= 32 && *p <= 246)
231 return 1;
233 if (*p >= 247 && *p <= 254)
234 return 2;
236 if (*p == 30) {
237 while ((*p & 0x0f) != 0x0f)
238 p++;
239 return p - begin + 1;
242 return 0;
245 static unsigned char *
246 encode_index_offset (unsigned char *p, int offset_size, unsigned long offset)
248 while (--offset_size >= 0) {
249 p[offset_size] = (unsigned char) (offset & 0xff);
250 offset >>= 8;
252 return p + offset_size;
255 static unsigned long
256 decode_index_offset(unsigned char *p, int off_size)
258 unsigned long offset = 0;
260 while (off_size-- > 0)
261 offset = offset*256 + *p++;
262 return offset;
265 static void
266 cff_index_init (cairo_array_t *index)
268 _cairo_array_init (index, sizeof (cff_index_element_t));
271 static cairo_int_status_t
272 cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_ptr)
274 cff_index_element_t element;
275 unsigned char *data, *p;
276 cairo_status_t status;
277 int offset_size, count, start, i;
278 int end = 0;
280 p = *ptr;
281 if (p + 2 > end_ptr)
282 return CAIRO_INT_STATUS_UNSUPPORTED;
283 count = be16_to_cpu( *((uint16_t *)p) );
284 p += 2;
285 if (count > 0) {
286 offset_size = *p++;
287 if (p + (count + 1)*offset_size > end_ptr)
288 return CAIRO_INT_STATUS_UNSUPPORTED;
289 data = p + offset_size*(count + 1) - 1;
290 start = decode_index_offset (p, offset_size);
291 p += offset_size;
292 for (i = 0; i < count; i++) {
293 end = decode_index_offset (p, offset_size);
294 p += offset_size;
295 if (p > end_ptr)
296 return CAIRO_INT_STATUS_UNSUPPORTED;
297 element.length = end - start;
298 element.is_copy = FALSE;
299 element.data = data + start;
300 status = _cairo_array_append (index, &element);
301 if (status)
302 return status;
303 start = end;
305 p = data + end;
307 *ptr = p;
309 return CAIRO_STATUS_SUCCESS;
312 static cairo_status_t
313 cff_index_write (cairo_array_t *index, cairo_array_t *output)
315 int offset_size;
316 int offset;
317 int num_elem;
318 int i;
319 cff_index_element_t *element;
320 uint16_t count;
321 unsigned char buf[5];
322 cairo_status_t status;
324 num_elem = _cairo_array_num_elements (index);
325 count = cpu_to_be16 ((uint16_t) num_elem);
326 status = _cairo_array_append_multiple (output, &count, 2);
327 if (status)
328 return status;
330 if (num_elem == 0)
331 return CAIRO_STATUS_SUCCESS;
333 /* Find maximum offset to determine offset size */
334 offset = 1;
335 for (i = 0; i < num_elem; i++) {
336 element = _cairo_array_index (index, i);
337 offset += element->length;
339 if (offset < 0x100)
340 offset_size = 1;
341 else if (offset < 0x10000)
342 offset_size = 2;
343 else if (offset < 0x1000000)
344 offset_size = 3;
345 else
346 offset_size = 4;
348 buf[0] = (unsigned char) offset_size;
349 status = _cairo_array_append (output, buf);
350 if (status)
351 return status;
353 offset = 1;
354 encode_index_offset (buf, offset_size, offset);
355 status = _cairo_array_append_multiple (output, buf, offset_size);
356 if (status)
357 return status;
359 for (i = 0; i < num_elem; i++) {
360 element = _cairo_array_index (index, i);
361 offset += element->length;
362 encode_index_offset (buf, offset_size, offset);
363 status = _cairo_array_append_multiple (output, buf, offset_size);
364 if (status)
365 return status;
368 for (i = 0; i < num_elem; i++) {
369 element = _cairo_array_index (index, i);
370 status = _cairo_array_append_multiple (output,
371 element->data,
372 element->length);
373 if (status)
374 return status;
376 return CAIRO_STATUS_SUCCESS;
379 static cairo_status_t
380 cff_index_append (cairo_array_t *index, unsigned char *object , int length)
382 cff_index_element_t element;
384 element.length = length;
385 element.is_copy = FALSE;
386 element.data = object;
388 return _cairo_array_append (index, &element);
391 static cairo_status_t
392 cff_index_append_copy (cairo_array_t *index,
393 const unsigned char *object,
394 unsigned int length)
396 cff_index_element_t element;
397 cairo_status_t status;
399 element.length = length;
400 element.is_copy = TRUE;
401 element.data = malloc (element.length);
402 if (element.data == NULL)
403 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
405 memcpy (element.data, object, element.length);
407 status = _cairo_array_append (index, &element);
408 if (status) {
409 free (element.data);
410 return status;
413 return CAIRO_STATUS_SUCCESS;
416 static void
417 cff_index_fini (cairo_array_t *index)
419 cff_index_element_t *element;
420 int i;
422 for (i = 0; i < _cairo_array_num_elements (index); i++) {
423 element = _cairo_array_index (index, i);
424 if (element->is_copy)
425 free (element->data);
427 _cairo_array_fini (index);
430 static cairo_bool_t
431 _cairo_cff_dict_equal (const void *key_a, const void *key_b)
433 const cff_dict_operator_t *op_a = key_a;
434 const cff_dict_operator_t *op_b = key_b;
436 return op_a->operator == op_b->operator;
439 static cairo_status_t
440 cff_dict_init (cairo_hash_table_t **dict)
442 *dict = _cairo_hash_table_create (_cairo_cff_dict_equal);
443 if (*dict == NULL)
444 return CAIRO_STATUS_NO_MEMORY;
446 return CAIRO_STATUS_SUCCESS;
449 static void
450 _cairo_dict_init_key (cff_dict_operator_t *key, int operator)
452 key->base.hash = (unsigned long) operator;
453 key->operator = operator;
456 static cairo_status_t
457 cff_dict_create_operator (int operator,
458 unsigned char *operand,
459 int operand_length,
460 cff_dict_operator_t **out)
462 cff_dict_operator_t *op;
464 op = malloc (sizeof (cff_dict_operator_t));
465 if (op == NULL)
466 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
468 _cairo_dict_init_key (op, operator);
469 op->operand = malloc (operand_length);
470 if (op->operand == NULL) {
471 free (op);
472 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
475 memcpy (op->operand, operand, operand_length);
476 op->operand_length = operand_length;
477 op->operand_offset = -1;
479 *out = op;
480 return CAIRO_STATUS_SUCCESS;
483 static cairo_status_t
484 cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size)
486 unsigned char *end;
487 cairo_array_t operands;
488 cff_dict_operator_t *op;
489 unsigned short operator;
490 cairo_status_t status = CAIRO_STATUS_SUCCESS;
491 int size;
493 end = p + dict_size;
494 _cairo_array_init (&operands, 1);
495 while (p < end) {
496 size = operand_length (p);
497 if (size != 0) {
498 status = _cairo_array_append_multiple (&operands, p, size);
499 if (status)
500 goto fail;
502 p += size;
503 } else {
504 p = decode_operator (p, &operator);
505 status = cff_dict_create_operator (operator,
506 _cairo_array_index (&operands, 0),
507 _cairo_array_num_elements (&operands),
508 &op);
509 if (status)
510 goto fail;
512 status = _cairo_hash_table_insert (dict, &op->base);
513 if (status)
514 goto fail;
516 _cairo_array_truncate (&operands, 0);
520 fail:
521 _cairo_array_fini (&operands);
523 return status;
526 static void
527 cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
529 cff_dict_operator_t key, *op;
531 _cairo_dict_init_key (&key, operator);
532 if (_cairo_hash_table_lookup (dict, &key.base,
533 (cairo_hash_entry_t **) &op))
535 free (op->operand);
536 _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
537 free (op);
541 static unsigned char *
542 cff_dict_get_operands (cairo_hash_table_t *dict,
543 unsigned short operator,
544 int *size)
546 cff_dict_operator_t key, *op;
548 _cairo_dict_init_key (&key, operator);
549 if (_cairo_hash_table_lookup (dict, &key.base,
550 (cairo_hash_entry_t **) &op))
552 *size = op->operand_length;
553 return op->operand;
556 return NULL;
559 static cairo_status_t
560 cff_dict_set_operands (cairo_hash_table_t *dict,
561 unsigned short operator,
562 unsigned char *operand,
563 int size)
565 cff_dict_operator_t key, *op;
566 cairo_status_t status;
568 _cairo_dict_init_key (&key, operator);
569 if (_cairo_hash_table_lookup (dict, &key.base,
570 (cairo_hash_entry_t **) &op))
572 free (op->operand);
573 op->operand = malloc (size);
574 if (op->operand == NULL)
575 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
577 memcpy (op->operand, operand, size);
578 op->operand_length = size;
580 else
582 status = cff_dict_create_operator (operator, operand, size, &op);
583 if (status)
584 return status;
586 status = _cairo_hash_table_insert (dict, &op->base);
587 if (status)
588 return status;
591 return CAIRO_STATUS_SUCCESS;
594 static int
595 cff_dict_get_location (cairo_hash_table_t *dict,
596 unsigned short operator,
597 int *size)
599 cff_dict_operator_t key, *op;
601 _cairo_dict_init_key (&key, operator);
602 if (_cairo_hash_table_lookup (dict, &key.base,
603 (cairo_hash_entry_t **) &op))
605 *size = op->operand_length;
606 return op->operand_offset;
609 return -1;
612 typedef struct _dict_write_info {
613 cairo_array_t *output;
614 cairo_status_t status;
615 } dict_write_info_t;
617 static void
618 cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info)
620 unsigned char data;
622 op->operand_offset = _cairo_array_num_elements (write_info->output);
623 write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length);
624 if (write_info->status)
625 return;
627 if (op->operator & 0xff00) {
628 data = op->operator >> 8;
629 write_info->status = _cairo_array_append (write_info->output, &data);
630 if (write_info->status)
631 return;
633 data = op->operator & 0xff;
634 write_info->status = _cairo_array_append (write_info->output, &data);
637 static void
638 _cairo_dict_collect (void *entry, void *closure)
640 dict_write_info_t *write_info = closure;
641 cff_dict_operator_t *op = entry;
643 if (write_info->status)
644 return;
646 /* The ROS operator is handled separately in cff_dict_write() */
647 if (op->operator != ROS_OP)
648 cairo_dict_write_operator (op, write_info);
651 static cairo_status_t
652 cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output)
654 dict_write_info_t write_info;
655 cff_dict_operator_t key, *op;
657 write_info.output = output;
658 write_info.status = CAIRO_STATUS_SUCCESS;
660 /* The CFF specification requires that the Top Dict of CID fonts
661 * begin with the ROS operator. */
662 _cairo_dict_init_key (&key, ROS_OP);
663 if (_cairo_hash_table_lookup (dict, &key.base,
664 (cairo_hash_entry_t **) &op))
665 cairo_dict_write_operator (op, &write_info);
667 _cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info);
669 return write_info.status;
672 static void
673 cff_dict_fini (cairo_hash_table_t *dict)
675 cff_dict_operator_t *entry;
677 while (1) {
678 entry = _cairo_hash_table_random_entry (dict, NULL);
679 if (entry == NULL)
680 break;
681 free (entry->operand);
682 _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) entry);
683 free (entry);
685 _cairo_hash_table_destroy (dict);
688 static cairo_int_status_t
689 cairo_cff_font_read_header (cairo_cff_font_t *font)
691 if (font->data_length < sizeof (cff_header_t))
692 return CAIRO_INT_STATUS_UNSUPPORTED;
694 font->header = (cff_header_t *) font->data;
695 font->current_ptr = font->data + font->header->header_size;
697 return CAIRO_STATUS_SUCCESS;
700 static cairo_int_status_t
701 cairo_cff_font_read_name (cairo_cff_font_t *font)
703 cairo_array_t index;
704 cairo_int_status_t status;
706 /* The original font name is not used in the subset. Read the name
707 * index to skip over it. */
708 cff_index_init (&index);
709 status = cff_index_read (&index, &font->current_ptr, font->data_end);
710 cff_index_fini (&index);
712 return status;
715 static cairo_int_status_t
716 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)
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;
730 status = cff_dict_read (private_dict, ptr, size);
731 if (status)
732 return status;
734 operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
735 if (operand) {
736 decode_integer (operand, &offset);
737 p = ptr + offset;
738 status = cff_index_read (local_sub_index, &p, font->data_end);
739 if (status)
740 return status;
742 /* Use maximum sized encoding to reserve space for later modification. */
743 end_buf = encode_integer_max (buf, 0);
744 status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
745 if (status)
746 return status;
749 return CAIRO_STATUS_SUCCESS;
752 static cairo_int_status_t
753 cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p)
755 int type, num_ranges, first, last, fd, i, j;
757 font->fdselect = calloc (font->num_glyphs, sizeof (int));
758 if (font->fdselect == NULL)
759 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
761 type = *p++;
762 if (type == 0)
764 for (i = 0; i < font->num_glyphs; i++)
765 font->fdselect[i] = *p++;
766 } else if (type == 3) {
767 num_ranges = be16_to_cpu( *((uint16_t *)p) );
768 p += 2;
769 for (i = 0; i < num_ranges; i++)
771 first = be16_to_cpu( *((uint16_t *)p) );
772 p += 2;
773 fd = *p++;
774 last = be16_to_cpu( *((uint16_t *)p) );
775 for (j = first; j < last; j++)
776 font->fdselect[j] = fd;
778 } else {
779 return CAIRO_INT_STATUS_UNSUPPORTED;
782 return CAIRO_STATUS_SUCCESS;
785 static cairo_int_status_t
786 cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
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;
798 cff_index_init (&index);
799 status = cff_index_read (&index, &ptr, font->data_end);
800 if (status)
801 goto fail;
803 font->num_fontdicts = _cairo_array_num_elements (&index);
805 font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
806 if (font->fd_dict == NULL) {
807 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
808 goto fail;
811 font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
812 if (font->fd_private_dict == NULL) {
813 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
814 goto fail;
817 font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts);
818 if (font->fd_local_sub_index == NULL) {
819 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
820 goto fail;
823 for (i = 0; i < font->num_fontdicts; i++) {
824 status = cff_dict_init (&font->fd_dict[i]);
825 if (status)
826 goto fail;
828 element = _cairo_array_index (&index, i);
829 status = cff_dict_read (font->fd_dict[i], element->data, element->length);
830 if (status)
831 goto fail;
833 operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size);
834 if (operand == NULL) {
835 status = CAIRO_INT_STATUS_UNSUPPORTED;
836 goto fail;
838 operand = decode_integer (operand, &size);
839 decode_integer (operand, &offset);
840 status = cff_dict_init (&font->fd_private_dict[i]);
841 if (status)
842 goto fail;
844 cff_index_init (&font->fd_local_sub_index[i]);
845 status = cairo_cff_font_read_private_dict (font,
846 font->fd_private_dict[i],
847 &font->fd_local_sub_index[i],
848 font->data + offset,
849 size);
850 if (status)
851 goto fail;
853 /* Set integer operand to max value to use max size encoding to reserve
854 * space for any value later */
855 end_buf = encode_integer_max (buf, 0);
856 end_buf = encode_integer_max (end_buf, 0);
857 status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf);
858 if (status)
859 goto fail;
862 return CAIRO_STATUS_SUCCESS;
864 fail:
865 cff_index_fini (&index);
867 return status;
870 static cairo_int_status_t
871 cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
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;
883 cff_index_init (&index);
884 status = cff_index_read (&index, &font->current_ptr, font->data_end);
885 if (status)
886 goto fail;
888 element = _cairo_array_index (&index, 0);
889 status = cff_dict_read (font->top_dict, element->data, element->length);
890 if (status)
891 goto fail;
893 if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL)
894 font->is_cid = TRUE;
895 else
896 font->is_cid = FALSE;
898 operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size);
899 decode_integer (operand, &offset);
900 p = font->data + offset;
901 status = cff_index_read (&font->charstrings_index, &p, font->data_end);
902 if (status)
903 goto fail;
904 font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index);
906 if (font->is_cid) {
907 operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
908 decode_integer (operand, &offset);
909 status = cairo_cff_font_read_fdselect (font, font->data + offset);
910 if (status)
911 goto fail;
913 operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
914 decode_integer (operand, &offset);
915 status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
916 if (status)
917 goto fail;
918 } else {
919 operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
920 operand = decode_integer (operand, &size);
921 decode_integer (operand, &offset);
922 status = cairo_cff_font_read_private_dict (font,
923 font->private_dict,
924 &font->local_sub_index,
925 font->data + offset,
926 size);
927 if (status)
928 goto fail;
931 /* Use maximum sized encoding to reserve space for later modification. */
932 end_buf = encode_integer_max (buf, 0);
933 status = cff_dict_set_operands (font->top_dict,
934 CHARSTRINGS_OP, buf, end_buf - buf);
935 if (status)
936 goto fail;
938 status = cff_dict_set_operands (font->top_dict,
939 FDSELECT_OP, buf, end_buf - buf);
940 if (status)
941 goto fail;
943 status = cff_dict_set_operands (font->top_dict,
944 FDARRAY_OP, buf, end_buf - buf);
945 if (status)
946 goto fail;
948 status = cff_dict_set_operands (font->top_dict,
949 CHARSET_OP, buf, end_buf - buf);
950 if (status)
951 goto fail;
953 cff_dict_remove (font->top_dict, ENCODING_OP);
954 cff_dict_remove (font->top_dict, PRIVATE_OP);
956 /* Remove the unique identifier operators as the subsetted font is
957 * not the same is the original font. */
958 cff_dict_remove (font->top_dict, UNIQUEID_OP);
959 cff_dict_remove (font->top_dict, XUID_OP);
961 fail:
962 cff_index_fini (&index);
964 return status;
967 static cairo_int_status_t
968 cairo_cff_font_read_strings (cairo_cff_font_t *font)
970 return cff_index_read (&font->strings_index, &font->current_ptr, font->data_end);
973 static cairo_int_status_t
974 cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font)
976 return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end);
979 typedef cairo_int_status_t
980 (*font_read_t) (cairo_cff_font_t *font);
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,
990 static cairo_int_status_t
991 cairo_cff_font_read_font (cairo_cff_font_t *font)
993 cairo_int_status_t status;
994 unsigned int i;
996 for (i = 0; i < ARRAY_LENGTH (font_read_funcs); i++) {
997 status = font_read_funcs[i] (font);
998 if (status)
999 return status;
1002 return CAIRO_STATUS_SUCCESS;
1005 static cairo_status_t
1006 cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
1008 cairo_status_t status;
1009 unsigned char buf[30];
1010 unsigned char *p;
1011 int sid1, sid2;
1012 const char *registry = "Adobe";
1013 const char *ordering = "Identity";
1015 sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
1016 status = cff_index_append_copy (&font->strings_subset_index,
1017 (unsigned char *)registry,
1018 strlen(registry));
1019 if (status)
1020 return status;
1022 sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
1023 status = cff_index_append_copy (&font->strings_subset_index,
1024 (unsigned char *)ordering,
1025 strlen(ordering));
1026 if (status)
1027 return status;
1029 p = encode_integer (buf, sid1);
1030 p = encode_integer (p, sid2);
1031 p = encode_integer (p, 0);
1032 status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
1033 if (status)
1034 return status;
1036 p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
1037 status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
1038 if (status)
1039 return status;
1041 return CAIRO_STATUS_SUCCESS;
1044 static cairo_status_t
1045 cairo_cff_font_subset_dict_string(cairo_cff_font_t *font,
1046 cairo_hash_table_t *dict,
1047 int operator)
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;
1056 p = cff_dict_get_operands (dict, operator, &size);
1057 if (!p)
1058 return CAIRO_STATUS_SUCCESS;
1060 decode_integer (p, &sid);
1061 if (sid < NUM_STD_STRINGS)
1062 return CAIRO_STATUS_SUCCESS;
1064 element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS);
1065 sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
1066 status = cff_index_append (&font->strings_subset_index, element->data, element->length);
1067 if (status)
1068 return status;
1070 p = encode_integer (buf, sid);
1071 status = cff_dict_set_operands (dict, operator, buf, p - buf);
1072 if (status)
1073 return status;
1075 return CAIRO_STATUS_SUCCESS;
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,
1090 static cairo_status_t
1091 cairo_cff_font_subset_dict_strings (cairo_cff_font_t *font,
1092 cairo_hash_table_t *dict)
1094 cairo_status_t status;
1095 unsigned int i;
1097 for (i = 0; i < ARRAY_LENGTH (dict_strings); i++) {
1098 status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]);
1099 if (status)
1100 return status;
1103 return CAIRO_STATUS_SUCCESS;
1106 static cairo_status_t
1107 cairo_cff_font_subset_charstrings (cairo_cff_font_t *font)
1109 cff_index_element_t *element;
1110 unsigned int i;
1111 cairo_status_t status;
1113 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
1114 element = _cairo_array_index (&font->charstrings_index,
1115 font->scaled_font_subset->glyphs[i]);
1116 status = cff_index_append (&font->charstrings_subset_index,
1117 element->data,
1118 element->length);
1119 if (status)
1120 return status;
1123 return CAIRO_STATUS_SUCCESS;
1126 static cairo_status_t
1127 cairo_cff_font_subset_fontdict (cairo_cff_font_t *font)
1129 unsigned int i;
1130 int fd;
1131 int *reverse_map;
1133 font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs,
1134 sizeof (int));
1135 if (font->fdselect_subset == NULL)
1136 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1138 font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int));
1139 if (font->fd_subset_map == NULL)
1140 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1142 font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int));
1143 if (font->private_dict_offset == NULL)
1144 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1146 reverse_map = calloc (font->num_fontdicts, sizeof (int));
1147 if (reverse_map == NULL)
1148 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1150 for (i = 0; i < font->num_fontdicts; i++)
1151 reverse_map[i] = -1;
1153 font->num_subset_fontdicts = 0;
1154 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
1155 fd = font->fdselect[font->scaled_font_subset->glyphs[i]];
1156 if (reverse_map[fd] < 0) {
1157 font->fd_subset_map[font->num_subset_fontdicts] = fd;
1158 reverse_map[fd] = font->num_subset_fontdicts++;
1160 font->fdselect_subset[i] = reverse_map[fd];
1163 free (reverse_map);
1165 return CAIRO_STATUS_SUCCESS;
1168 static cairo_status_t
1169 cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
1171 unsigned char buf[100];
1172 unsigned char *end_buf;
1173 cairo_status_t status;
1175 font->num_fontdicts = 1;
1176 font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
1177 if (font->fd_dict == NULL)
1178 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1180 if (cff_dict_init (&font->fd_dict[0])) {
1181 free (font->fd_dict);
1182 font->fd_dict = NULL;
1183 font->num_fontdicts = 0;
1184 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1187 font->fd_subset_map = malloc (sizeof (int));
1188 if (font->fd_subset_map == NULL)
1189 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1191 font->private_dict_offset = malloc (sizeof (int));
1192 if (font->private_dict_offset == NULL)
1193 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1195 font->fd_subset_map[0] = 0;
1196 font->num_subset_fontdicts = 1;
1198 /* Set integer operand to max value to use max size encoding to reserve
1199 * space for any value later */
1200 end_buf = encode_integer_max (buf, 0);
1201 end_buf = encode_integer_max (end_buf, 0);
1202 status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
1203 if (status)
1204 return status;
1206 return CAIRO_STATUS_SUCCESS;
1209 static cairo_status_t
1210 cairo_cff_font_subset_strings (cairo_cff_font_t *font)
1212 cairo_status_t status;
1213 unsigned int i;
1215 status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
1216 if (status)
1217 return status;
1219 if (font->is_cid) {
1220 for (i = 0; i < font->num_subset_fontdicts; i++) {
1221 status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
1222 if (status)
1223 return status;
1225 status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]);
1226 if (status)
1227 return status;
1229 } else {
1230 status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
1233 return status;
1236 static cairo_status_t
1237 cairo_cff_font_subset_font (cairo_cff_font_t *font)
1239 cairo_status_t status;
1241 status = cairo_cff_font_set_ros_strings (font);
1242 if (status)
1243 return status;
1245 status = cairo_cff_font_subset_charstrings (font);
1246 if (status)
1247 return status;
1249 if (font->is_cid)
1250 status = cairo_cff_font_subset_fontdict (font);
1251 else
1252 status = cairo_cff_font_create_cid_fontdict (font);
1253 if (status)
1254 return status;
1256 status = cairo_cff_font_subset_strings (font);
1257 if (status)
1258 return status;
1260 return status;
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 cairo_cff_font_set_topdict_operator_to_cur_pos (cairo_cff_font_t *font,
1269 int operator)
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;
1278 cur_pos = _cairo_array_num_elements (&font->output);
1279 buf_end = encode_integer_max (buf, cur_pos);
1280 offset = cff_dict_get_location (font->top_dict, operator, &size);
1281 assert (offset > 0);
1282 op_ptr = _cairo_array_index (&font->output, offset);
1283 memcpy (op_ptr, buf, buf_end - buf);
1286 static cairo_status_t
1287 cairo_cff_font_write_header (cairo_cff_font_t *font)
1289 return _cairo_array_append_multiple (&font->output,
1290 font->header,
1291 font->header->header_size);
1294 static cairo_status_t
1295 cairo_cff_font_write_name (cairo_cff_font_t *font)
1297 cairo_status_t status = CAIRO_STATUS_SUCCESS;
1298 cairo_array_t index;
1300 cff_index_init (&index);
1302 status = cff_index_append_copy (&index,
1303 (unsigned char *) font->subset_font_name,
1304 strlen(font->subset_font_name));
1305 if (status)
1306 goto FAIL;
1308 status = cff_index_write (&index, &font->output);
1309 if (status)
1310 goto FAIL;
1312 FAIL:
1313 cff_index_fini (&index);
1315 return status;
1318 static cairo_status_t
1319 cairo_cff_font_write_top_dict (cairo_cff_font_t *font)
1321 uint16_t count;
1322 unsigned char buf[10];
1323 unsigned char *p;
1324 int offset_index;
1325 int dict_start, dict_size;
1326 int offset_size = 4;
1327 cairo_status_t status;
1329 /* Write an index containing the top dict */
1331 count = cpu_to_be16 (1);
1332 status = _cairo_array_append_multiple (&font->output, &count, 2);
1333 if (status)
1334 return status;
1335 buf[0] = offset_size;
1336 status = _cairo_array_append (&font->output, buf);
1337 if (status)
1338 return status;
1339 encode_index_offset (buf, offset_size, 1);
1340 status = _cairo_array_append_multiple (&font->output, buf, offset_size);
1341 if (status)
1342 return status;
1344 /* Reserve space for last element of offset array and update after
1345 * dict is written */
1346 offset_index = _cairo_array_num_elements (&font->output);
1347 status = _cairo_array_append_multiple (&font->output, buf, offset_size);
1348 if (status)
1349 return status;
1351 dict_start = _cairo_array_num_elements (&font->output);
1352 status = cff_dict_write (font->top_dict, &font->output);
1353 if (status)
1354 return status;
1355 dict_size = _cairo_array_num_elements (&font->output) - dict_start;
1357 encode_index_offset (buf, offset_size, dict_size + 1);
1358 p = _cairo_array_index (&font->output, offset_index);
1359 memcpy (p, buf, offset_size);
1361 return CAIRO_STATUS_SUCCESS;
1364 static cairo_status_t
1365 cairo_cff_font_write_strings (cairo_cff_font_t *font)
1367 return cff_index_write (&font->strings_subset_index, &font->output);
1370 static cairo_status_t
1371 cairo_cff_font_write_global_subrs (cairo_cff_font_t *font)
1373 return cff_index_write (&font->global_sub_index, &font->output);
1376 static cairo_status_t
1377 cairo_cff_font_write_fdselect (cairo_cff_font_t *font)
1379 unsigned char data;
1380 unsigned int i;
1381 cairo_int_status_t status;
1383 cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP);
1385 if (font->is_cid) {
1386 data = 0;
1387 status = _cairo_array_append (&font->output, &data);
1388 if (status)
1389 return status;
1391 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
1392 data = font->fdselect_subset[i];
1393 status = _cairo_array_append (&font->output, &data);
1394 if (status)
1395 return status;
1397 } else {
1398 unsigned char byte;
1399 uint16_t word;
1401 status = _cairo_array_grow_by (&font->output, 9);
1402 if (status)
1403 return status;
1405 byte = 3;
1406 status = _cairo_array_append (&font->output, &byte);
1407 assert (status == CAIRO_STATUS_SUCCESS);
1409 word = cpu_to_be16 (1);
1410 status = _cairo_array_append_multiple (&font->output, &word, 2);
1411 assert (status == CAIRO_STATUS_SUCCESS);
1413 word = cpu_to_be16 (0);
1414 status = _cairo_array_append_multiple (&font->output, &word, 2);
1415 assert (status == CAIRO_STATUS_SUCCESS);
1417 byte = 0;
1418 status = _cairo_array_append (&font->output, &byte);
1419 assert (status == CAIRO_STATUS_SUCCESS);
1421 word = cpu_to_be16 (font->scaled_font_subset->num_glyphs);
1422 status = _cairo_array_append_multiple (&font->output, &word, 2);
1423 assert (status == CAIRO_STATUS_SUCCESS);
1426 return CAIRO_STATUS_SUCCESS;
1429 static cairo_status_t
1430 cairo_cff_font_write_charset (cairo_cff_font_t *font)
1432 unsigned char byte;
1433 uint16_t word;
1434 cairo_status_t status;
1436 cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
1437 status = _cairo_array_grow_by (&font->output, 5);
1438 if (status)
1439 return status;
1441 byte = 2;
1442 status = _cairo_array_append (&font->output, &byte);
1443 assert (status == CAIRO_STATUS_SUCCESS);
1445 word = cpu_to_be16 (1);
1446 status = _cairo_array_append_multiple (&font->output, &word, 2);
1447 assert (status == CAIRO_STATUS_SUCCESS);
1449 word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2);
1450 status = _cairo_array_append_multiple (&font->output, &word, 2);
1451 assert (status == CAIRO_STATUS_SUCCESS);
1453 return CAIRO_STATUS_SUCCESS;
1456 static cairo_status_t
1457 cairo_cff_font_write_charstrings (cairo_cff_font_t *font)
1459 cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP);
1461 return cff_index_write (&font->charstrings_subset_index, &font->output);
1464 static cairo_status_t
1465 cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
1467 unsigned int i;
1468 cairo_int_status_t status;
1469 uint32_t *offset_array;
1470 int offset_base;
1471 uint16_t count;
1472 uint8_t offset_size = 4;
1474 cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP);
1475 count = cpu_to_be16 (font->num_subset_fontdicts);
1476 status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t));
1477 if (status)
1478 return status;
1479 status = _cairo_array_append (&font->output, &offset_size);
1480 if (status)
1481 return status;
1482 status = _cairo_array_allocate (&font->output,
1483 (font->num_subset_fontdicts + 1)*offset_size,
1484 (void **) &offset_array);
1485 if (status)
1486 return status;
1487 offset_base = _cairo_array_num_elements (&font->output) - 1;
1488 *offset_array++ = cpu_to_be32(1);
1489 for (i = 0; i < font->num_subset_fontdicts; i++) {
1490 status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
1491 &font->output);
1492 if (status)
1493 return status;
1494 *offset_array++ = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
1497 return CAIRO_STATUS_SUCCESS;
1500 static cairo_status_t
1501 cairo_cff_font_write_private_dict (cairo_cff_font_t *font,
1502 int dict_num,
1503 cairo_hash_table_t *parent_dict,
1504 cairo_hash_table_t *private_dict)
1506 int offset;
1507 int size;
1508 unsigned char buf[10];
1509 unsigned char *buf_end;
1510 unsigned char *p;
1511 cairo_status_t status;
1513 /* Write private dict and update offset and size in top dict */
1514 font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output);
1515 status = cff_dict_write (private_dict, &font->output);
1516 if (status)
1517 return status;
1519 size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
1520 /* private entry has two operands - size and offset */
1521 buf_end = encode_integer_max (buf, size);
1522 buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]);
1523 offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size);
1524 assert (offset > 0);
1525 p = _cairo_array_index (&font->output, offset);
1526 memcpy (p, buf, buf_end - buf);
1528 return CAIRO_STATUS_SUCCESS;
1531 static cairo_status_t
1532 cairo_cff_font_write_local_sub (cairo_cff_font_t *font,
1533 int dict_num,
1534 cairo_hash_table_t *private_dict,
1535 cairo_array_t *local_sub_index)
1537 int offset;
1538 int size;
1539 unsigned char buf[10];
1540 unsigned char *buf_end;
1541 unsigned char *p;
1542 cairo_status_t status;
1544 if (_cairo_array_num_elements (local_sub_index) > 0) {
1545 /* Write local subroutines and update offset in private
1546 * dict. Local subroutines offset is relative to start of
1547 * private dict */
1548 offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
1549 buf_end = encode_integer_max (buf, offset);
1550 offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size);
1551 assert (offset > 0);
1552 p = _cairo_array_index (&font->output, offset);
1553 memcpy (p, buf, buf_end - buf);
1554 status = cff_index_write (local_sub_index, &font->output);
1555 if (status)
1556 return status;
1559 return CAIRO_STATUS_SUCCESS;
1563 static cairo_status_t
1564 cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font)
1566 unsigned int i;
1567 cairo_int_status_t status;
1569 if (font->is_cid) {
1570 for (i = 0; i < font->num_subset_fontdicts; i++) {
1571 status = cairo_cff_font_write_private_dict (
1572 font,
1574 font->fd_dict[font->fd_subset_map[i]],
1575 font->fd_private_dict[font->fd_subset_map[i]]);
1576 if (status)
1577 return status;
1580 for (i = 0; i < font->num_subset_fontdicts; i++) {
1581 status = cairo_cff_font_write_local_sub (
1582 font,
1584 font->fd_private_dict[font->fd_subset_map[i]],
1585 &font->fd_local_sub_index[font->fd_subset_map[i]]);
1586 if (status)
1587 return status;
1589 } else {
1590 status = cairo_cff_font_write_private_dict (font,
1592 font->fd_dict[0],
1593 font->private_dict);
1594 if (status)
1595 return status;
1597 status = cairo_cff_font_write_local_sub (font,
1599 font->private_dict,
1600 &font->local_sub_index);
1601 if (status)
1602 return status;
1605 return CAIRO_STATUS_SUCCESS;
1608 typedef cairo_status_t
1609 (*font_write_t) (cairo_cff_font_t *font);
1611 static const font_write_t font_write_funcs[] = {
1612 cairo_cff_font_write_header,
1613 cairo_cff_font_write_name,
1614 cairo_cff_font_write_top_dict,
1615 cairo_cff_font_write_strings,
1616 cairo_cff_font_write_global_subrs,
1617 cairo_cff_font_write_charset,
1618 cairo_cff_font_write_fdselect,
1619 cairo_cff_font_write_charstrings,
1620 cairo_cff_font_write_cid_fontdict,
1621 cairo_cff_font_write_cid_private_dict_and_local_sub,
1624 static cairo_status_t
1625 cairo_cff_font_write_subset (cairo_cff_font_t *font)
1627 cairo_int_status_t status;
1628 unsigned int i;
1630 for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) {
1631 status = font_write_funcs[i] (font);
1632 if (status)
1633 return status;
1636 return CAIRO_STATUS_SUCCESS;
1639 static cairo_int_status_t
1640 cairo_cff_font_generate (cairo_cff_font_t *font,
1641 const char **data,
1642 unsigned long *length)
1644 cairo_int_status_t status;
1646 status = cairo_cff_font_read_font (font);
1647 if (status)
1648 return status;
1650 status = cairo_cff_font_subset_font (font);
1651 if (status)
1652 return status;
1654 status = cairo_cff_font_write_subset (font);
1655 if (status)
1656 return status;
1658 *data = _cairo_array_index (&font->output, 0);
1659 *length = _cairo_array_num_elements (&font->output);
1661 return CAIRO_STATUS_SUCCESS;
1664 static cairo_int_status_t
1665 cairo_cff_font_create_set_widths (cairo_cff_font_t *font)
1667 unsigned long size;
1668 unsigned long long_entry_size;
1669 unsigned long short_entry_size;
1670 unsigned int i;
1671 tt_hhea_t hhea;
1672 int num_hmetrics;
1673 unsigned char buf[10];
1674 int glyph_index;
1675 cairo_int_status_t status;
1677 size = sizeof (tt_hhea_t);
1678 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
1679 TT_TAG_hhea, 0,
1680 (unsigned char*) &hhea, &size);
1681 if (status)
1682 return status;
1683 num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
1685 for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
1686 glyph_index = font->scaled_font_subset->glyphs[i];
1687 long_entry_size = 2 * sizeof (int16_t);
1688 short_entry_size = sizeof (int16_t);
1689 if (glyph_index < num_hmetrics) {
1690 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
1691 TT_TAG_hmtx,
1692 glyph_index * long_entry_size,
1693 buf, &short_entry_size);
1694 if (status)
1695 return status;
1697 else
1699 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
1700 TT_TAG_hmtx,
1701 (num_hmetrics - 1) * long_entry_size,
1702 buf, &short_entry_size);
1703 if (status)
1704 return status;
1706 font->widths[i] = be16_to_cpu (*((int16_t*)buf));
1709 return CAIRO_STATUS_SUCCESS;
1712 static cairo_int_status_t
1713 _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
1714 cairo_cff_font_t **font_return,
1715 const char *subset_name)
1717 const cairo_scaled_font_backend_t *backend;
1718 cairo_status_t status;
1719 cairo_cff_font_t *font;
1720 tt_head_t head;
1721 tt_hhea_t hhea;
1722 tt_name_t *name;
1723 tt_name_record_t *record;
1724 unsigned long size, data_length;
1725 int i, j;
1727 backend = scaled_font_subset->scaled_font->backend;
1728 if (!backend->load_truetype_table)
1729 return CAIRO_INT_STATUS_UNSUPPORTED;
1731 data_length = 0;
1732 status = backend->load_truetype_table( scaled_font_subset->scaled_font,
1733 TT_TAG_CFF, 0, NULL, &data_length);
1734 if (status)
1735 return status;
1737 size = sizeof (tt_head_t);
1738 status = backend->load_truetype_table (scaled_font_subset->scaled_font,
1739 TT_TAG_head, 0,
1740 (unsigned char *) &head, &size);
1741 if (status)
1742 return status;
1744 size = sizeof (tt_hhea_t);
1745 status = backend->load_truetype_table (scaled_font_subset->scaled_font,
1746 TT_TAG_hhea, 0,
1747 (unsigned char *) &hhea, &size);
1748 if (status)
1749 return status;
1751 size = 0;
1752 status = backend->load_truetype_table (scaled_font_subset->scaled_font,
1753 TT_TAG_hmtx, 0, NULL, &size);
1754 if (status)
1755 return status;
1757 size = 0;
1758 status = backend->load_truetype_table (scaled_font_subset->scaled_font,
1759 TT_TAG_name, 0, NULL, &size);
1760 if (status)
1761 return status;
1763 name = malloc (size);
1764 if (name == NULL)
1765 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1767 status = backend->load_truetype_table (scaled_font_subset->scaled_font,
1768 TT_TAG_name, 0,
1769 (unsigned char *) name, &size);
1770 if (status)
1771 goto fail1;
1773 font = malloc (sizeof (cairo_cff_font_t));
1774 if (font == NULL) {
1775 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1776 goto fail1;
1779 font->backend = backend;
1780 font->scaled_font_subset = scaled_font_subset;
1782 _cairo_array_init (&font->output, sizeof (char));
1783 status = _cairo_array_grow_by (&font->output, 4096);
1784 if (status)
1785 goto fail2;
1787 font->subset_font_name = strdup (subset_name);
1788 if (font->subset_font_name == NULL) {
1789 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1790 goto fail2;
1792 font->x_min = (int16_t) be16_to_cpu (head.x_min);
1793 font->y_min = (int16_t) be16_to_cpu (head.y_min);
1794 font->x_max = (int16_t) be16_to_cpu (head.x_max);
1795 font->y_max = (int16_t) be16_to_cpu (head.y_max);
1796 font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
1797 font->descent = (int16_t) be16_to_cpu (hhea.descender);
1799 /* Extract the font name from the name table. At present this
1800 * just looks for the Mac platform/Roman encoded font name. It
1801 * should be extended to use any suitable font name in the
1802 * name table. If the mac/roman font name is not found a
1803 * CairoFont-x-y name is created.
1805 font->font_name = NULL;
1806 for (i = 0; i < be16_to_cpu(name->num_records); i++) {
1807 record = &(name->records[i]);
1808 if ((be16_to_cpu (record->platform) == 1) &&
1809 (be16_to_cpu (record->encoding) == 0) &&
1810 (be16_to_cpu (record->name) == 4)) {
1811 font->font_name = malloc (be16_to_cpu(record->length) + 1);
1812 if (font->font_name) {
1813 strncpy(font->font_name,
1814 ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset),
1815 be16_to_cpu (record->length));
1816 font->font_name[be16_to_cpu (record->length)] = 0;
1818 break;
1822 if (font->font_name == NULL) {
1823 font->font_name = malloc (30);
1824 if (font->font_name == NULL) {
1825 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1826 goto fail3;
1828 snprintf(font->font_name, 30, "CairoFont-%u-%u",
1829 scaled_font_subset->font_id,
1830 scaled_font_subset->subset_id);
1833 for (i = 0, j = 0; font->font_name[j]; j++) {
1834 if (font->font_name[j] == ' ')
1835 continue;
1836 font->font_name[i++] = font->font_name[j];
1838 font->font_name[i] = '\0';
1840 font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
1841 if (font->widths == NULL) {
1842 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1843 goto fail4;
1846 status = cairo_cff_font_create_set_widths (font);
1847 if (status)
1848 goto fail5;
1850 font->data_length = data_length;
1851 font->data = malloc (data_length);
1852 if (font->data == NULL) {
1853 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1854 goto fail5;
1856 status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font,
1857 TT_TAG_CFF, 0, font->data,
1858 &font->data_length);
1859 if (status)
1860 goto fail6;
1862 font->data_end = font->data + font->data_length;
1864 status = cff_dict_init (&font->top_dict);
1865 if (status)
1866 goto fail6;
1868 status = cff_dict_init (&font->private_dict);
1869 if (status)
1870 goto fail7;
1872 cff_index_init (&font->strings_index);
1873 cff_index_init (&font->charstrings_index);
1874 cff_index_init (&font->global_sub_index);
1875 cff_index_init (&font->local_sub_index);
1876 cff_index_init (&font->charstrings_subset_index);
1877 cff_index_init (&font->strings_subset_index);
1878 font->fdselect = NULL;
1879 font->fd_dict = NULL;
1880 font->fd_private_dict = NULL;
1881 font->fd_local_sub_index = NULL;
1882 font->fdselect_subset = NULL;
1883 font->fd_subset_map = NULL;
1884 font->private_dict_offset = NULL;
1886 free (name);
1887 *font_return = font;
1889 return CAIRO_STATUS_SUCCESS;
1891 fail7:
1892 _cairo_hash_table_destroy (font->top_dict);
1893 fail6:
1894 free (font->data);
1895 fail5:
1896 free (font->widths);
1897 fail4:
1898 free (font->font_name);
1899 fail3:
1900 free (font->subset_font_name);
1901 fail2:
1902 _cairo_array_fini (&font->output);
1903 free (font);
1904 fail1:
1905 free (name);
1906 return status;
1909 static void
1910 cairo_cff_font_destroy (cairo_cff_font_t *font)
1912 unsigned int i;
1914 free (font->widths);
1915 free (font->font_name);
1916 free (font->subset_font_name);
1917 _cairo_array_fini (&font->output);
1918 cff_dict_fini (font->top_dict);
1919 cff_dict_fini (font->private_dict);
1920 cff_index_fini (&font->strings_index);
1921 cff_index_fini (&font->charstrings_index);
1922 cff_index_fini (&font->global_sub_index);
1923 cff_index_fini (&font->local_sub_index);
1924 cff_index_fini (&font->charstrings_subset_index);
1925 cff_index_fini (&font->strings_subset_index);
1927 /* If we bailed out early as a result of an error some of the
1928 * following cairo_cff_font_t members may still be NULL */
1929 if (font->fd_dict) {
1930 for (i = 0; i < font->num_fontdicts; i++) {
1931 if (font->fd_dict[i])
1932 cff_dict_fini (font->fd_dict[i]);
1934 free (font->fd_dict);
1936 if (font->fd_subset_map)
1937 free (font->fd_subset_map);
1938 if (font->private_dict_offset)
1939 free (font->private_dict_offset);
1941 if (font->is_cid) {
1942 if (font->fdselect)
1943 free (font->fdselect);
1944 if (font->fdselect_subset)
1945 free (font->fdselect_subset);
1946 if (font->fd_private_dict) {
1947 for (i = 0; i < font->num_fontdicts; i++) {
1948 if (font->fd_private_dict[i])
1949 cff_dict_fini (font->fd_private_dict[i]);
1951 free (font->fd_private_dict);
1953 if (font->fd_local_sub_index) {
1954 for (i = 0; i < font->num_fontdicts; i++)
1955 cff_index_fini (&font->fd_local_sub_index[i]);
1956 free (font->fd_local_sub_index);
1960 if (font->data)
1961 free (font->data);
1963 free (font);
1966 cairo_status_t
1967 _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
1968 const char *subset_name,
1969 cairo_scaled_font_subset_t *font_subset)
1971 cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
1972 cairo_status_t status;
1973 const char *data = NULL; /* squelch bogus compiler warning */
1974 unsigned long length = 0; /* squelch bogus compiler warning */
1975 unsigned int i;
1977 status = _cairo_cff_font_create (font_subset, &font, subset_name);
1978 if (status)
1979 return status;
1981 status = cairo_cff_font_generate (font, &data, &length);
1982 if (status)
1983 goto fail1;
1985 cff_subset->base_font = strdup (font->font_name);
1986 if (cff_subset->base_font == NULL) {
1987 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1988 goto fail1;
1991 cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
1992 if (cff_subset->widths == NULL) {
1993 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1994 goto fail2;
1996 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
1997 cff_subset->widths[i] = font->widths[i];
1999 cff_subset->x_min = font->x_min;
2000 cff_subset->y_min = font->y_min;
2001 cff_subset->x_max = font->x_max;
2002 cff_subset->y_max = font->y_max;
2003 cff_subset->ascent = font->ascent;
2004 cff_subset->descent = font->descent;
2006 cff_subset->data = malloc (length);
2007 if (cff_subset->data == NULL) {
2008 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2009 goto fail3;
2012 memcpy (cff_subset->data, data, length);
2013 cff_subset->data_length = length;
2015 cairo_cff_font_destroy (font);
2017 return CAIRO_STATUS_SUCCESS;
2019 fail3:
2020 free (cff_subset->widths);
2021 fail2:
2022 free (cff_subset->base_font);
2023 fail1:
2024 cairo_cff_font_destroy (font);
2026 return status;
2029 void
2030 _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
2032 free (subset->base_font);
2033 free (subset->widths);
2034 free (subset->data);
2037 static cairo_int_status_t
2038 _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset,
2039 cairo_cff_font_t **font_return,
2040 const char *subset_name)
2042 cairo_status_t status;
2043 cairo_cff_font_t *font;
2045 font = malloc (sizeof (cairo_cff_font_t));
2046 if (font == NULL)
2047 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2049 font->backend = NULL;
2050 font->scaled_font_subset = scaled_font_subset;
2052 _cairo_array_init (&font->output, sizeof (char));
2053 status = _cairo_array_grow_by (&font->output, 4096);
2054 if (status)
2055 goto fail1;
2057 font->subset_font_name = strdup (subset_name);
2058 if (font->subset_font_name == NULL) {
2059 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2060 goto fail1;
2063 font->font_name = strdup (subset_name);
2064 if (font->subset_font_name == NULL) {
2065 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2066 goto fail2;
2069 font->x_min = 0;
2070 font->y_min = 0;
2071 font->x_max = 0;
2072 font->y_max = 0;
2073 font->ascent = 0;
2074 font->descent = 0;
2076 font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
2077 if (font->widths == NULL) {
2078 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2079 goto fail3;
2082 font->data_length = 0;
2083 font->data = NULL;
2084 font->data_end = NULL;
2086 status = cff_dict_init (&font->top_dict);
2087 if (status)
2088 goto fail4;
2090 status = cff_dict_init (&font->private_dict);
2091 if (status)
2092 goto fail5;
2094 cff_index_init (&font->strings_index);
2095 cff_index_init (&font->charstrings_index);
2096 cff_index_init (&font->global_sub_index);
2097 cff_index_init (&font->local_sub_index);
2098 cff_index_init (&font->charstrings_subset_index);
2099 cff_index_init (&font->strings_subset_index);
2100 font->fdselect = NULL;
2101 font->fd_dict = NULL;
2102 font->fd_private_dict = NULL;
2103 font->fd_local_sub_index = NULL;
2104 font->fdselect_subset = NULL;
2105 font->fd_subset_map = NULL;
2106 font->private_dict_offset = NULL;
2108 *font_return = font;
2110 return CAIRO_STATUS_SUCCESS;
2112 fail5:
2113 _cairo_hash_table_destroy (font->top_dict);
2114 fail4:
2115 free (font->widths);
2116 fail3:
2117 free (font->font_name);
2118 fail2:
2119 free (font->subset_font_name);
2120 fail1:
2121 _cairo_array_fini (&font->output);
2122 free (font);
2123 return status;
2126 static cairo_int_status_t
2127 cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
2128 cairo_type2_charstrings_t *type2_subset,
2129 const char **data,
2130 unsigned long *length)
2132 cairo_int_status_t status;
2133 cff_header_t header;
2134 cairo_array_t *charstring;
2135 unsigned char buf[40];
2136 unsigned char *end_buf;
2137 unsigned int i;
2139 /* Create header */
2140 header.major = 1;
2141 header.minor = 0;
2142 header.header_size = 4;
2143 header.offset_size = 4;
2144 font->header = &header;
2146 /* Create Top Dict */
2147 font->is_cid = FALSE;
2148 end_buf = encode_integer (buf, type2_subset->x_min);
2149 end_buf = encode_integer (end_buf, type2_subset->y_min);
2150 end_buf = encode_integer (end_buf, type2_subset->x_max);
2151 end_buf = encode_integer (end_buf, type2_subset->y_max);
2152 status = cff_dict_set_operands (font->top_dict,
2153 FONTBBOX_OP, buf, end_buf - buf);
2154 if (status)
2155 return status;
2157 end_buf = encode_integer_max (buf, 0);
2158 status = cff_dict_set_operands (font->top_dict,
2159 CHARSTRINGS_OP, buf, end_buf - buf);
2160 if (status)
2161 return status;
2163 status = cff_dict_set_operands (font->top_dict,
2164 FDSELECT_OP, buf, end_buf - buf);
2165 if (status)
2166 return status;
2168 status = cff_dict_set_operands (font->top_dict,
2169 FDARRAY_OP, buf, end_buf - buf);
2170 if (status)
2171 return status;
2173 status = cff_dict_set_operands (font->top_dict,
2174 CHARSET_OP, buf, end_buf - buf);
2175 if (status)
2176 return status;
2178 status = cairo_cff_font_set_ros_strings (font);
2179 if (status)
2180 return status;
2182 /* Create CID FD dictionary */
2183 status = cairo_cff_font_create_cid_fontdict (font);
2184 if (status)
2185 return status;
2187 /* Create charstrings */
2188 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
2189 charstring = _cairo_array_index(&type2_subset->charstrings, i);
2191 status = cff_index_append (&font->charstrings_subset_index,
2192 _cairo_array_index (charstring, 0),
2193 _cairo_array_num_elements (charstring));
2195 if (status)
2196 return status;
2199 status = cairo_cff_font_write_subset (font);
2200 if (status)
2201 return status;
2203 *data = _cairo_array_index (&font->output, 0);
2204 *length = _cairo_array_num_elements (&font->output);
2206 return CAIRO_STATUS_SUCCESS;
2209 cairo_status_t
2210 _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
2211 const char *subset_name,
2212 cairo_scaled_font_subset_t *font_subset)
2214 cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
2215 cairo_status_t status;
2216 const char *data = NULL; /* squelch bogus compiler warning */
2217 unsigned long length = 0; /* squelch bogus compiler warning */
2218 unsigned int i;
2219 cairo_type2_charstrings_t type2_subset;
2221 status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
2222 if (status)
2223 return status;
2225 status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
2226 if (status)
2227 goto fail1;
2229 status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
2230 if (status)
2231 goto fail2;
2233 cff_subset->base_font = strdup (font->font_name);
2234 if (cff_subset->base_font == NULL) {
2235 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2236 goto fail2;
2239 cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
2240 if (cff_subset->widths == NULL) {
2241 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2242 goto fail3;
2244 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
2245 cff_subset->widths[i] = type2_subset.widths[i];
2247 cff_subset->x_min = type2_subset.x_min;
2248 cff_subset->y_min = type2_subset.y_min;
2249 cff_subset->x_max = type2_subset.x_max;
2250 cff_subset->y_max = type2_subset.y_max;
2251 cff_subset->ascent = type2_subset.y_max;
2252 cff_subset->descent = type2_subset.y_min;
2254 cff_subset->data = malloc (length);
2255 if (cff_subset->data == NULL) {
2256 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2257 goto fail4;
2260 memcpy (cff_subset->data, data, length);
2261 cff_subset->data_length = length;
2262 cff_subset->data_length = length;
2264 _cairo_type2_charstrings_fini (&type2_subset);
2265 cairo_cff_font_destroy (font);
2267 return CAIRO_STATUS_SUCCESS;
2269 fail4:
2270 free (cff_subset->widths);
2271 fail3:
2272 free (cff_subset->base_font);
2273 fail2:
2274 _cairo_type2_charstrings_fini (&type2_subset);
2275 fail1:
2276 cairo_cff_font_destroy (font);
2278 return status;
2281 void
2282 _cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
2284 free (subset->base_font);
2285 free (subset->widths);
2286 free (subset->data);
2289 #endif /* CAIRO_HAS_FONT_SUBSET */