Rev 1897 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1897 | Rev 3959 | ||
---|---|---|---|
Line -... | Line 1... | ||
- | 1 | /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ |
|
1 | /* cairo - a vector graphics library with display and print output |
2 | /* cairo - a vector graphics library with display and print output |
2 | * |
3 | * |
3 | * Copyright © 2006 Adrian Johnson |
4 | * Copyright © 2006 Adrian Johnson |
4 | * |
5 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * This library is free software; you can redistribute it and/or |
Line 34... | Line 35... | ||
34 | * Eugeniy Meshcheryakov |
35 | * Eugeniy Meshcheryakov |
35 | */ |
36 | */ |
Line 36... | Line 37... | ||
36 | 37 | ||
37 | /* |
38 | /* |
38 | * Useful links: |
39 | * Useful links: |
- | 40 | * http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5176.CFF.pdf |
|
39 | * http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf |
41 | * http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5177.Type2.pdf |
Line 40... | Line 42... | ||
40 | */ |
42 | */ |
41 | 43 | ||
- | 44 | #define _BSD_SOURCE /* for snprintf(), strdup() */ |
|
- | 45 | #include "cairoint.h" |
|
42 | #define _BSD_SOURCE /* for snprintf(), strdup() */ |
46 | |
Line 43... | Line 47... | ||
43 | #include "cairoint.h" |
47 | #include "cairo-array-private.h" |
Line 44... | Line 48... | ||
44 | #include "cairo-error-private.h" |
48 | #include "cairo-error-private.h" |
45 | 49 | ||
46 | #if CAIRO_HAS_FONT_SUBSET |
50 | #if CAIRO_HAS_FONT_SUBSET |
- | 51 | ||
Line 47... | Line 52... | ||
47 | 52 | #include "cairo-scaled-font-subsets-private.h" |
|
48 | #include "cairo-scaled-font-subsets-private.h" |
53 | #include "cairo-truetype-subset-private.h" |
49 | #include "cairo-truetype-subset-private.h" |
54 | #include |
50 | #include |
55 | #include |
51 | 56 | ||
52 | /* CFF Dict Operators. If the high byte is 0 the command is encoded |
57 | /* CFF Dict Operators. If the high byte is 0 the command is encoded |
53 | * with a single byte. */ |
58 | * with a single byte. */ |
- | 59 | #define BASEFONTNAME_OP 0x0c16 |
|
54 | #define BASEFONTNAME_OP 0x0c16 |
60 | #define CIDCOUNT_OP 0x0c22 |
55 | #define CIDCOUNT_OP 0x0c22 |
61 | #define CHARSET_OP 0x000f |
56 | #define CHARSET_OP 0x000f |
62 | #define CHARSTRINGS_OP 0x0011 |
57 | #define CHARSTRINGS_OP 0x0011 |
63 | #define COPYRIGHT_OP 0x0c00 |
58 | #define COPYRIGHT_OP 0x0c00 |
64 | #define DEFAULTWIDTH_OP 0x0014 |
- | 65 | #define ENCODING_OP 0x0010 |
|
59 | #define ENCODING_OP 0x0010 |
66 | #define FAMILYNAME_OP 0x0003 |
60 | #define FAMILYNAME_OP 0x0003 |
67 | #define FDARRAY_OP 0x0c24 |
61 | #define FDARRAY_OP 0x0c24 |
68 | #define FDSELECT_OP 0x0c25 |
- | 69 | #define FONTBBOX_OP 0x0005 |
|
62 | #define FDSELECT_OP 0x0c25 |
70 | #define FONTMATRIX_OP 0x0c07 |
63 | #define FONTBBOX_OP 0x0005 |
71 | #define FONTNAME_OP 0x0c26 |
64 | #define FONTNAME_OP 0x0c26 |
72 | #define FULLNAME_OP 0x0002 |
65 | #define FULLNAME_OP 0x0002 |
73 | #define LOCAL_SUB_OP 0x0013 |
66 | #define LOCAL_SUB_OP 0x0013 |
74 | #define NOMINALWIDTH_OP 0x0015 |
Line 73... | Line 81... | ||
73 | #define WEIGHT_OP 0x0004 |
81 | #define WEIGHT_OP 0x0004 |
74 | #define XUID_OP 0x000e |
82 | #define XUID_OP 0x000e |
Line 75... | Line 83... | ||
75 | 83 | ||
Line -... | Line 84... | ||
- | 84 | #define NUM_STD_STRINGS 391 |
|
- | 85 | ||
- | 86 | /* Type 2 Charstring operators */ |
|
- | 87 | #define TYPE2_hstem 0x0001 |
|
- | 88 | #define TYPE2_vstem 0x0003 |
|
- | 89 | #define TYPE2_callsubr 0x000a |
|
- | 90 | ||
- | 91 | #define TYPE2_return 0x000b |
|
- | 92 | #define TYPE2_endchar 0x000e |
|
- | 93 | ||
- | 94 | #define TYPE2_hstemhm 0x0012 |
|
- | 95 | #define TYPE2_hintmask 0x0013 |
|
- | 96 | #define TYPE2_cntrmask 0x0014 |
|
- | 97 | #define TYPE2_vstemhm 0x0017 |
|
- | 98 | #define TYPE2_callgsubr 0x001d |
|
- | 99 | ||
- | 100 | #define TYPE2_rmoveto 0x0015 |
|
- | 101 | #define TYPE2_hmoveto 0x0016 |
|
- | 102 | #define TYPE2_vmoveto 0x0004 |
|
- | 103 | ||
- | 104 | ||
- | 105 | #define MAX_SUBROUTINE_NESTING 10 /* From Type2 Charstring spec */ |
|
76 | #define NUM_STD_STRINGS 391 |
106 | |
77 | 107 | ||
78 | typedef struct _cff_header { |
108 | typedef struct _cff_header { |
79 | uint8_t major; |
109 | uint8_t major; |
80 | uint8_t minor; |
110 | uint8_t minor; |
Line 114... | Line 144... | ||
114 | cairo_hash_table_t *private_dict; |
144 | cairo_hash_table_t *private_dict; |
115 | cairo_array_t strings_index; |
145 | cairo_array_t strings_index; |
116 | cairo_array_t charstrings_index; |
146 | cairo_array_t charstrings_index; |
117 | cairo_array_t global_sub_index; |
147 | cairo_array_t global_sub_index; |
118 | cairo_array_t local_sub_index; |
148 | cairo_array_t local_sub_index; |
- | 149 | unsigned char *charset; |
|
119 | int num_glyphs; |
150 | int num_glyphs; |
120 | cairo_bool_t is_cid; |
151 | cairo_bool_t is_cid; |
- | 152 | cairo_bool_t is_opentype; |
|
121 | int units_per_em; |
153 | int units_per_em; |
- | 154 | int global_sub_bias; |
|
- | 155 | int local_sub_bias; |
|
- | 156 | double default_width; |
|
- | 157 | double nominal_width; |
|
Line 122... | Line 158... | ||
122 | 158 | ||
123 | /* CID Font Data */ |
159 | /* CID Font Data */ |
124 | int *fdselect; |
160 | int *fdselect; |
125 | unsigned int num_fontdicts; |
161 | unsigned int num_fontdicts; |
126 | cairo_hash_table_t **fd_dict; |
162 | cairo_hash_table_t **fd_dict; |
127 | cairo_hash_table_t **fd_private_dict; |
163 | cairo_hash_table_t **fd_private_dict; |
- | 164 | cairo_array_t *fd_local_sub_index; |
|
- | 165 | int *fd_local_sub_bias; |
|
- | 166 | double *fd_default_width; |
|
Line 128... | Line 167... | ||
128 | cairo_array_t *fd_local_sub_index; |
167 | double *fd_nominal_width; |
129 | 168 | ||
130 | /* Subsetted Font Data */ |
169 | /* Subsetted Font Data */ |
131 | char *subset_font_name; |
170 | char *subset_font_name; |
- | 171 | cairo_array_t charstrings_subset_index; |
|
132 | cairo_array_t charstrings_subset_index; |
172 | cairo_array_t strings_subset_index; |
133 | cairo_array_t strings_subset_index; |
173 | int euro_sid; |
134 | int *fdselect_subset; |
174 | int *fdselect_subset; |
135 | unsigned int num_subset_fontdicts; |
175 | unsigned int num_subset_fontdicts; |
- | 176 | int *fd_subset_map; |
|
- | 177 | int *private_dict_offset; |
|
- | 178 | cairo_bool_t subset_subroutines; |
|
- | 179 | cairo_bool_t *global_subs_used; |
|
136 | int *fd_subset_map; |
180 | cairo_bool_t *local_subs_used; |
Line 137... | Line 181... | ||
137 | int *private_dict_offset; |
181 | cairo_bool_t **fd_local_subs_used; |
138 | cairo_array_t output; |
182 | cairo_array_t output; |
139 | 183 | ||
140 | /* Subset Metrics */ |
184 | /* Subset Metrics */ |
Line -... | Line 185... | ||
- | 185 | int *widths; |
|
- | 186 | int x_min, y_min, x_max, y_max; |
|
- | 187 | int ascent, descent; |
|
- | 188 | ||
- | 189 | /* Type 2 charstring data */ |
|
- | 190 | int type2_stack_size; |
|
- | 191 | int type2_stack_top_value; |
|
- | 192 | cairo_bool_t type2_stack_top_is_int; |
|
- | 193 | int type2_num_hints; |
|
- | 194 | int type2_hintmask_bytes; |
|
- | 195 | int type2_nesting_level; |
|
- | 196 | cairo_bool_t type2_seen_first_int; |
|
- | 197 | cairo_bool_t type2_find_width; |
|
141 | int *widths; |
198 | cairo_bool_t type2_found_width; |
Line 142... | Line 199... | ||
142 | int x_min, y_min, x_max, y_max; |
199 | int type2_width; |
143 | int ascent, descent; |
200 | cairo_bool_t type2_has_path; |
144 | 201 | ||
Line 202... | Line 259... | ||
202 | p += 1; |
259 | p += 1; |
203 | } |
260 | } |
204 | return p; |
261 | return p; |
205 | } |
262 | } |
Line -... | Line 263... | ||
- | 263 | ||
- | 264 | static char * |
|
- | 265 | decode_nibble (int n, char *buf) |
|
- | 266 | { |
|
- | 267 | switch (n) |
|
- | 268 | { |
|
- | 269 | case 0xa: |
|
- | 270 | *buf++ = '.'; |
|
- | 271 | break; |
|
- | 272 | case 0xb: |
|
- | 273 | *buf++ = 'E'; |
|
- | 274 | break; |
|
- | 275 | case 0xc: |
|
- | 276 | *buf++ = 'E'; |
|
- | 277 | *buf++ = '-'; |
|
- | 278 | break; |
|
- | 279 | case 0xd: |
|
- | 280 | *buf++ = '-'; |
|
- | 281 | break; |
|
- | 282 | case 0xe: |
|
- | 283 | *buf++ = '-'; |
|
- | 284 | break; |
|
- | 285 | case 0xf: |
|
- | 286 | break; |
|
- | 287 | default: |
|
- | 288 | *buf++ = '0' + n; |
|
- | 289 | break; |
|
- | 290 | } |
|
- | 291 | ||
- | 292 | return buf; |
|
- | 293 | } |
|
- | 294 | ||
- | 295 | static unsigned char * |
|
- | 296 | decode_real (unsigned char *p, double *real) |
|
- | 297 | { |
|
- | 298 | struct lconv *locale_data; |
|
- | 299 | const char *decimal_point; |
|
- | 300 | int decimal_point_len; |
|
- | 301 | int n; |
|
- | 302 | char buffer[100]; |
|
- | 303 | char buffer2[200]; |
|
- | 304 | char *q; |
|
- | 305 | char *buf = buffer; |
|
- | 306 | char *buf_end = buffer + sizeof (buffer); |
|
- | 307 | ||
- | 308 | locale_data = localeconv (); |
|
- | 309 | decimal_point = locale_data->decimal_point; |
|
- | 310 | decimal_point_len = strlen (decimal_point); |
|
- | 311 | ||
- | 312 | assert (decimal_point_len != 0); |
|
- | 313 | assert (sizeof(buffer) + decimal_point_len < sizeof(buffer2)); |
|
- | 314 | ||
- | 315 | p++; |
|
- | 316 | while (buf + 2 < buf_end) { |
|
- | 317 | n = *p >> 4; |
|
- | 318 | buf = decode_nibble (n, buf); |
|
- | 319 | n = *p & 0x0f; |
|
- | 320 | buf = decode_nibble (n, buf); |
|
- | 321 | if ((*p & 0x0f) == 0x0f) { |
|
- | 322 | p++; |
|
- | 323 | break; |
|
- | 324 | } |
|
- | 325 | p++; |
|
- | 326 | }; |
|
- | 327 | *buf = 0; |
|
- | 328 | ||
- | 329 | buf = buffer; |
|
- | 330 | if (strchr (buffer, '.')) { |
|
- | 331 | q = strchr (buffer, '.'); |
|
- | 332 | strncpy (buffer2, buffer, q - buffer); |
|
- | 333 | buf = buffer2 + (q - buffer); |
|
- | 334 | strncpy (buf, decimal_point, decimal_point_len); |
|
- | 335 | buf += decimal_point_len; |
|
- | 336 | strcpy (buf, q + 1); |
|
- | 337 | buf = buffer2; |
|
- | 338 | } |
|
- | 339 | ||
- | 340 | if (sscanf(buf, "%lf", real) != 1) |
|
- | 341 | *real = 0.0; |
|
- | 342 | ||
- | 343 | return p; |
|
- | 344 | } |
|
- | 345 | ||
- | 346 | static unsigned char * |
|
- | 347 | decode_number (unsigned char *p, double *number) |
|
- | 348 | { |
|
- | 349 | if (*p == 30) { |
|
- | 350 | p = decode_real (p, number); |
|
- | 351 | } else { |
|
- | 352 | int i; |
|
- | 353 | p = decode_integer (p, &i); |
|
- | 354 | *number = i; |
|
- | 355 | } |
|
- | 356 | return p; |
|
- | 357 | } |
|
206 | 358 | ||
207 | static unsigned char * |
359 | static unsigned char * |
208 | decode_operator (unsigned char *p, unsigned short *operator) |
360 | decode_operator (unsigned char *p, unsigned short *operator) |
209 | { |
361 | { |
Line 368... | Line 520... | ||
368 | return status; |
520 | return status; |
369 | } |
521 | } |
Line 370... | Line 522... | ||
370 | 522 | ||
371 | for (i = 0; i < num_elem; i++) { |
523 | for (i = 0; i < num_elem; i++) { |
- | 524 | element = _cairo_array_index (index, i); |
|
372 | element = _cairo_array_index (index, i); |
525 | if (element->length > 0) { |
373 | status = _cairo_array_append_multiple (output, |
526 | status = _cairo_array_append_multiple (output, |
374 | element->data, |
527 | element->data, |
- | 528 | element->length); |
|
375 | element->length); |
529 | } |
376 | if (unlikely (status)) |
530 | if (unlikely (status)) |
377 | return status; |
531 | return status; |
378 | } |
532 | } |
379 | return CAIRO_STATUS_SUCCESS; |
533 | return CAIRO_STATUS_SUCCESS; |
Line -... | Line 534... | ||
- | 534 | } |
|
- | 535 | ||
- | 536 | static void |
|
- | 537 | cff_index_set_object (cairo_array_t *index, int obj_index, |
|
- | 538 | unsigned char *object , int length) |
|
- | 539 | { |
|
- | 540 | cff_index_element_t *element; |
|
- | 541 | ||
- | 542 | element = _cairo_array_index (index, obj_index); |
|
- | 543 | if (element->is_copy) |
|
- | 544 | free (element->data); |
|
- | 545 | ||
- | 546 | element->data = object; |
|
- | 547 | element->length = length; |
|
- | 548 | element->is_copy = FALSE; |
|
380 | } |
549 | } |
381 | 550 | ||
382 | static cairo_status_t |
551 | static cairo_status_t |
383 | cff_index_append (cairo_array_t *index, unsigned char *object , int length) |
552 | cff_index_append (cairo_array_t *index, unsigned char *object , int length) |
Line 418... | Line 587... | ||
418 | 587 | ||
419 | static void |
588 | static void |
420 | cff_index_fini (cairo_array_t *index) |
589 | cff_index_fini (cairo_array_t *index) |
421 | { |
590 | { |
422 | cff_index_element_t *element; |
591 | cff_index_element_t *element; |
Line 423... | Line 592... | ||
423 | int i; |
592 | unsigned int i; |
424 | 593 | ||
425 | for (i = 0; i < _cairo_array_num_elements (index); i++) { |
594 | for (i = 0; i < _cairo_array_num_elements (index); i++) { |
426 | element = _cairo_array_index (index, i); |
595 | element = _cairo_array_index (index, i); |
427 | if (element->is_copy) |
596 | if (element->is_copy && element->data) |
428 | free (element->data); |
597 | free (element->data); |
429 | } |
598 | } |
Line 689... | Line 858... | ||
689 | cairo_cff_font_read_header (cairo_cff_font_t *font) |
858 | cairo_cff_font_read_header (cairo_cff_font_t *font) |
690 | { |
859 | { |
691 | if (font->data_length < sizeof (cff_header_t)) |
860 | if (font->data_length < sizeof (cff_header_t)) |
692 | return CAIRO_INT_STATUS_UNSUPPORTED; |
861 | return CAIRO_INT_STATUS_UNSUPPORTED; |
Line -... | Line 862... | ||
- | 862 | ||
693 | 863 | ||
694 | font->header = (cff_header_t *) font->data; |
864 | font->header = (cff_header_t *) font->data; |
Line 695... | Line 865... | ||
695 | font->current_ptr = font->data + font->header->header_size; |
865 | font->current_ptr = font->data + font->header->header_size; |
696 | 866 | ||
Line 700... | Line 870... | ||
700 | static cairo_int_status_t |
870 | static cairo_int_status_t |
701 | cairo_cff_font_read_name (cairo_cff_font_t *font) |
871 | cairo_cff_font_read_name (cairo_cff_font_t *font) |
702 | { |
872 | { |
703 | cairo_array_t index; |
873 | cairo_array_t index; |
704 | cairo_int_status_t status; |
874 | cairo_int_status_t status; |
- | 875 | cff_index_element_t *element; |
|
- | 876 | unsigned char *p; |
|
- | 877 | int i, len; |
|
Line 705... | Line -... | ||
705 | - | ||
706 | /* The original font name is not used in the subset. Read the name |
- | |
707 | * index to skip over it. */ |
878 | |
708 | cff_index_init (&index); |
879 | cff_index_init (&index); |
- | 880 | status = cff_index_read (&index, &font->current_ptr, font->data_end); |
|
- | 881 | if (!font->is_opentype) { |
|
- | 882 | element = _cairo_array_index (&index, 0); |
|
- | 883 | p = element->data; |
|
- | 884 | len = element->length; |
|
- | 885 | ||
- | 886 | /* If font name is prefixed with a subset tag, strip it off. */ |
|
- | 887 | if (len > 7 && p[6] == '+') { |
|
- | 888 | for (i = 0; i < 6; i++) |
|
- | 889 | if (p[i] < 'A' || p[i] > 'Z') |
|
- | 890 | break; |
|
- | 891 | if (i == 6) { |
|
- | 892 | p += 7; |
|
- | 893 | len -= 7; |
|
- | 894 | } |
|
- | 895 | } |
|
- | 896 | font->ps_name = malloc (len + 1); |
|
- | 897 | if (unlikely (font->ps_name == NULL)) |
|
- | 898 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 899 | ||
- | 900 | memcpy (font->ps_name, p, len); |
|
- | 901 | font->ps_name[len] = 0; |
|
709 | status = cff_index_read (&index, &font->current_ptr, font->data_end); |
902 | } |
Line 710... | Line 903... | ||
710 | cff_index_fini (&index); |
903 | cff_index_fini (&index); |
711 | 904 | ||
Line 712... | Line 905... | ||
712 | return status; |
905 | return status; |
713 | } |
906 | } |
714 | 907 | ||
715 | static cairo_int_status_t |
908 | static cairo_int_status_t |
- | 909 | cairo_cff_font_read_private_dict (cairo_cff_font_t *font, |
|
- | 910 | cairo_hash_table_t *private_dict, |
|
- | 911 | cairo_array_t *local_sub_index, |
|
- | 912 | int *local_sub_bias, |
|
716 | cairo_cff_font_read_private_dict (cairo_cff_font_t *font, |
913 | cairo_bool_t **local_subs_used, |
717 | cairo_hash_table_t *private_dict, |
914 | double *default_width, |
718 | cairo_array_t *local_sub_index, |
915 | double *nominal_width, |
719 | unsigned char *ptr, |
916 | unsigned char *ptr, |
720 | int size) |
917 | int size) |
721 | { |
918 | { |
722 | cairo_int_status_t status; |
919 | cairo_int_status_t status; |
723 | unsigned char buf[10]; |
920 | unsigned char buf[10]; |
724 | unsigned char *end_buf; |
921 | unsigned char *end_buf; |
725 | int offset; |
922 | int offset; |
- | 923 | int i; |
|
Line 726... | Line 924... | ||
726 | int i; |
924 | unsigned char *operand; |
727 | unsigned char *operand; |
925 | unsigned char *p; |
728 | unsigned char *p; |
926 | int num_subs; |
Line 737... | Line 935... | ||
737 | p = ptr + offset; |
935 | p = ptr + offset; |
738 | status = cff_index_read (local_sub_index, &p, font->data_end); |
936 | status = cff_index_read (local_sub_index, &p, font->data_end); |
739 | if (unlikely (status)) |
937 | if (unlikely (status)) |
740 | return status; |
938 | return status; |
Line 741... | Line 939... | ||
741 | 939 | ||
742 | /* Use maximum sized encoding to reserve space for later modification. */ |
940 | /* Use maximum sized encoding to reserve space for later modification. */ |
743 | end_buf = encode_integer_max (buf, 0); |
941 | end_buf = encode_integer_max (buf, 0); |
744 | status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf); |
942 | status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf); |
745 | if (unlikely (status)) |
943 | if (unlikely (status)) |
746 | return status; |
944 | return status; |
Line -... | Line 945... | ||
- | 945 | } |
|
- | 946 | ||
- | 947 | *default_width = 0; |
|
- | 948 | operand = cff_dict_get_operands (private_dict, DEFAULTWIDTH_OP, &i); |
|
- | 949 | if (operand) |
|
- | 950 | decode_number (operand, default_width); |
|
- | 951 | ||
- | 952 | *nominal_width = 0; |
|
- | 953 | operand = cff_dict_get_operands (private_dict, NOMINALWIDTH_OP, &i); |
|
- | 954 | if (operand) |
|
- | 955 | decode_number (operand, nominal_width); |
|
- | 956 | ||
- | 957 | num_subs = _cairo_array_num_elements (local_sub_index); |
|
- | 958 | *local_subs_used = calloc (num_subs, sizeof (cairo_bool_t)); |
|
- | 959 | if (unlikely (*local_subs_used == NULL)) |
|
- | 960 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 961 | ||
- | 962 | if (num_subs < 1240) |
|
- | 963 | *local_sub_bias = 107; |
|
- | 964 | else if (num_subs < 33900) |
|
- | 965 | *local_sub_bias = 1131; |
|
- | 966 | else |
|
747 | } |
967 | *local_sub_bias = 32768; |
748 | 968 | ||
Line 749... | Line 969... | ||
749 | return CAIRO_STATUS_SUCCESS; |
969 | return CAIRO_STATUS_SUCCESS; |
750 | } |
970 | } |
Line 818... | Line 1038... | ||
818 | if (unlikely (font->fd_local_sub_index == NULL)) { |
1038 | if (unlikely (font->fd_local_sub_index == NULL)) { |
819 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1039 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
820 | goto fail; |
1040 | goto fail; |
821 | } |
1041 | } |
Line -... | Line 1042... | ||
- | 1042 | ||
- | 1043 | font->fd_local_sub_bias = calloc (sizeof (int), font->num_fontdicts); |
|
- | 1044 | if (unlikely (font->fd_local_sub_bias == NULL)) { |
|
- | 1045 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 1046 | goto fail; |
|
- | 1047 | } |
|
- | 1048 | ||
- | 1049 | font->fd_local_subs_used = calloc (sizeof (cairo_bool_t *), font->num_fontdicts); |
|
- | 1050 | if (unlikely (font->fd_local_subs_used == NULL)) { |
|
- | 1051 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 1052 | goto fail; |
|
- | 1053 | } |
|
- | 1054 | ||
- | 1055 | font->fd_default_width = calloc (font->num_fontdicts, sizeof (double)); |
|
- | 1056 | if (unlikely (font->fd_default_width == NULL)) { |
|
- | 1057 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 1058 | goto fail; |
|
- | 1059 | } |
|
- | 1060 | ||
- | 1061 | font->fd_nominal_width = calloc (font->num_fontdicts, sizeof (double)); |
|
- | 1062 | if (unlikely (font->fd_nominal_width == NULL)) { |
|
- | 1063 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 1064 | goto fail; |
|
- | 1065 | } |
|
822 | 1066 | ||
823 | for (i = 0; i < font->num_fontdicts; i++) { |
1067 | for (i = 0; i < font->num_fontdicts; i++) { |
824 | status = cff_dict_init (&font->fd_dict[i]); |
1068 | status = cff_dict_init (&font->fd_dict[i]); |
825 | if (unlikely (status)) |
1069 | if (unlikely (status)) |
Line 843... | Line 1087... | ||
843 | 1087 | ||
844 | cff_index_init (&font->fd_local_sub_index[i]); |
1088 | cff_index_init (&font->fd_local_sub_index[i]); |
845 | status = cairo_cff_font_read_private_dict (font, |
1089 | status = cairo_cff_font_read_private_dict (font, |
846 | font->fd_private_dict[i], |
1090 | font->fd_private_dict[i], |
- | 1091 | &font->fd_local_sub_index[i], |
|
- | 1092 | &font->fd_local_sub_bias[i], |
|
- | 1093 | &font->fd_local_subs_used[i], |
|
- | 1094 | &font->fd_default_width[i], |
|
847 | &font->fd_local_sub_index[i], |
1095 | &font->fd_nominal_width[i], |
848 | font->data + offset, |
1096 | font->data + offset, |
849 | size); |
1097 | size); |
850 | if (unlikely (status)) |
1098 | if (unlikely (status)) |
Line 851... | Line 1099... | ||
851 | goto fail; |
1099 | goto fail; |
852 | 1100 | ||
853 | /* Set integer operand to max value to use max size encoding to reserve |
1101 | /* Set integer operand to max value to use max size encoding to reserve |
854 | * space for any value later */ |
1102 | * space for any value later */ |
855 | end_buf = encode_integer_max (buf, 0); |
1103 | end_buf = encode_integer_max (buf, 0); |
856 | end_buf = encode_integer_max (end_buf, 0); |
1104 | end_buf = encode_integer_max (end_buf, 0); |
Line 865... | Line 1113... | ||
865 | cff_index_fini (&index); |
1113 | cff_index_fini (&index); |
Line 866... | Line 1114... | ||
866 | 1114 | ||
867 | return status; |
1115 | return status; |
Line -... | Line 1116... | ||
- | 1116 | } |
|
- | 1117 | ||
- | 1118 | static void |
|
- | 1119 | cairo_cff_font_read_font_metrics (cairo_cff_font_t *font, cairo_hash_table_t *top_dict) |
|
- | 1120 | { |
|
- | 1121 | unsigned char *p; |
|
- | 1122 | unsigned char *end; |
|
- | 1123 | int size; |
|
- | 1124 | double x_min, y_min, x_max, y_max; |
|
- | 1125 | double xx, yx, xy, yy; |
|
- | 1126 | ||
- | 1127 | x_min = 0.0; |
|
- | 1128 | y_min = 0.0; |
|
- | 1129 | x_max = 0.0; |
|
- | 1130 | y_max = 0.0; |
|
- | 1131 | p = cff_dict_get_operands (font->top_dict, FONTBBOX_OP, &size); |
|
- | 1132 | if (p) { |
|
- | 1133 | end = p + size; |
|
- | 1134 | if (p < end) |
|
- | 1135 | p = decode_number (p, &x_min); |
|
- | 1136 | if (p < end) |
|
- | 1137 | p = decode_number (p, &y_min); |
|
- | 1138 | if (p < end) |
|
- | 1139 | p = decode_number (p, &x_max); |
|
- | 1140 | if (p < end) |
|
- | 1141 | p = decode_number (p, &y_max); |
|
- | 1142 | } |
|
- | 1143 | font->x_min = floor (x_min); |
|
- | 1144 | font->y_min = floor (y_min); |
|
- | 1145 | font->x_max = floor (x_max); |
|
- | 1146 | font->y_max = floor (y_max); |
|
- | 1147 | font->ascent = font->y_max; |
|
- | 1148 | font->descent = font->y_min; |
|
- | 1149 | ||
- | 1150 | xx = 0.001; |
|
- | 1151 | yx = 0.0; |
|
- | 1152 | xy = 0.0; |
|
- | 1153 | yy = 0.001; |
|
- | 1154 | p = cff_dict_get_operands (font->top_dict, FONTMATRIX_OP, &size); |
|
- | 1155 | if (p) { |
|
- | 1156 | end = p + size; |
|
- | 1157 | if (p < end) |
|
- | 1158 | p = decode_number (p, &xx); |
|
- | 1159 | if (p < end) |
|
- | 1160 | p = decode_number (p, &yx); |
|
- | 1161 | if (p < end) |
|
- | 1162 | p = decode_number (p, &xy); |
|
- | 1163 | if (p < end) |
|
- | 1164 | p = decode_number (p, &yy); |
|
- | 1165 | } |
|
- | 1166 | /* Freetype uses 1/yy to get units per EM */ |
|
- | 1167 | font->units_per_em = _cairo_round(1.0/yy); |
|
868 | } |
1168 | } |
869 | 1169 | ||
870 | static cairo_int_status_t |
1170 | static cairo_int_status_t |
871 | cairo_cff_font_read_top_dict (cairo_cff_font_t *font) |
1171 | cairo_cff_font_read_top_dict (cairo_cff_font_t *font) |
872 | { |
1172 | { |
Line 902... | Line 1202... | ||
902 | if (unlikely (status)) |
1202 | if (unlikely (status)) |
903 | goto fail; |
1203 | goto fail; |
904 | font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index); |
1204 | font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index); |
Line 905... | Line 1205... | ||
905 | 1205 | ||
- | 1206 | if (font->is_cid) { |
|
- | 1207 | operand = cff_dict_get_operands (font->top_dict, CHARSET_OP, &size); |
|
- | 1208 | if (!operand) |
|
- | 1209 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1210 | ||
- | 1211 | decode_integer (operand, &offset); |
|
- | 1212 | font->charset = font->data + offset; |
|
- | 1213 | if (font->charset >= font->data_end) |
|
- | 1214 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1215 | } |
|
- | 1216 | ||
- | 1217 | if (!font->is_opentype) |
|
- | 1218 | cairo_cff_font_read_font_metrics (font, font->top_dict); |
|
- | 1219 | ||
906 | if (font->is_cid) { |
1220 | if (font->is_cid) { |
907 | operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size); |
1221 | operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size); |
908 | decode_integer (operand, &offset); |
1222 | decode_integer (operand, &offset); |
909 | status = cairo_cff_font_read_fdselect (font, font->data + offset); |
1223 | status = cairo_cff_font_read_fdselect (font, font->data + offset); |
910 | if (unlikely (status)) |
1224 | if (unlikely (status)) |
Line 917... | Line 1231... | ||
917 | goto fail; |
1231 | goto fail; |
918 | } else { |
1232 | } else { |
919 | operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size); |
1233 | operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size); |
920 | operand = decode_integer (operand, &size); |
1234 | operand = decode_integer (operand, &size); |
921 | decode_integer (operand, &offset); |
1235 | decode_integer (operand, &offset); |
922 | status = cairo_cff_font_read_private_dict (font, |
1236 | status = cairo_cff_font_read_private_dict (font, |
923 | font->private_dict, |
1237 | font->private_dict, |
924 | &font->local_sub_index, |
1238 | &font->local_sub_index, |
- | 1239 | &font->local_sub_bias, |
|
- | 1240 | &font->local_subs_used, |
|
- | 1241 | &font->default_width, |
|
- | 1242 | &font->nominal_width, |
|
925 | font->data + offset, |
1243 | font->data + offset, |
926 | size); |
1244 | size); |
927 | if (unlikely (status)) |
1245 | if (unlikely (status)) |
928 | goto fail; |
1246 | goto fail; |
929 | } |
1247 | } |
Line 934... | Line 1252... | ||
934 | CHARSTRINGS_OP, buf, end_buf - buf); |
1252 | CHARSTRINGS_OP, buf, end_buf - buf); |
935 | if (unlikely (status)) |
1253 | if (unlikely (status)) |
936 | goto fail; |
1254 | goto fail; |
Line 937... | Line 1255... | ||
937 | 1255 | ||
938 | status = cff_dict_set_operands (font->top_dict, |
1256 | status = cff_dict_set_operands (font->top_dict, |
939 | FDSELECT_OP, buf, end_buf - buf); |
1257 | CHARSET_OP, buf, end_buf - buf); |
940 | if (unlikely (status)) |
1258 | if (unlikely (status)) |
Line -... | Line 1259... | ||
- | 1259 | goto fail; |
|
941 | goto fail; |
1260 | |
942 | 1261 | if (font->scaled_font_subset->is_latin) { |
|
943 | status = cff_dict_set_operands (font->top_dict, |
1262 | status = cff_dict_set_operands (font->top_dict, |
944 | FDARRAY_OP, buf, end_buf - buf); |
1263 | ENCODING_OP, buf, end_buf - buf); |
Line -... | Line 1264... | ||
- | 1264 | if (unlikely (status)) |
|
945 | if (unlikely (status)) |
1265 | goto fail; |
946 | goto fail; |
1266 | |
947 | 1267 | /* Private has two operands - size and offset */ |
|
948 | status = cff_dict_set_operands (font->top_dict, |
1268 | end_buf = encode_integer_max (end_buf, 0); |
Line -... | Line 1269... | ||
- | 1269 | cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf - buf); |
|
- | 1270 | if (unlikely (status)) |
|
- | 1271 | goto fail; |
|
- | 1272 | ||
- | 1273 | } else { |
|
- | 1274 | status = cff_dict_set_operands (font->top_dict, |
|
- | 1275 | FDSELECT_OP, buf, end_buf - buf); |
|
- | 1276 | if (unlikely (status)) |
|
- | 1277 | goto fail; |
|
- | 1278 | ||
- | 1279 | status = cff_dict_set_operands (font->top_dict, |
|
949 | CHARSET_OP, buf, end_buf - buf); |
1280 | FDARRAY_OP, buf, end_buf - buf); |
950 | if (unlikely (status)) |
1281 | if (unlikely (status)) |
- | 1282 | goto fail; |
|
Line 951... | Line 1283... | ||
951 | goto fail; |
1283 | |
952 | 1284 | cff_dict_remove (font->top_dict, ENCODING_OP); |
|
953 | cff_dict_remove (font->top_dict, ENCODING_OP); |
1285 | cff_dict_remove (font->top_dict, PRIVATE_OP); |
954 | cff_dict_remove (font->top_dict, PRIVATE_OP); |
1286 | } |
Line 971... | Line 1303... | ||
971 | } |
1303 | } |
Line 972... | Line 1304... | ||
972 | 1304 | ||
973 | static cairo_int_status_t |
1305 | static cairo_int_status_t |
974 | cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font) |
1306 | cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font) |
- | 1307 | { |
|
- | 1308 | cairo_int_status_t status; |
|
- | 1309 | int num_subs; |
|
975 | { |
1310 | |
- | 1311 | status = cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end); |
|
- | 1312 | if (unlikely (status)) |
|
- | 1313 | return status; |
|
- | 1314 | ||
- | 1315 | num_subs = _cairo_array_num_elements (&font->global_sub_index); |
|
- | 1316 | font->global_subs_used = calloc (num_subs, sizeof(cairo_bool_t)); |
|
- | 1317 | if (unlikely (font->global_subs_used == NULL)) |
|
- | 1318 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 1319 | ||
- | 1320 | if (num_subs < 1240) |
|
- | 1321 | font->global_sub_bias = 107; |
|
- | 1322 | else if (num_subs < 33900) |
|
- | 1323 | font->global_sub_bias = 1131; |
|
- | 1324 | else |
|
- | 1325 | font->global_sub_bias = 32768; |
|
- | 1326 | ||
976 | return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end); |
1327 | return CAIRO_STATUS_SUCCESS; |
Line 977... | Line 1328... | ||
977 | } |
1328 | } |
978 | 1329 | ||
Line 1101... | Line 1452... | ||
1101 | } |
1452 | } |
Line 1102... | Line 1453... | ||
1102 | 1453 | ||
1103 | return CAIRO_STATUS_SUCCESS; |
1454 | return CAIRO_STATUS_SUCCESS; |
Line -... | Line 1455... | ||
- | 1455 | } |
|
- | 1456 | ||
- | 1457 | static unsigned char * |
|
- | 1458 | type2_decode_integer (unsigned char *p, int *integer) |
|
- | 1459 | { |
|
- | 1460 | if (*p == 28) { |
|
- | 1461 | *integer = p[1] << 8 | p[2]; |
|
- | 1462 | p += 3; |
|
- | 1463 | } else if (*p <= 246) { |
|
- | 1464 | *integer = *p++ - 139; |
|
- | 1465 | } else if (*p <= 250) { |
|
- | 1466 | *integer = (p[0] - 247) * 256 + p[1] + 108; |
|
- | 1467 | p += 2; |
|
- | 1468 | } else if (*p <= 254) { |
|
- | 1469 | *integer = -(p[0] - 251) * 256 - p[1] - 108; |
|
- | 1470 | p += 2; |
|
- | 1471 | } else { /* *p == 255 */ |
|
- | 1472 | /* 16.16 fixed-point number. The fraction is ignored. */ |
|
- | 1473 | *integer = (int16_t)((p[1] << 8) | p[2]); |
|
- | 1474 | p += 5; |
|
- | 1475 | } |
|
- | 1476 | return p; |
|
- | 1477 | } |
|
- | 1478 | ||
- | 1479 | /* Type 2 charstring parser for finding calls to local or global |
|
- | 1480 | * subroutines. For non Opentype CFF fonts it also gets the glyph |
|
- | 1481 | * widths. |
|
- | 1482 | * |
|
- | 1483 | * When we find a subroutine operator, the subroutine is marked as in |
|
- | 1484 | * use and recursively followed. The subroutine number is the value on |
|
- | 1485 | * the top of the stack when the subroutine operator is executed. In |
|
- | 1486 | * most fonts the subroutine number is encoded in an integer |
|
- | 1487 | * immediately preceding the subroutine operator. However it is |
|
- | 1488 | * possible for the subroutine number on the stack to be the result of |
|
- | 1489 | * a computation (in which case there will be an operator preceding |
|
- | 1490 | * the subroutine operator). If this occurs, subroutine subsetting is |
|
- | 1491 | * disabled since we can't easily determine which subroutines are |
|
- | 1492 | * used. |
|
- | 1493 | * |
|
- | 1494 | * The width, if present, is the first integer in the charstring. The |
|
- | 1495 | * only way to confirm if the integer at the start of the charstring is |
|
- | 1496 | * the width is when the first stack clearing operator is parsed, |
|
- | 1497 | * check if there is an extra integer left over on the stack. |
|
- | 1498 | * |
|
- | 1499 | * When the first stack clearing operator is encountered |
|
- | 1500 | * type2_find_width is set to FALSE and type2_found_width is set to |
|
- | 1501 | * TRUE if an extra argument is found, otherwise FALSE. |
|
- | 1502 | */ |
|
- | 1503 | static cairo_status_t |
|
- | 1504 | cairo_cff_parse_charstring (cairo_cff_font_t *font, |
|
- | 1505 | unsigned char *charstring, int length, |
|
- | 1506 | int glyph_id, |
|
- | 1507 | cairo_bool_t need_width) |
|
- | 1508 | { |
|
- | 1509 | unsigned char *p = charstring; |
|
- | 1510 | unsigned char *end = charstring + length; |
|
- | 1511 | int integer; |
|
- | 1512 | int hint_bytes; |
|
- | 1513 | int sub_num; |
|
- | 1514 | cff_index_element_t *element; |
|
- | 1515 | int fd; |
|
- | 1516 | ||
- | 1517 | while (p < end) { |
|
- | 1518 | if (*p == 28 || *p >= 32) { |
|
- | 1519 | /* Integer value */ |
|
- | 1520 | p = type2_decode_integer (p, &integer); |
|
- | 1521 | font->type2_stack_size++; |
|
- | 1522 | font->type2_stack_top_value = integer; |
|
- | 1523 | font->type2_stack_top_is_int = TRUE; |
|
- | 1524 | if (!font->type2_seen_first_int) { |
|
- | 1525 | font->type2_width = integer; |
|
- | 1526 | font->type2_seen_first_int = TRUE; |
|
- | 1527 | } |
|
- | 1528 | } else if (*p == TYPE2_hstem || *p == TYPE2_vstem || |
|
- | 1529 | *p == TYPE2_hstemhm || *p == TYPE2_vstemhm) { |
|
- | 1530 | /* Hint operator. The number of hints declared by the |
|
- | 1531 | * operator depends on the size of the stack. */ |
|
- | 1532 | font->type2_stack_top_is_int = FALSE; |
|
- | 1533 | font->type2_num_hints += font->type2_stack_size/2; |
|
- | 1534 | if (font->type2_find_width && font->type2_stack_size % 2) |
|
- | 1535 | font->type2_found_width = TRUE; |
|
- | 1536 | ||
- | 1537 | font->type2_stack_size = 0; |
|
- | 1538 | font->type2_find_width = FALSE; |
|
- | 1539 | p++; |
|
- | 1540 | } else if (*p == TYPE2_hintmask || *p == TYPE2_cntrmask) { |
|
- | 1541 | /* Hintmask operator. These operators are followed by a |
|
- | 1542 | * variable length mask where the length depends on the |
|
- | 1543 | * number of hints declared. The first time this is called |
|
- | 1544 | * it is also an implicit vstem if there are arguments on |
|
- | 1545 | * the stack. */ |
|
- | 1546 | if (font->type2_hintmask_bytes == 0) { |
|
- | 1547 | font->type2_stack_top_is_int = FALSE; |
|
- | 1548 | font->type2_num_hints += font->type2_stack_size/2; |
|
- | 1549 | if (font->type2_find_width && font->type2_stack_size % 2) |
|
- | 1550 | font->type2_found_width = TRUE; |
|
- | 1551 | ||
- | 1552 | font->type2_stack_size = 0; |
|
- | 1553 | font->type2_find_width = FALSE; |
|
- | 1554 | font->type2_hintmask_bytes = (font->type2_num_hints+7)/8; |
|
- | 1555 | } |
|
- | 1556 | ||
- | 1557 | hint_bytes = font->type2_hintmask_bytes; |
|
- | 1558 | p++; |
|
- | 1559 | p += hint_bytes; |
|
- | 1560 | } else if (*p == TYPE2_rmoveto) { |
|
- | 1561 | if (font->type2_find_width && font->type2_stack_size > 2) |
|
- | 1562 | font->type2_found_width = TRUE; |
|
- | 1563 | ||
- | 1564 | font->type2_stack_size = 0; |
|
- | 1565 | font->type2_find_width = FALSE; |
|
- | 1566 | font->type2_has_path = TRUE; |
|
- | 1567 | p++; |
|
- | 1568 | } else if (*p == TYPE2_hmoveto || *p == TYPE2_vmoveto) { |
|
- | 1569 | if (font->type2_find_width && font->type2_stack_size > 1) |
|
- | 1570 | font->type2_found_width = TRUE; |
|
- | 1571 | ||
- | 1572 | font->type2_stack_size = 0; |
|
- | 1573 | font->type2_find_width = FALSE; |
|
- | 1574 | font->type2_has_path = TRUE; |
|
- | 1575 | p++; |
|
- | 1576 | } else if (*p == TYPE2_endchar) { |
|
- | 1577 | if (!font->type2_has_path && font->type2_stack_size > 3) |
|
- | 1578 | return CAIRO_INT_STATUS_UNSUPPORTED; /* seac (Ref Appendix C of Type 2 Charstring Format */ |
|
- | 1579 | ||
- | 1580 | if (font->type2_find_width && font->type2_stack_size > 0) |
|
- | 1581 | font->type2_found_width = TRUE; |
|
- | 1582 | ||
- | 1583 | return CAIRO_STATUS_SUCCESS; |
|
- | 1584 | } else if (*p == TYPE2_callsubr) { |
|
- | 1585 | /* call to local subroutine */ |
|
- | 1586 | if (! font->type2_stack_top_is_int) |
|
- | 1587 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1588 | ||
- | 1589 | if (++font->type2_nesting_level > MAX_SUBROUTINE_NESTING) |
|
- | 1590 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1591 | ||
- | 1592 | p++; |
|
- | 1593 | font->type2_stack_top_is_int = FALSE; |
|
- | 1594 | font->type2_stack_size--; |
|
- | 1595 | if (font->type2_find_width && font->type2_stack_size == 0) |
|
- | 1596 | font->type2_seen_first_int = FALSE; |
|
- | 1597 | ||
- | 1598 | if (font->is_cid) { |
|
- | 1599 | fd = font->fdselect[glyph_id]; |
|
- | 1600 | sub_num = font->type2_stack_top_value + font->fd_local_sub_bias[fd]; |
|
- | 1601 | element = _cairo_array_index (&font->fd_local_sub_index[fd], sub_num); |
|
- | 1602 | if (! font->fd_local_subs_used[fd][sub_num]) { |
|
- | 1603 | font->fd_local_subs_used[fd][sub_num] = TRUE; |
|
- | 1604 | cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width); |
|
- | 1605 | } |
|
- | 1606 | } else { |
|
- | 1607 | sub_num = font->type2_stack_top_value + font->local_sub_bias; |
|
- | 1608 | element = _cairo_array_index (&font->local_sub_index, sub_num); |
|
- | 1609 | if (! font->local_subs_used[sub_num] || |
|
- | 1610 | (need_width && !font->type2_found_width)) |
|
- | 1611 | { |
|
- | 1612 | font->local_subs_used[sub_num] = TRUE; |
|
- | 1613 | cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width); |
|
- | 1614 | } |
|
- | 1615 | } |
|
- | 1616 | font->type2_nesting_level--; |
|
- | 1617 | } else if (*p == TYPE2_callgsubr) { |
|
- | 1618 | /* call to global subroutine */ |
|
- | 1619 | if (! font->type2_stack_top_is_int) |
|
- | 1620 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1621 | ||
- | 1622 | if (++font->type2_nesting_level > MAX_SUBROUTINE_NESTING) |
|
- | 1623 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1624 | ||
- | 1625 | p++; |
|
- | 1626 | font->type2_stack_size--; |
|
- | 1627 | font->type2_stack_top_is_int = FALSE; |
|
- | 1628 | if (font->type2_find_width && font->type2_stack_size == 0) |
|
- | 1629 | font->type2_seen_first_int = FALSE; |
|
- | 1630 | ||
- | 1631 | sub_num = font->type2_stack_top_value + font->global_sub_bias; |
|
- | 1632 | element = _cairo_array_index (&font->global_sub_index, sub_num); |
|
- | 1633 | if (! font->global_subs_used[sub_num] || |
|
- | 1634 | (need_width && !font->type2_found_width)) |
|
- | 1635 | { |
|
- | 1636 | font->global_subs_used[sub_num] = TRUE; |
|
- | 1637 | cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width); |
|
- | 1638 | } |
|
- | 1639 | font->type2_nesting_level--; |
|
- | 1640 | } else if (*p == 12) { |
|
- | 1641 | /* 2 byte instruction */ |
|
- | 1642 | ||
- | 1643 | /* All the 2 byte operators are either not valid before a |
|
- | 1644 | * stack clearing operator or they are one of the |
|
- | 1645 | * arithmetic, storage, or conditional operators. */ |
|
- | 1646 | if (need_width && font->type2_find_width) |
|
- | 1647 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1648 | ||
- | 1649 | p += 2; |
|
- | 1650 | font->type2_stack_top_is_int = FALSE; |
|
- | 1651 | } else { |
|
- | 1652 | /* 1 byte instruction */ |
|
- | 1653 | p++; |
|
- | 1654 | font->type2_stack_top_is_int = FALSE; |
|
- | 1655 | } |
|
- | 1656 | } |
|
- | 1657 | ||
- | 1658 | return CAIRO_STATUS_SUCCESS; |
|
1104 | } |
1659 | } |
- | 1660 | ||
- | 1661 | static cairo_status_t |
|
- | 1662 | cairo_cff_find_width_and_subroutines_used (cairo_cff_font_t *font, |
|
- | 1663 | unsigned char *charstring, int length, |
|
- | 1664 | int glyph_id, int subset_id) |
|
- | 1665 | { |
|
- | 1666 | cairo_status_t status; |
|
- | 1667 | int width; |
|
- | 1668 | int fd; |
|
- | 1669 | ||
- | 1670 | font->type2_stack_size = 0; |
|
- | 1671 | font->type2_stack_top_value = 0;; |
|
- | 1672 | font->type2_stack_top_is_int = FALSE; |
|
- | 1673 | font->type2_num_hints = 0; |
|
- | 1674 | font->type2_hintmask_bytes = 0; |
|
- | 1675 | font->type2_nesting_level = 0; |
|
- | 1676 | font->type2_seen_first_int = FALSE; |
|
- | 1677 | font->type2_find_width = TRUE; |
|
- | 1678 | font->type2_found_width = FALSE; |
|
- | 1679 | font->type2_width = 0; |
|
- | 1680 | font->type2_has_path = FALSE; |
|
- | 1681 | ||
- | 1682 | status = cairo_cff_parse_charstring (font, charstring, length, glyph_id, TRUE); |
|
- | 1683 | if (status) |
|
- | 1684 | return status; |
|
- | 1685 | ||
- | 1686 | if (!font->is_opentype) { |
|
- | 1687 | if (font->is_cid) { |
|
- | 1688 | fd = font->fdselect[glyph_id]; |
|
- | 1689 | if (font->type2_found_width) |
|
- | 1690 | width = font->fd_nominal_width[fd] + font->type2_width; |
|
- | 1691 | else |
|
- | 1692 | width = font->fd_default_width[fd]; |
|
- | 1693 | } else { |
|
- | 1694 | if (font->type2_found_width) |
|
- | 1695 | width = font->nominal_width + font->type2_width; |
|
- | 1696 | else |
|
- | 1697 | width = font->default_width; |
|
- | 1698 | } |
|
- | 1699 | font->widths[subset_id] = width; |
|
- | 1700 | } |
|
- | 1701 | ||
- | 1702 | return CAIRO_STATUS_SUCCESS; |
|
- | 1703 | } |
|
- | 1704 | ||
- | 1705 | static cairo_int_status_t |
|
- | 1706 | cairo_cff_font_get_gid_for_cid (cairo_cff_font_t *font, unsigned long cid, unsigned long *gid) |
|
- | 1707 | { |
|
- | 1708 | unsigned char *p; |
|
- | 1709 | unsigned long first_gid; |
|
- | 1710 | unsigned long first_cid; |
|
- | 1711 | int num_left; |
|
- | 1712 | unsigned long c, g; |
|
- | 1713 | ||
- | 1714 | if (cid == 0) { |
|
- | 1715 | *gid = 0; |
|
- | 1716 | return CAIRO_STATUS_SUCCESS; |
|
- | 1717 | } |
|
- | 1718 | ||
- | 1719 | switch (font->charset[0]) { |
|
- | 1720 | /* Format 0 */ |
|
- | 1721 | case 0: |
|
- | 1722 | p = font->charset + 1; |
|
- | 1723 | g = 1; |
|
- | 1724 | while (g <= (unsigned)font->num_glyphs && p < font->data_end) { |
|
- | 1725 | c = be16_to_cpu( *((uint16_t *)p) ); |
|
- | 1726 | if (c == cid) { |
|
- | 1727 | *gid = g; |
|
- | 1728 | return CAIRO_STATUS_SUCCESS; |
|
- | 1729 | } |
|
- | 1730 | g++; |
|
- | 1731 | p += 2; |
|
- | 1732 | } |
|
- | 1733 | break; |
|
- | 1734 | ||
- | 1735 | /* Format 1 */ |
|
- | 1736 | case 1: |
|
- | 1737 | first_gid = 1; |
|
- | 1738 | p = font->charset + 1; |
|
- | 1739 | while (first_gid <= (unsigned)font->num_glyphs && p + 2 < font->data_end) { |
|
- | 1740 | first_cid = be16_to_cpu( *((uint16_t *)p) ); |
|
- | 1741 | num_left = p[2]; |
|
- | 1742 | if (cid >= first_cid && cid <= first_cid + num_left) { |
|
- | 1743 | *gid = first_gid + cid - first_cid; |
|
- | 1744 | return CAIRO_STATUS_SUCCESS; |
|
- | 1745 | } |
|
- | 1746 | first_gid += num_left + 1; |
|
- | 1747 | p += 3; |
|
- | 1748 | } |
|
- | 1749 | break; |
|
- | 1750 | ||
- | 1751 | /* Format 2 */ |
|
- | 1752 | case 2: |
|
- | 1753 | first_gid = 1; |
|
- | 1754 | p = font->charset + 1; |
|
- | 1755 | while (first_gid <= (unsigned)font->num_glyphs && p + 3 < font->data_end) { |
|
- | 1756 | first_cid = be16_to_cpu( *((uint16_t *)p) ); |
|
- | 1757 | num_left = be16_to_cpu( *((uint16_t *)(p+2)) ); |
|
- | 1758 | if (cid >= first_cid && cid <= first_cid + num_left) { |
|
- | 1759 | *gid = first_gid + cid - first_cid; |
|
- | 1760 | return CAIRO_STATUS_SUCCESS; |
|
- | 1761 | } |
|
- | 1762 | first_gid += num_left + 1; |
|
- | 1763 | p += 4; |
|
- | 1764 | } |
|
- | 1765 | break; |
|
- | 1766 | ||
- | 1767 | default: |
|
- | 1768 | break; |
|
- | 1769 | } |
|
- | 1770 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1771 | } |
|
1105 | 1772 | ||
1106 | static cairo_status_t |
1773 | static cairo_int_status_t |
1107 | cairo_cff_font_subset_charstrings (cairo_cff_font_t *font) |
1774 | cairo_cff_font_subset_charstrings_and_subroutines (cairo_cff_font_t *font) |
1108 | { |
1775 | { |
1109 | cff_index_element_t *element; |
1776 | cff_index_element_t *element; |
- | 1777 | unsigned int i; |
|
Line -... | Line 1778... | ||
- | 1778 | cairo_int_status_t status; |
|
1110 | unsigned int i; |
1779 | unsigned long glyph, cid; |
- | 1780 | ||
- | 1781 | font->subset_subroutines = TRUE; |
|
1111 | cairo_status_t status; |
1782 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
- | 1783 | if (font->is_cid) { |
|
- | 1784 | cid = font->scaled_font_subset->glyphs[i]; |
|
- | 1785 | status = cairo_cff_font_get_gid_for_cid (font, cid, &glyph); |
|
1112 | 1786 | if (unlikely (status)) |
|
- | 1787 | return status; |
|
- | 1788 | } else { |
|
1113 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
1789 | glyph = font->scaled_font_subset->glyphs[i]; |
1114 | element = _cairo_array_index (&font->charstrings_index, |
1790 | } |
1115 | font->scaled_font_subset->glyphs[i]); |
1791 | element = _cairo_array_index (&font->charstrings_index, glyph); |
1116 | status = cff_index_append (&font->charstrings_subset_index, |
1792 | status = cff_index_append (&font->charstrings_subset_index, |
1117 | element->data, |
1793 | element->data, |
- | 1794 | element->length); |
|
- | 1795 | if (unlikely (status)) |
|
- | 1796 | return status; |
|
- | 1797 | ||
- | 1798 | if (font->subset_subroutines) { |
|
- | 1799 | status = cairo_cff_find_width_and_subroutines_used (font, |
|
- | 1800 | element->data, element->length, |
|
- | 1801 | glyph, i); |
|
- | 1802 | if (status == CAIRO_INT_STATUS_UNSUPPORTED) { |
|
- | 1803 | /* If parsing the charstrings fails we embed all the |
|
- | 1804 | * subroutines. But if the font is not opentype we |
|
- | 1805 | * need to successfully parse all charstrings to get |
|
- | 1806 | * the widths. */ |
|
- | 1807 | font->subset_subroutines = FALSE; |
|
- | 1808 | if (!font->is_opentype) |
|
- | 1809 | return status; |
|
- | 1810 | } else if (unlikely (status)) { |
|
1118 | element->length); |
1811 | return status; |
Line 1119... | Line 1812... | ||
1119 | if (unlikely (status)) |
1812 | } |
1120 | return status; |
1813 | } |
Line 1127... | Line 1820... | ||
1127 | cairo_cff_font_subset_fontdict (cairo_cff_font_t *font) |
1820 | cairo_cff_font_subset_fontdict (cairo_cff_font_t *font) |
1128 | { |
1821 | { |
1129 | unsigned int i; |
1822 | unsigned int i; |
1130 | int fd; |
1823 | int fd; |
1131 | int *reverse_map; |
1824 | int *reverse_map; |
- | 1825 | unsigned long cid, gid; |
|
- | 1826 | cairo_int_status_t status; |
|
Line 1132... | Line 1827... | ||
1132 | 1827 | ||
1133 | font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs, |
1828 | font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs, |
1134 | sizeof (int)); |
1829 | sizeof (int)); |
1135 | if (unlikely (font->fdselect_subset == NULL)) |
1830 | if (unlikely (font->fdselect_subset == NULL)) |
Line 1150... | Line 1845... | ||
1150 | for (i = 0; i < font->num_fontdicts; i++) |
1845 | for (i = 0; i < font->num_fontdicts; i++) |
1151 | reverse_map[i] = -1; |
1846 | reverse_map[i] = -1; |
Line 1152... | Line 1847... | ||
1152 | 1847 | ||
1153 | font->num_subset_fontdicts = 0; |
1848 | font->num_subset_fontdicts = 0; |
1154 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
1849 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
- | 1850 | cid = font->scaled_font_subset->glyphs[i]; |
|
- | 1851 | status = cairo_cff_font_get_gid_for_cid (font, cid, &gid); |
|
- | 1852 | if (unlikely (status)) |
|
- | 1853 | return status; |
|
- | 1854 | ||
1155 | fd = font->fdselect[font->scaled_font_subset->glyphs[i]]; |
1855 | fd = font->fdselect[gid]; |
1156 | if (reverse_map[fd] < 0) { |
1856 | if (reverse_map[fd] < 0) { |
1157 | font->fd_subset_map[font->num_subset_fontdicts] = fd; |
1857 | font->fd_subset_map[font->num_subset_fontdicts] = fd; |
1158 | reverse_map[fd] = font->num_subset_fontdicts++; |
1858 | reverse_map[fd] = font->num_subset_fontdicts++; |
1159 | } |
1859 | } |
Line 1231... | Line 1931... | ||
1231 | } |
1931 | } |
Line 1232... | Line 1932... | ||
1232 | 1932 | ||
1233 | return status; |
1933 | return status; |
Line -... | Line 1934... | ||
- | 1934 | } |
|
- | 1935 | ||
- | 1936 | /* The Euro is the only the only character in the winansi encoding |
|
- | 1937 | * with a glyph name that is not a CFF standard string. As the strings |
|
- | 1938 | * are written before the charset, we need to check during the |
|
- | 1939 | * subsetting phase if the Euro glyph is required and add the |
|
- | 1940 | * glyphname to the list of strings to write out. |
|
- | 1941 | */ |
|
- | 1942 | static cairo_status_t |
|
- | 1943 | cairo_cff_font_add_euro_charset_string (cairo_cff_font_t *font) |
|
- | 1944 | { |
|
- | 1945 | cairo_status_t status; |
|
- | 1946 | unsigned int i; |
|
- | 1947 | int ch; |
|
- | 1948 | const char *euro = "Euro"; |
|
- | 1949 | ||
- | 1950 | for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { |
|
- | 1951 | ch = font->scaled_font_subset->to_latin_char[i]; |
|
- | 1952 | if (ch == 128) { |
|
- | 1953 | font->euro_sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); |
|
- | 1954 | status = cff_index_append_copy (&font->strings_subset_index, |
|
- | 1955 | (unsigned char *)euro, strlen(euro)); |
|
- | 1956 | return status; |
|
- | 1957 | } |
|
- | 1958 | } |
|
- | 1959 | ||
- | 1960 | return CAIRO_STATUS_SUCCESS; |
|
1234 | } |
1961 | } |
1235 | 1962 | ||
1236 | static cairo_status_t |
1963 | static cairo_status_t |
1237 | cairo_cff_font_subset_font (cairo_cff_font_t *font) |
1964 | cairo_cff_font_subset_font (cairo_cff_font_t *font) |
Line -... | Line 1965... | ||
- | 1965 | { |
|
1238 | { |
1966 | cairo_status_t status; |
1239 | cairo_status_t status; |
1967 | |
1240 | 1968 | if (!font->scaled_font_subset->is_latin) { |
|
- | 1969 | status = cairo_cff_font_set_ros_strings (font); |
|
Line 1241... | Line 1970... | ||
1241 | status = cairo_cff_font_set_ros_strings (font); |
1970 | if (unlikely (status)) |
1242 | if (unlikely (status)) |
1971 | return status; |
1243 | return status; |
1972 | } |
Line -... | Line 1973... | ||
- | 1973 | ||
1244 | 1974 | status = cairo_cff_font_subset_charstrings_and_subroutines (font); |
|
1245 | status = cairo_cff_font_subset_charstrings (font); |
1975 | if (unlikely (status)) |
1246 | if (unlikely (status)) |
1976 | return status; |
1247 | return status; |
1977 | |
1248 | 1978 | if (!font->scaled_font_subset->is_latin) { |
|
1249 | if (font->is_cid) |
1979 | if (font->is_cid) |
- | 1980 | status = cairo_cff_font_subset_fontdict (font); |
|
- | 1981 | else |
|
- | 1982 | status = cairo_cff_font_create_cid_fontdict (font); |
|
- | 1983 | if (unlikely (status)) |
|
- | 1984 | return status; |
|
Line 1250... | Line 1985... | ||
1250 | status = cairo_cff_font_subset_fontdict (font); |
1985 | } else { |
1251 | else |
1986 | font->private_dict_offset = malloc (sizeof (int)); |
1252 | status = cairo_cff_font_create_cid_fontdict (font); |
1987 | if (unlikely (font->private_dict_offset == NULL)) |
Line -... | Line 1988... | ||
- | 1988 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 1989 | } |
|
- | 1990 | ||
1253 | if (unlikely (status)) |
1991 | status = cairo_cff_font_subset_strings (font); |
1254 | return status; |
1992 | if (unlikely (status)) |
Line 1255... | Line 1993... | ||
1255 | 1993 | return status; |
|
1256 | status = cairo_cff_font_subset_strings (font); |
1994 | |
Line 1298... | Line 2036... | ||
1298 | cairo_array_t index; |
2036 | cairo_array_t index; |
Line 1299... | Line 2037... | ||
1299 | 2037 | ||
Line 1300... | Line 2038... | ||
1300 | cff_index_init (&index); |
2038 | cff_index_init (&index); |
1301 | 2039 | ||
1302 | status = cff_index_append_copy (&index, |
2040 | status = cff_index_append_copy (&index, |
1303 | (unsigned char *) font->subset_font_name, |
2041 | (unsigned char *) font->ps_name, |
1304 | strlen(font->subset_font_name)); |
2042 | strlen(font->ps_name)); |
Line 1305... | Line 2043... | ||
1305 | if (unlikely (status)) |
2043 | if (unlikely (status)) |
1306 | goto FAIL; |
2044 | goto FAIL; |
Line 1368... | Line 2106... | ||
1368 | } |
2106 | } |
Line 1369... | Line 2107... | ||
1369 | 2107 | ||
1370 | static cairo_status_t |
2108 | static cairo_status_t |
1371 | cairo_cff_font_write_global_subrs (cairo_cff_font_t *font) |
2109 | cairo_cff_font_write_global_subrs (cairo_cff_font_t *font) |
- | 2110 | { |
|
- | 2111 | unsigned int i; |
|
- | 2112 | unsigned char return_op = TYPE2_return; |
|
- | 2113 | ||
- | 2114 | /* poppler and fontforge don't like zero length subroutines so we |
|
- | 2115 | * replace unused subroutines with a 'return' instruction. */ |
|
- | 2116 | if (font->subset_subroutines) { |
|
- | 2117 | for (i = 0; i < _cairo_array_num_elements (&font->global_sub_index); i++) { |
|
- | 2118 | if (! font->global_subs_used[i]) |
|
- | 2119 | cff_index_set_object (&font->global_sub_index, i, &return_op, 1); |
|
- | 2120 | } |
|
- | 2121 | } |
|
1372 | { |
2122 | |
1373 | return cff_index_write (&font->global_sub_index, &font->output); |
2123 | return cff_index_write (&font->global_sub_index, &font->output); |
Line 1374... | Line 2124... | ||
1374 | } |
2124 | } |
- | 2125 | ||
- | 2126 | static cairo_status_t |
|
- | 2127 | cairo_cff_font_write_encoding (cairo_cff_font_t *font) |
|
- | 2128 | { |
|
- | 2129 | unsigned char buf[2]; |
|
- | 2130 | cairo_status_t status; |
|
- | 2131 | unsigned int i; |
|
- | 2132 | ||
- | 2133 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, ENCODING_OP); |
|
- | 2134 | buf[0] = 0; /* Format 0 */ |
|
- | 2135 | buf[1] = font->scaled_font_subset->num_glyphs - 1; |
|
- | 2136 | status = _cairo_array_append_multiple (&font->output, buf, 2); |
|
- | 2137 | if (unlikely (status)) |
|
- | 2138 | return status; |
|
- | 2139 | ||
- | 2140 | for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { |
|
- | 2141 | unsigned char ch = font->scaled_font_subset->to_latin_char[i]; |
|
- | 2142 | status = _cairo_array_append (&font->output, &ch); |
|
- | 2143 | if (unlikely (status)) |
|
- | 2144 | return status; |
|
- | 2145 | } |
|
- | 2146 | ||
- | 2147 | return CAIRO_STATUS_SUCCESS; |
|
- | 2148 | } |
|
1375 | 2149 | ||
1376 | static cairo_status_t |
2150 | static cairo_status_t |
1377 | cairo_cff_font_write_fdselect (cairo_cff_font_t *font) |
2151 | cairo_cff_font_write_fdselect (cairo_cff_font_t *font) |
1378 | { |
2152 | { |
1379 | unsigned char data; |
2153 | unsigned char data; |
Line 1402... | Line 2176... | ||
1402 | if (unlikely (status)) |
2176 | if (unlikely (status)) |
1403 | return status; |
2177 | return status; |
Line 1404... | Line 2178... | ||
1404 | 2178 | ||
1405 | byte = 3; |
2179 | byte = 3; |
1406 | status = _cairo_array_append (&font->output, &byte); |
2180 | status = _cairo_array_append (&font->output, &byte); |
Line 1407... | Line 2181... | ||
1407 | assert (status == CAIRO_STATUS_SUCCESS); |
2181 | assert (status == CAIRO_INT_STATUS_SUCCESS); |
1408 | 2182 | ||
1409 | word = cpu_to_be16 (1); |
2183 | word = cpu_to_be16 (1); |
Line 1410... | Line 2184... | ||
1410 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
2184 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
1411 | assert (status == CAIRO_STATUS_SUCCESS); |
2185 | assert (status == CAIRO_INT_STATUS_SUCCESS); |
1412 | 2186 | ||
Line 1413... | Line 2187... | ||
1413 | word = cpu_to_be16 (0); |
2187 | word = cpu_to_be16 (0); |
1414 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
2188 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
1415 | assert (status == CAIRO_STATUS_SUCCESS); |
2189 | assert (status == CAIRO_INT_STATUS_SUCCESS); |
Line 1416... | Line 2190... | ||
1416 | 2190 | ||
1417 | byte = 0; |
2191 | byte = 0; |
1418 | status = _cairo_array_append (&font->output, &byte); |
2192 | status = _cairo_array_append (&font->output, &byte); |
- | 2193 | assert (status == CAIRO_INT_STATUS_SUCCESS); |
|
- | 2194 | ||
- | 2195 | word = cpu_to_be16 (font->scaled_font_subset->num_glyphs); |
|
- | 2196 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
|
- | 2197 | assert (status == CAIRO_INT_STATUS_SUCCESS); |
|
- | 2198 | } |
|
- | 2199 | ||
- | 2200 | return CAIRO_STATUS_SUCCESS; |
|
- | 2201 | } |
|
- | 2202 | ||
- | 2203 | /* Winansi to CFF standard strings mapping for characters 128 to 255 */ |
|
- | 2204 | static const int winansi_to_cff_std_string[] = { |
|
- | 2205 | /* 128 */ |
|
- | 2206 | 0, 0, 117, 101, 118, 121, 112, 113, |
|
- | 2207 | 126, 122, 192, 107, 142, 0, 199, 0, |
|
- | 2208 | /* 144 */ |
|
- | 2209 | 0, 65, 8, 105, 119, 116, 111, 137, |
|
- | 2210 | 127, 153, 221, 108, 148, 0, 228, 198, |
|
- | 2211 | /* 160 */ |
|
- | 2212 | 0, 96, 97, 98, 103, 100, 160, 102, |
|
- | 2213 | 131, 170, 139, 106, 151, 0, 165, 128, |
|
- | 2214 | /* 176 */ |
|
- | 2215 | 161, 156, 164, 169, 125, 152, 115, 114, |
|
- | 2216 | 133, 150, 143, 120, 158, 155, 163, 123, |
|
- | 2217 | /* 192 */ |
|
- | 2218 | 174, 171, 172, 176, 173, 175, 138, 177, |
|
- | 2219 | 181, 178, 179, 180, 185, 182, 183, 184, |
|
- | 2220 | /* 208 */ |
|
- | 2221 | 154, 186, 190, 187, 188, 191, 189, 168, |
|
- | 2222 | 141, 196, 193, 194, 195, 197, 157, 149, |
|
- | 2223 | /* 224 */ |
|
- | 2224 | 203, 200, 201, 205, 202, 204, 144, 206, |
|
- | 2225 | 210, 207, 208, 209, 214, 211, 212, 213, |
|
- | 2226 | /* 240 */ |
|
- | 2227 | 167, 215, 219, 216, 217, 220, 218, 159, |
|
- | 2228 | 147, 225, 222, 223, 224, 226, 162, 227, |
|
- | 2229 | }; |
|
- | 2230 | ||
- | 2231 | static int |
|
- | 2232 | cairo_cff_font_get_sid_for_winansi_char (cairo_cff_font_t *font, int ch) |
|
- | 2233 | { |
|
- | 2234 | int sid; |
|
- | 2235 | ||
- | 2236 | if (ch == 39) { |
|
- | 2237 | sid = 104; |
|
- | 2238 | ||
- | 2239 | } else if (ch == 96) { |
|
- | 2240 | sid = 124; |
|
- | 2241 | ||
- | 2242 | } else if (ch >= 32 && ch <= 126) { |
|
- | 2243 | sid = ch - 31; |
|
- | 2244 | ||
- | 2245 | } else if (ch == 128) { |
|
- | 2246 | assert (font->euro_sid >= NUM_STD_STRINGS); |
|
- | 2247 | sid = font->euro_sid; |
|
- | 2248 | ||
- | 2249 | } else if (ch >= 128 && ch <= 255) { |
|
- | 2250 | sid = winansi_to_cff_std_string[ch - 128]; |
|
- | 2251 | ||
- | 2252 | } else { |
|
- | 2253 | sid = 0; |
|
- | 2254 | } |
|
- | 2255 | ||
- | 2256 | return sid; |
|
- | 2257 | } |
|
- | 2258 | ||
- | 2259 | static cairo_status_t |
|
- | 2260 | cairo_cff_font_write_type1_charset (cairo_cff_font_t *font) |
|
- | 2261 | { |
|
- | 2262 | unsigned char format = 0; |
|
- | 2263 | unsigned int i; |
|
- | 2264 | int ch, sid; |
|
- | 2265 | cairo_status_t status; |
|
- | 2266 | uint16_t sid_be16; |
|
- | 2267 | ||
- | 2268 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP); |
|
- | 2269 | status = _cairo_array_append (&font->output, &format); |
|
- | 2270 | if (unlikely (status)) |
|
- | 2271 | return status; |
|
- | 2272 | ||
- | 2273 | for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { |
|
- | 2274 | ch = font->scaled_font_subset->to_latin_char[i]; |
|
- | 2275 | sid = cairo_cff_font_get_sid_for_winansi_char (font, ch); |
|
- | 2276 | if (unlikely (status)) |
|
- | 2277 | return status; |
|
1419 | assert (status == CAIRO_STATUS_SUCCESS); |
2278 | |
Line 1420... | Line 2279... | ||
1420 | 2279 | sid_be16 = cpu_to_be16(sid); |
|
1421 | word = cpu_to_be16 (font->scaled_font_subset->num_glyphs); |
2280 | status = _cairo_array_append_multiple (&font->output, &sid_be16, sizeof(sid_be16)); |
Line 1422... | Line 2281... | ||
1422 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
2281 | if (unlikely (status)) |
1423 | assert (status == CAIRO_STATUS_SUCCESS); |
2282 | return status; |
1424 | } |
2283 | } |
1425 | 2284 | ||
1426 | return CAIRO_STATUS_SUCCESS; |
2285 | return CAIRO_STATUS_SUCCESS; |
1427 | } |
2286 | } |
Line 1464... | Line 2323... | ||
1464 | static cairo_status_t |
2323 | static cairo_status_t |
1465 | cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font) |
2324 | cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font) |
1466 | { |
2325 | { |
1467 | unsigned int i; |
2326 | unsigned int i; |
1468 | cairo_int_status_t status; |
2327 | cairo_int_status_t status; |
- | 2328 | unsigned int offset_array; |
|
1469 | uint32_t *offset_array; |
2329 | uint32_t *offset_array_ptr; |
1470 | int offset_base; |
2330 | int offset_base; |
1471 | uint16_t count; |
2331 | uint16_t count; |
1472 | uint8_t offset_size = 4; |
2332 | uint8_t offset_size = 4; |
Line 1473... | Line 2333... | ||
1473 | 2333 | ||
Line 1477... | Line 2337... | ||
1477 | if (unlikely (status)) |
2337 | if (unlikely (status)) |
1478 | return status; |
2338 | return status; |
1479 | status = _cairo_array_append (&font->output, &offset_size); |
2339 | status = _cairo_array_append (&font->output, &offset_size); |
1480 | if (unlikely (status)) |
2340 | if (unlikely (status)) |
1481 | return status; |
2341 | return status; |
- | 2342 | ||
- | 2343 | offset_array = _cairo_array_num_elements (&font->output); |
|
1482 | status = _cairo_array_allocate (&font->output, |
2344 | status = _cairo_array_allocate (&font->output, |
1483 | (font->num_subset_fontdicts + 1)*offset_size, |
2345 | (font->num_subset_fontdicts + 1)*offset_size, |
1484 | (void **) &offset_array); |
2346 | (void **) &offset_array_ptr); |
1485 | if (unlikely (status)) |
2347 | if (unlikely (status)) |
1486 | return status; |
2348 | return status; |
1487 | offset_base = _cairo_array_num_elements (&font->output) - 1; |
2349 | offset_base = _cairo_array_num_elements (&font->output) - 1; |
1488 | *offset_array++ = cpu_to_be32(1); |
2350 | *offset_array_ptr = cpu_to_be32(1); |
- | 2351 | offset_array += sizeof(uint32_t); |
|
1489 | for (i = 0; i < font->num_subset_fontdicts; i++) { |
2352 | for (i = 0; i < font->num_subset_fontdicts; i++) { |
1490 | status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]], |
2353 | status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]], |
1491 | &font->output); |
2354 | &font->output); |
1492 | if (unlikely (status)) |
2355 | if (unlikely (status)) |
1493 | return status; |
2356 | return status; |
- | 2357 | ||
- | 2358 | offset_array_ptr = (uint32_t *) _cairo_array_index (&font->output, offset_array); |
|
1494 | *offset_array++ = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base); |
2359 | *offset_array_ptr = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base); |
- | 2360 | offset_array += sizeof(uint32_t); |
|
1495 | } |
2361 | } |
Line 1496... | Line 2362... | ||
1496 | 2362 | ||
1497 | return CAIRO_STATUS_SUCCESS; |
2363 | return CAIRO_STATUS_SUCCESS; |
Line 1498... | Line 2364... | ||
1498 | } |
2364 | } |
1499 | 2365 | ||
1500 | static cairo_status_t |
2366 | static cairo_status_t |
1501 | cairo_cff_font_write_private_dict (cairo_cff_font_t *font, |
2367 | cairo_cff_font_write_private_dict (cairo_cff_font_t *font, |
1502 | int dict_num, |
2368 | int dict_num, |
1503 | cairo_hash_table_t *parent_dict, |
2369 | cairo_hash_table_t *parent_dict, |
1504 | cairo_hash_table_t *private_dict) |
2370 | cairo_hash_table_t *private_dict) |
1505 | { |
2371 | { |
1506 | int offset; |
2372 | int offset; |
1507 | int size; |
2373 | int size; |
Line 1530... | Line 2396... | ||
1530 | 2396 | ||
1531 | static cairo_status_t |
2397 | static cairo_status_t |
1532 | cairo_cff_font_write_local_sub (cairo_cff_font_t *font, |
2398 | cairo_cff_font_write_local_sub (cairo_cff_font_t *font, |
1533 | int dict_num, |
2399 | int dict_num, |
1534 | cairo_hash_table_t *private_dict, |
2400 | cairo_hash_table_t *private_dict, |
- | 2401 | cairo_array_t *local_sub_index, |
|
1535 | cairo_array_t *local_sub_index) |
2402 | cairo_bool_t *local_subs_used) |
1536 | { |
2403 | { |
1537 | int offset; |
2404 | int offset; |
1538 | int size; |
2405 | int size; |
1539 | unsigned char buf[10]; |
2406 | unsigned char buf[10]; |
1540 | unsigned char *buf_end; |
2407 | unsigned char *buf_end; |
1541 | unsigned char *p; |
2408 | unsigned char *p; |
- | 2409 | cairo_status_t status; |
|
- | 2410 | unsigned int i; |
|
Line 1542... | Line 2411... | ||
1542 | cairo_status_t status; |
2411 | unsigned char return_op = TYPE2_return; |
1543 | 2412 | ||
1544 | if (_cairo_array_num_elements (local_sub_index) > 0) { |
2413 | if (_cairo_array_num_elements (local_sub_index) > 0) { |
1545 | /* Write local subroutines and update offset in private |
2414 | /* Write local subroutines and update offset in private |
Line 1549... | Line 2418... | ||
1549 | buf_end = encode_integer_max (buf, offset); |
2418 | buf_end = encode_integer_max (buf, offset); |
1550 | offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size); |
2419 | offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size); |
1551 | assert (offset > 0); |
2420 | assert (offset > 0); |
1552 | p = _cairo_array_index (&font->output, offset); |
2421 | p = _cairo_array_index (&font->output, offset); |
1553 | memcpy (p, buf, buf_end - buf); |
2422 | memcpy (p, buf, buf_end - buf); |
- | 2423 | ||
- | 2424 | /* poppler and fontforge don't like zero length subroutines so |
|
- | 2425 | * we replace unused subroutines with a 'return' instruction. |
|
- | 2426 | */ |
|
- | 2427 | if (font->subset_subroutines) { |
|
- | 2428 | for (i = 0; i < _cairo_array_num_elements (local_sub_index); i++) { |
|
- | 2429 | if (! local_subs_used[i]) |
|
- | 2430 | cff_index_set_object (local_sub_index, i, &return_op, 1); |
|
- | 2431 | } |
|
- | 2432 | } |
|
1554 | status = cff_index_write (local_sub_index, &font->output); |
2433 | status = cff_index_write (local_sub_index, &font->output); |
1555 | if (unlikely (status)) |
2434 | if (unlikely (status)) |
1556 | return status; |
2435 | return status; |
1557 | } |
2436 | } |
Line 1580... | Line 2459... | ||
1580 | for (i = 0; i < font->num_subset_fontdicts; i++) { |
2459 | for (i = 0; i < font->num_subset_fontdicts; i++) { |
1581 | status = cairo_cff_font_write_local_sub ( |
2460 | status = cairo_cff_font_write_local_sub ( |
1582 | font, |
2461 | font, |
1583 | i, |
2462 | i, |
1584 | font->fd_private_dict[font->fd_subset_map[i]], |
2463 | font->fd_private_dict[font->fd_subset_map[i]], |
1585 | &font->fd_local_sub_index[font->fd_subset_map[i]]); |
2464 | &font->fd_local_sub_index[font->fd_subset_map[i]], |
- | 2465 | font->fd_local_subs_used[font->fd_subset_map[i]]); |
|
1586 | if (unlikely (status)) |
2466 | if (unlikely (status)) |
1587 | return status; |
2467 | return status; |
1588 | } |
2468 | } |
1589 | } else { |
2469 | } else { |
1590 | status = cairo_cff_font_write_private_dict (font, |
2470 | status = cairo_cff_font_write_private_dict (font, |
Line 1595... | Line 2475... | ||
1595 | return status; |
2475 | return status; |
Line 1596... | Line 2476... | ||
1596 | 2476 | ||
1597 | status = cairo_cff_font_write_local_sub (font, |
2477 | status = cairo_cff_font_write_local_sub (font, |
1598 | 0, |
2478 | 0, |
1599 | font->private_dict, |
2479 | font->private_dict, |
- | 2480 | &font->local_sub_index, |
|
1600 | &font->local_sub_index); |
2481 | font->local_subs_used); |
1601 | if (unlikely (status)) |
2482 | if (unlikely (status)) |
1602 | return status; |
2483 | return status; |
Line 1603... | Line 2484... | ||
1603 | } |
2484 | } |
1604 | 2485 | ||
Line -... | Line 2486... | ||
- | 2486 | return CAIRO_STATUS_SUCCESS; |
|
- | 2487 | } |
|
- | 2488 | ||
- | 2489 | static cairo_status_t |
|
- | 2490 | cairo_cff_font_write_type1_private_dict_and_local_sub (cairo_cff_font_t *font) |
|
- | 2491 | { |
|
- | 2492 | cairo_int_status_t status; |
|
- | 2493 | ||
- | 2494 | status = cairo_cff_font_write_private_dict (font, |
|
- | 2495 | 0, |
|
- | 2496 | font->top_dict, |
|
- | 2497 | font->private_dict); |
|
- | 2498 | if (unlikely (status)) |
|
- | 2499 | return status; |
|
- | 2500 | ||
- | 2501 | status = cairo_cff_font_write_local_sub (font, |
|
- | 2502 | 0, |
|
- | 2503 | font->private_dict, |
|
- | 2504 | &font->local_sub_index, |
|
- | 2505 | font->local_subs_used); |
|
- | 2506 | if (unlikely (status)) |
|
- | 2507 | return status; |
|
- | 2508 | ||
- | 2509 | return CAIRO_STATUS_SUCCESS; |
|
1605 | return CAIRO_STATUS_SUCCESS; |
2510 | } |
1606 | } |
2511 | |
Line 1607... | Line 2512... | ||
1607 | 2512 | ||
1608 | typedef cairo_status_t |
2513 | typedef cairo_status_t |
1609 | (*font_write_t) (cairo_cff_font_t *font); |
2514 | (*font_write_t) (cairo_cff_font_t *font); |
1610 | 2515 | ||
1611 | static const font_write_t font_write_funcs[] = { |
2516 | static const font_write_t font_write_cid_funcs[] = { |
1612 | cairo_cff_font_write_header, |
2517 | cairo_cff_font_write_header, |
1613 | cairo_cff_font_write_name, |
2518 | cairo_cff_font_write_name, |
1614 | cairo_cff_font_write_top_dict, |
2519 | cairo_cff_font_write_top_dict, |
1615 | cairo_cff_font_write_strings, |
2520 | cairo_cff_font_write_strings, |
1616 | cairo_cff_font_write_global_subrs, |
2521 | cairo_cff_font_write_global_subrs, |
1617 | cairo_cff_font_write_charset, |
2522 | cairo_cff_font_write_cid_charset, |
1618 | cairo_cff_font_write_fdselect, |
2523 | cairo_cff_font_write_fdselect, |
Line -... | Line 2524... | ||
- | 2524 | cairo_cff_font_write_charstrings, |
|
- | 2525 | cairo_cff_font_write_cid_fontdict, |
|
- | 2526 | cairo_cff_font_write_cid_private_dict_and_local_sub, |
|
- | 2527 | }; |
|
- | 2528 | ||
- | 2529 | static const font_write_t font_write_type1_funcs[] = { |
|
- | 2530 | cairo_cff_font_write_header, |
|
- | 2531 | cairo_cff_font_write_name, |
|
- | 2532 | cairo_cff_font_write_top_dict, |
|
- | 2533 | cairo_cff_font_write_strings, |
|
- | 2534 | cairo_cff_font_write_global_subrs, |
|
- | 2535 | cairo_cff_font_write_encoding, |
|
1619 | cairo_cff_font_write_charstrings, |
2536 | cairo_cff_font_write_type1_charset, |
1620 | cairo_cff_font_write_cid_fontdict, |
2537 | cairo_cff_font_write_charstrings, |
1621 | cairo_cff_font_write_cid_private_dict_and_local_sub, |
2538 | cairo_cff_font_write_type1_private_dict_and_local_sub, |
1622 | }; |
2539 | }; |
1623 | 2540 | ||
Line -... | Line 2541... | ||
- | 2541 | static cairo_status_t |
|
- | 2542 | cairo_cff_font_write_subset (cairo_cff_font_t *font) |
|
- | 2543 | { |
|
- | 2544 | cairo_int_status_t status; |
|
- | 2545 | unsigned int i; |
|
- | 2546 | ||
- | 2547 | if (font->scaled_font_subset->is_latin) { |
|
1624 | static cairo_status_t |
2548 | for (i = 0; i < ARRAY_LENGTH (font_write_type1_funcs); i++) { |
1625 | cairo_cff_font_write_subset (cairo_cff_font_t *font) |
2549 | status = font_write_type1_funcs[i] (font); |
1626 | { |
2550 | if (unlikely (status)) |
1627 | cairo_int_status_t status; |
2551 | return status; |
- | 2552 | } |
|
1628 | unsigned int i; |
2553 | } else { |
Line 1629... | Line 2554... | ||
1629 | 2554 | for (i = 0; i < ARRAY_LENGTH (font_write_cid_funcs); i++) { |
|
1630 | for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) { |
2555 | status = font_write_cid_funcs[i] (font); |
Line 1645... | Line 2570... | ||
1645 | 2570 | ||
1646 | status = cairo_cff_font_read_font (font); |
2571 | status = cairo_cff_font_read_font (font); |
1647 | if (unlikely (status)) |
2572 | if (unlikely (status)) |
Line -... | Line 2573... | ||
- | 2573 | return status; |
|
- | 2574 | ||
- | 2575 | /* If the PS name is not found, create a CairoFont-x-y name. */ |
|
- | 2576 | if (font->ps_name == NULL) { |
|
- | 2577 | font->ps_name = malloc (30); |
|
- | 2578 | if (unlikely (font->ps_name == NULL)) |
|
- | 2579 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 2580 | ||
- | 2581 | snprintf(font->ps_name, 30, "CairoFont-%u-%u", |
|
- | 2582 | font->scaled_font_subset->font_id, |
|
- | 2583 | font->scaled_font_subset->subset_id); |
|
1648 | return status; |
2584 | } |
1649 | 2585 | ||
1650 | status = cairo_cff_font_subset_font (font); |
2586 | status = cairo_cff_font_subset_font (font); |
Line 1651... | Line 2587... | ||
1651 | if (unlikely (status)) |
2587 | if (unlikely (status)) |
1652 | return status; |
2588 | return status; |
1653 | 2589 | ||
Line -... | Line 2590... | ||
- | 2590 | status = cairo_cff_font_write_subset (font); |
|
1654 | status = cairo_cff_font_write_subset (font); |
2591 | if (unlikely (status)) |
1655 | if (unlikely (status)) |
2592 | return status; |
Line 1656... | Line 2593... | ||
1656 | return status; |
2593 | |
1657 | 2594 | ||
Line 1680... | Line 2617... | ||
1680 | (unsigned char*) &hhea, &size); |
2617 | (unsigned char*) &hhea, &size); |
1681 | if (unlikely (status)) |
2618 | if (unlikely (status)) |
1682 | return status; |
2619 | return status; |
1683 | num_hmetrics = be16_to_cpu (hhea.num_hmetrics); |
2620 | num_hmetrics = be16_to_cpu (hhea.num_hmetrics); |
Line 1684... | Line 2621... | ||
1684 | 2621 | ||
1685 | for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { |
2622 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
1686 | glyph_index = font->scaled_font_subset->glyphs[i]; |
2623 | glyph_index = font->scaled_font_subset->glyphs[i]; |
1687 | long_entry_size = 2 * sizeof (int16_t); |
2624 | long_entry_size = 2 * sizeof (int16_t); |
1688 | short_entry_size = sizeof (int16_t); |
2625 | short_entry_size = sizeof (int16_t); |
1689 | if (glyph_index < num_hmetrics) { |
2626 | if (glyph_index < num_hmetrics) { |
Line 1707... | Line 2644... | ||
1707 | } |
2644 | } |
Line 1708... | Line 2645... | ||
1708 | 2645 | ||
1709 | return CAIRO_STATUS_SUCCESS; |
2646 | return CAIRO_STATUS_SUCCESS; |
Line -... | Line 2647... | ||
- | 2647 | } |
|
- | 2648 | ||
- | 2649 | static cairo_bool_t |
|
- | 2650 | check_fontdata_is_cff (const unsigned char *data, long length) |
|
- | 2651 | { |
|
- | 2652 | cff_header_t *header; |
|
- | 2653 | ||
- | 2654 | if (length < (long)sizeof (cff_header_t)) |
|
- | 2655 | return FALSE; |
|
- | 2656 | ||
- | 2657 | header = (cff_header_t *) data; |
|
- | 2658 | if (header->major == 1 && |
|
- | 2659 | header->minor == 0 && |
|
- | 2660 | header->header_size == 4) |
|
- | 2661 | { |
|
- | 2662 | return TRUE; |
|
- | 2663 | } |
|
- | 2664 | ||
- | 2665 | return FALSE; |
|
1710 | } |
2666 | } |
1711 | 2667 | ||
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, |
2668 | static cairo_int_status_t |
1715 | const char *subset_name) |
2669 | _cairo_cff_font_load_opentype_cff (cairo_cff_font_t *font) |
1716 | { |
2670 | { |
1717 | const cairo_scaled_font_backend_t *backend; |
- | |
1718 | cairo_status_t status; |
2671 | const cairo_scaled_font_backend_t *backend = font->backend; |
1719 | cairo_cff_font_t *font; |
2672 | cairo_status_t status; |
1720 | tt_head_t head; |
2673 | tt_head_t head; |
Line 1721... | Line -... | ||
1721 | tt_hhea_t hhea; |
- | |
1722 | unsigned long size, data_length; |
2674 | tt_hhea_t hhea; |
1723 | 2675 | unsigned long size, data_length; |
|
Line 1724... | Line 2676... | ||
1724 | backend = scaled_font_subset->scaled_font->backend; |
2676 | |
1725 | if (!backend->load_truetype_table) |
2677 | if (!backend->load_truetype_table) |
1726 | return CAIRO_INT_STATUS_UNSUPPORTED; |
2678 | return CAIRO_INT_STATUS_UNSUPPORTED; |
1727 | 2679 | ||
1728 | data_length = 0; |
2680 | data_length = 0; |
Line 1729... | Line 2681... | ||
1729 | status = backend->load_truetype_table( scaled_font_subset->scaled_font, |
2681 | status = backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1730 | TT_TAG_CFF, 0, NULL, &data_length); |
2682 | TT_TAG_CFF, 0, NULL, &data_length); |
1731 | if (unlikely (status)) |
2683 | if (status) |
1732 | return status; |
2684 | return status; |
1733 | 2685 | ||
1734 | size = sizeof (tt_head_t); |
2686 | size = sizeof (tt_head_t); |
Line 1735... | Line 2687... | ||
1735 | status = backend->load_truetype_table (scaled_font_subset->scaled_font, |
2687 | status = backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1736 | TT_TAG_head, 0, |
2688 | TT_TAG_head, 0, |
1737 | (unsigned char *) &head, &size); |
2689 | (unsigned char *) &head, &size); |
1738 | if (unlikely (status)) |
2690 | if (unlikely (status)) |
1739 | return status; |
2691 | return status; |
1740 | 2692 | ||
Line 1741... | Line 2693... | ||
1741 | size = sizeof (tt_hhea_t); |
2693 | size = sizeof (tt_hhea_t); |
1742 | status = backend->load_truetype_table (scaled_font_subset->scaled_font, |
2694 | status = backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1743 | TT_TAG_hhea, 0, |
2695 | TT_TAG_hhea, 0, |
1744 | (unsigned char *) &hhea, &size); |
2696 | (unsigned char *) &hhea, &size); |
1745 | if (unlikely (status)) |
2697 | if (unlikely (status)) |
Line 1746... | Line -... | ||
1746 | return status; |
- | |
1747 | - | ||
1748 | size = 0; |
- | |
1749 | status = backend->load_truetype_table (scaled_font_subset->scaled_font, |
- | |
1750 | TT_TAG_hmtx, 0, NULL, &size); |
- | |
1751 | if (unlikely (status)) |
- | |
1752 | return status; |
- | |
1753 | - | ||
1754 | font = malloc (sizeof (cairo_cff_font_t)); |
- | |
1755 | if (unlikely (font == NULL)) |
- | |
1756 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
1757 | - | ||
1758 | font->backend = backend; |
- | |
1759 | font->scaled_font_subset = scaled_font_subset; |
- | |
1760 | - | ||
1761 | _cairo_array_init (&font->output, sizeof (char)); |
- | |
1762 | status = _cairo_array_grow_by (&font->output, 4096); |
- | |
1763 | if (unlikely (status)) |
2698 | return status; |
1764 | goto fail2; |
2699 | |
1765 | 2700 | size = 0; |
|
1766 | font->subset_font_name = strdup (subset_name); |
2701 | status = backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1767 | if (unlikely (font->subset_font_name == NULL)) { |
2702 | TT_TAG_hmtx, 0, NULL, &size); |
Line 1777... | Line 2712... | ||
1777 | font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em); |
2712 | font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em); |
1778 | if (font->units_per_em == 0) |
2713 | if (font->units_per_em == 0) |
1779 | font->units_per_em = 1000; |
2714 | font->units_per_em = 1000; |
Line 1780... | Line 2715... | ||
1780 | 2715 | ||
1781 | font->font_name = NULL; |
2716 | font->font_name = NULL; |
1782 | status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font, |
2717 | status = _cairo_truetype_read_font_name (font->scaled_font_subset->scaled_font, |
1783 | &font->ps_name, |
2718 | &font->ps_name, |
1784 | &font->font_name); |
2719 | &font->font_name); |
1785 | if (_cairo_status_is_error (status)) |
2720 | if (_cairo_status_is_error (status)) |
Line 1786... | Line 2721... | ||
1786 | goto fail3; |
2721 | return status; |
1787 | 2722 | ||
1788 | /* If the PS name is not found, create a CairoFont-x-y name. */ |
2723 | font->is_opentype = TRUE; |
1789 | if (font->ps_name == NULL) { |
2724 | font->data_length = data_length; |
1790 | font->ps_name = malloc (30); |
2725 | font->data = malloc (data_length); |
1791 | if (unlikely (font->ps_name == NULL)) { |
- | |
1792 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
Line 1793... | Line 2726... | ||
1793 | goto fail3; |
2726 | if (unlikely (font->data == NULL)) |
1794 | } |
2727 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | 2728 | ||
1795 | 2729 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
|
1796 | snprintf(font->ps_name, 30, "CairoFont-%u-%u", |
2730 | TT_TAG_CFF, 0, font->data, |
Line 1797... | Line 2731... | ||
1797 | scaled_font_subset->font_id, |
2731 | &font->data_length); |
1798 | scaled_font_subset->subset_id); |
2732 | if (unlikely (status)) |
- | 2733 | return status; |
|
1799 | } |
2734 | |
- | 2735 | if (!check_fontdata_is_cff (font->data, data_length)) |
|
- | 2736 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
1800 | 2737 | ||
- | 2738 | return CAIRO_STATUS_SUCCESS; |
|
1801 | font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int)); |
2739 | } |
- | 2740 | ||
- | 2741 | static cairo_int_status_t |
|
- | 2742 | _cairo_cff_font_load_cff (cairo_cff_font_t *font) |
|
Line -... | Line 2743... | ||
- | 2743 | { |
|
- | 2744 | const cairo_scaled_font_backend_t *backend = font->backend; |
|
- | 2745 | cairo_status_t status; |
|
- | 2746 | unsigned long data_length; |
|
1802 | if (unlikely (font->widths == NULL)) { |
2747 | |
- | 2748 | if (!backend->load_type1_data) |
|
1803 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2749 | return CAIRO_INT_STATUS_UNSUPPORTED; |
1804 | goto fail4; |
2750 | |
Line -... | Line 2751... | ||
- | 2751 | data_length = 0; |
|
- | 2752 | status = backend->load_type1_data (font->scaled_font_subset->scaled_font, |
|
1805 | } |
2753 | 0, NULL, &data_length); |
1806 | 2754 | if (unlikely (status)) |
|
1807 | status = cairo_cff_font_create_set_widths (font); |
2755 | return status; |
1808 | if (unlikely (status)) |
2756 | |
1809 | goto fail5; |
- | |
1810 | 2757 | font->font_name = NULL; |
|
1811 | font->data_length = data_length; |
2758 | font->is_opentype = FALSE; |
1812 | font->data = malloc (data_length); |
- | |
1813 | if (unlikely (font->data == NULL)) { |
2759 | font->data_length = data_length; |
1814 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2760 | font->data = malloc (data_length); |
1815 | goto fail5; |
2761 | if (unlikely (font->data == NULL)) |
- | 2762 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 2763 | ||
- | 2764 | status = font->backend->load_type1_data (font->scaled_font_subset->scaled_font, |
|
- | 2765 | 0, font->data, &font->data_length); |
|
- | 2766 | if (unlikely (status)) |
|
- | 2767 | return status; |
|
- | 2768 | ||
- | 2769 | if (!check_fontdata_is_cff (font->data, data_length)) |
|
- | 2770 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 2771 | ||
- | 2772 | return CAIRO_STATUS_SUCCESS; |
|
- | 2773 | } |
|
- | 2774 | ||
- | 2775 | static cairo_int_status_t |
|
- | 2776 | _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset, |
|
- | 2777 | cairo_cff_font_t **font_return, |
|
- | 2778 | const char *subset_name) |
|
- | 2779 | { |
|
- | 2780 | const cairo_scaled_font_backend_t *backend; |
|
- | 2781 | cairo_int_status_t status; |
|
- | 2782 | cairo_cff_font_t *font; |
|
- | 2783 | ||
- | 2784 | backend = scaled_font_subset->scaled_font->backend; |
|
- | 2785 | ||
- | 2786 | /* We need to use a fallback font generated from the synthesized outlines. */ |
|
- | 2787 | if (backend->is_synthetic && backend->is_synthetic (scaled_font_subset->scaled_font)) |
|
- | 2788 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 2789 | ||
- | 2790 | font = calloc (1, sizeof (cairo_cff_font_t)); |
|
- | 2791 | if (unlikely (font == NULL)) |
|
- | 2792 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 2793 | ||
- | 2794 | font->backend = backend; |
|
- | 2795 | font->scaled_font_subset = scaled_font_subset; |
|
Line 1816... | Line 2796... | ||
1816 | } |
2796 | |
- | 2797 | status = _cairo_cff_font_load_opentype_cff (font); |
|
- | 2798 | if (status == CAIRO_INT_STATUS_UNSUPPORTED) |
|
- | 2799 | status = _cairo_cff_font_load_cff (font); |
|
- | 2800 | if (status) |
|
- | 2801 | goto fail1; |
|
- | 2802 | ||
- | 2803 | font->data_end = font->data + font->data_length; |
|
- | 2804 | _cairo_array_init (&font->output, sizeof (char)); |
|
- | 2805 | status = _cairo_array_grow_by (&font->output, 4096); |
|
- | 2806 | if (unlikely (status)) |
|
- | 2807 | goto fail2; |
|
- | 2808 | ||
- | 2809 | font->subset_font_name = strdup (subset_name); |
|
- | 2810 | if (unlikely (font->subset_font_name == NULL)) { |
|
- | 2811 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 2812 | goto fail2; |
|
- | 2813 | } |
|
- | 2814 | ||
- | 2815 | font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int)); |
|
- | 2816 | if (unlikely (font->widths == NULL)) { |
|
- | 2817 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 2818 | goto fail3; |
|
Line 1817... | Line 2819... | ||
1817 | status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font, |
2819 | } |
1818 | TT_TAG_CFF, 0, font->data, |
2820 | |
1819 | &font->data_length); |
2821 | if (font->is_opentype) { |
Line 1820... | Line 2822... | ||
1820 | if (unlikely (status)) |
2822 | status = cairo_cff_font_create_set_widths (font); |
1821 | goto fail6; |
2823 | if (unlikely (status)) |
1822 | 2824 | goto fail4; |
|
Line 1823... | Line 2825... | ||
1823 | font->data_end = font->data + font->data_length; |
2825 | } |
1824 | 2826 | ||
1825 | status = cff_dict_init (&font->top_dict); |
2827 | status = cff_dict_init (&font->top_dict); |
1826 | if (unlikely (status)) |
2828 | if (unlikely (status)) |
1827 | goto fail6; |
2829 | goto fail4; |
1828 | 2830 | ||
- | 2831 | status = cff_dict_init (&font->private_dict); |
|
1829 | status = cff_dict_init (&font->private_dict); |
2832 | if (unlikely (status)) |
1830 | if (unlikely (status)) |
2833 | goto fail5; |
1831 | goto fail7; |
2834 | |
1832 | 2835 | cff_index_init (&font->strings_index); |
|
- | 2836 | cff_index_init (&font->charstrings_index); |
|
1833 | cff_index_init (&font->strings_index); |
2837 | cff_index_init (&font->global_sub_index); |
1834 | cff_index_init (&font->charstrings_index); |
2838 | cff_index_init (&font->local_sub_index); |
1835 | cff_index_init (&font->global_sub_index); |
2839 | cff_index_init (&font->charstrings_subset_index); |
- | 2840 | cff_index_init (&font->strings_subset_index); |
|
- | 2841 | font->euro_sid = 0; |
|
- | 2842 | font->fdselect = NULL; |
|
Line 1836... | Line 2843... | ||
1836 | cff_index_init (&font->local_sub_index); |
2843 | font->fd_dict = NULL; |
Line 1837... | Line 2844... | ||
1837 | cff_index_init (&font->charstrings_subset_index); |
2844 | font->fd_private_dict = NULL; |
Line 1838... | Line -... | ||
1838 | cff_index_init (&font->strings_subset_index); |
- | |
1839 | font->fdselect = NULL; |
- | |
1840 | font->fd_dict = NULL; |
- | |
1841 | font->fd_private_dict = NULL; |
- | |
1842 | font->fd_local_sub_index = NULL; |
2845 | font->fd_local_sub_index = NULL; |
1843 | font->fdselect_subset = NULL; |
2846 | font->fd_local_sub_bias = NULL; |
1844 | font->fd_subset_map = NULL; |
2847 | font->fdselect_subset = NULL; |
1845 | font->private_dict_offset = NULL; |
- | |
1846 | 2848 | font->fd_subset_map = NULL; |
|
1847 | *font_return = font; |
2849 | font->private_dict_offset = NULL; |
1848 | 2850 | font->global_subs_used = NULL; |
|
1849 | return CAIRO_STATUS_SUCCESS; |
2851 | font->local_subs_used = NULL; |
- | 2852 | font->fd_local_subs_used = NULL; |
|
1850 | 2853 | ||
- | 2854 | *font_return = font; |
|
- | 2855 | ||
- | 2856 | return CAIRO_STATUS_SUCCESS; |
|
1851 | fail7: |
2857 | |
Line 1852... | Line 2858... | ||
1852 | _cairo_hash_table_destroy (font->top_dict); |
2858 | fail5: |
1853 | fail6: |
2859 | _cairo_hash_table_destroy (font->top_dict); |
Line 1870... | Line 2876... | ||
1870 | cairo_cff_font_destroy (cairo_cff_font_t *font) |
2876 | cairo_cff_font_destroy (cairo_cff_font_t *font) |
1871 | { |
2877 | { |
1872 | unsigned int i; |
2878 | unsigned int i; |
Line 1873... | Line 2879... | ||
1873 | 2879 | ||
1874 | free (font->widths); |
- | |
1875 | if (font->font_name) |
2880 | free (font->widths); |
1876 | free (font->font_name); |
2881 | free (font->font_name); |
1877 | free (font->ps_name); |
2882 | free (font->ps_name); |
1878 | free (font->subset_font_name); |
2883 | free (font->subset_font_name); |
1879 | _cairo_array_fini (&font->output); |
2884 | _cairo_array_fini (&font->output); |
1880 | cff_dict_fini (font->top_dict); |
2885 | cff_dict_fini (font->top_dict); |
Line 1893... | Line 2898... | ||
1893 | if (font->fd_dict[i]) |
2898 | if (font->fd_dict[i]) |
1894 | cff_dict_fini (font->fd_dict[i]); |
2899 | cff_dict_fini (font->fd_dict[i]); |
1895 | } |
2900 | } |
1896 | free (font->fd_dict); |
2901 | free (font->fd_dict); |
1897 | } |
2902 | } |
1898 | if (font->fd_subset_map) |
2903 | free (font->global_subs_used); |
1899 | free (font->fd_subset_map); |
2904 | free (font->local_subs_used); |
1900 | if (font->private_dict_offset) |
2905 | free (font->fd_subset_map); |
1901 | free (font->private_dict_offset); |
2906 | free (font->private_dict_offset); |
Line 1902... | Line 2907... | ||
1902 | 2907 | ||
1903 | if (font->is_cid) { |
- | |
1904 | if (font->fdselect) |
2908 | if (font->is_cid) { |
1905 | free (font->fdselect); |
- | |
1906 | if (font->fdselect_subset) |
2909 | free (font->fdselect); |
1907 | free (font->fdselect_subset); |
2910 | free (font->fdselect_subset); |
1908 | if (font->fd_private_dict) { |
2911 | if (font->fd_private_dict) { |
1909 | for (i = 0; i < font->num_fontdicts; i++) { |
2912 | for (i = 0; i < font->num_fontdicts; i++) { |
1910 | if (font->fd_private_dict[i]) |
2913 | if (font->fd_private_dict[i]) |
1911 | cff_dict_fini (font->fd_private_dict[i]); |
2914 | cff_dict_fini (font->fd_private_dict[i]); |
Line 1915... | Line 2918... | ||
1915 | if (font->fd_local_sub_index) { |
2918 | if (font->fd_local_sub_index) { |
1916 | for (i = 0; i < font->num_fontdicts; i++) |
2919 | for (i = 0; i < font->num_fontdicts; i++) |
1917 | cff_index_fini (&font->fd_local_sub_index[i]); |
2920 | cff_index_fini (&font->fd_local_sub_index[i]); |
1918 | free (font->fd_local_sub_index); |
2921 | free (font->fd_local_sub_index); |
1919 | } |
2922 | } |
- | 2923 | free (font->fd_local_sub_bias); |
|
- | 2924 | if (font->fd_local_subs_used) { |
|
- | 2925 | for (i = 0; i < font->num_fontdicts; i++) { |
|
- | 2926 | free (font->fd_local_subs_used[i]); |
|
- | 2927 | } |
|
- | 2928 | free (font->fd_local_subs_used); |
|
- | 2929 | } |
|
- | 2930 | free (font->fd_default_width); |
|
- | 2931 | free (font->fd_nominal_width); |
|
1920 | } |
2932 | } |
Line 1921... | Line -... | ||
1921 | - | ||
1922 | if (font->data) |
2933 | |
Line 1923... | Line 2934... | ||
1923 | free (font->data); |
2934 | free (font->data); |
1924 | 2935 | ||
Line 1925... | Line 2936... | ||
1925 | free (font); |
2936 | free (font); |
Line 1949... | Line 2960... | ||
1949 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2960 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1950 | goto fail1; |
2961 | goto fail1; |
1951 | } |
2962 | } |
Line 1952... | Line 2963... | ||
1952 | 2963 | ||
1953 | if (font->font_name) { |
2964 | if (font->font_name) { |
1954 | cff_subset->font_name = strdup (font->font_name); |
2965 | cff_subset->family_name_utf8 = strdup (font->font_name); |
1955 | if (cff_subset->font_name == NULL) { |
2966 | if (cff_subset->family_name_utf8 == NULL) { |
1956 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2967 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1957 | goto fail2; |
2968 | goto fail2; |
1958 | } |
2969 | } |
1959 | } else { |
2970 | } else { |
1960 | cff_subset->font_name = NULL; |
2971 | cff_subset->family_name_utf8 = NULL; |
Line 1961... | Line 2972... | ||
1961 | } |
2972 | } |
1962 | 2973 | ||
1963 | cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs); |
2974 | cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs); |
Line 1989... | Line 3000... | ||
1989 | return CAIRO_STATUS_SUCCESS; |
3000 | return CAIRO_STATUS_SUCCESS; |
Line 1990... | Line 3001... | ||
1990 | 3001 | ||
1991 | fail4: |
3002 | fail4: |
1992 | free (cff_subset->widths); |
3003 | free (cff_subset->widths); |
1993 | fail3: |
- | |
1994 | if (cff_subset->font_name) |
3004 | fail3: |
1995 | free (cff_subset->font_name); |
3005 | free (cff_subset->family_name_utf8); |
1996 | fail2: |
3006 | fail2: |
1997 | free (cff_subset->ps_name); |
3007 | free (cff_subset->ps_name); |
1998 | fail1: |
3008 | fail1: |
Line 2003... | Line 3013... | ||
2003 | 3013 | ||
2004 | void |
3014 | void |
2005 | _cairo_cff_subset_fini (cairo_cff_subset_t *subset) |
3015 | _cairo_cff_subset_fini (cairo_cff_subset_t *subset) |
2006 | { |
3016 | { |
2007 | free (subset->ps_name); |
- | |
2008 | if (subset->font_name) |
3017 | free (subset->ps_name); |
2009 | free (subset->font_name); |
3018 | free (subset->family_name_utf8); |
2010 | free (subset->widths); |
3019 | free (subset->widths); |
2011 | free (subset->data); |
3020 | free (subset->data); |
Line -... | Line 3021... | ||
- | 3021 | } |
|
- | 3022 | ||
- | 3023 | cairo_bool_t |
|
- | 3024 | _cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font) |
|
- | 3025 | { |
|
- | 3026 | const cairo_scaled_font_backend_t *backend; |
|
- | 3027 | cairo_int_status_t status; |
|
- | 3028 | unsigned char *data; |
|
- | 3029 | unsigned long data_length; |
|
- | 3030 | unsigned char *current_ptr; |
|
- | 3031 | unsigned char *data_end; |
|
- | 3032 | cff_header_t *header; |
|
- | 3033 | cff_index_element_t *element; |
|
- | 3034 | cairo_hash_table_t *top_dict; |
|
- | 3035 | cairo_array_t index; |
|
- | 3036 | int size; |
|
- | 3037 | cairo_bool_t is_cid = FALSE; |
|
- | 3038 | ||
- | 3039 | backend = scaled_font->backend; |
|
- | 3040 | data = NULL; |
|
- | 3041 | data_length = 0; |
|
- | 3042 | status = CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 3043 | /* Try to load an OpenType/CFF font */ |
|
- | 3044 | if (backend->load_truetype_table && |
|
- | 3045 | (status = backend->load_truetype_table (scaled_font, TT_TAG_CFF, |
|
- | 3046 | 0, NULL, &data_length)) == CAIRO_INT_STATUS_SUCCESS) |
|
- | 3047 | { |
|
- | 3048 | data = malloc (data_length); |
|
- | 3049 | if (unlikely (data == NULL)) { |
|
- | 3050 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 3051 | return FALSE; |
|
- | 3052 | } |
|
- | 3053 | ||
- | 3054 | status = backend->load_truetype_table (scaled_font, TT_TAG_CFF, |
|
- | 3055 | 0, data, &data_length); |
|
- | 3056 | if (unlikely (status)) |
|
- | 3057 | goto fail1; |
|
- | 3058 | } |
|
- | 3059 | /* Try to load a CFF font */ |
|
- | 3060 | if (status == CAIRO_INT_STATUS_UNSUPPORTED && |
|
- | 3061 | backend->load_type1_data && |
|
- | 3062 | (status = backend->load_type1_data (scaled_font, |
|
- | 3063 | 0, NULL, &data_length)) == CAIRO_INT_STATUS_SUCCESS) |
|
- | 3064 | { |
|
- | 3065 | data = malloc (data_length); |
|
- | 3066 | if (unlikely (data == NULL)) { |
|
- | 3067 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 3068 | return FALSE; |
|
- | 3069 | } |
|
- | 3070 | ||
- | 3071 | status = backend->load_type1_data (scaled_font, 0, data, &data_length); |
|
- | 3072 | if (unlikely (status)) |
|
- | 3073 | goto fail1; |
|
- | 3074 | } |
|
- | 3075 | if (status) |
|
- | 3076 | goto fail1; |
|
- | 3077 | ||
- | 3078 | /* Check if it looks like a CFF font */ |
|
- | 3079 | if (!check_fontdata_is_cff (data, data_length)) |
|
- | 3080 | goto fail1; |
|
- | 3081 | ||
- | 3082 | data_end = data + data_length; |
|
- | 3083 | ||
- | 3084 | /* skip header */ |
|
- | 3085 | if (data_length < sizeof (cff_header_t)) |
|
- | 3086 | goto fail1; |
|
- | 3087 | ||
- | 3088 | header = (cff_header_t *) data; |
|
- | 3089 | current_ptr = data + header->header_size; |
|
- | 3090 | ||
- | 3091 | /* skip name */ |
|
- | 3092 | cff_index_init (&index); |
|
- | 3093 | status = cff_index_read (&index, ¤t_ptr, data_end); |
|
- | 3094 | cff_index_fini (&index); |
|
- | 3095 | ||
- | 3096 | if (status) |
|
- | 3097 | goto fail1; |
|
- | 3098 | ||
- | 3099 | /* read top dict */ |
|
- | 3100 | cff_index_init (&index); |
|
- | 3101 | status = cff_index_read (&index, ¤t_ptr, data_end); |
|
- | 3102 | if (unlikely (status)) |
|
- | 3103 | goto fail2; |
|
- | 3104 | ||
- | 3105 | status = cff_dict_init (&top_dict); |
|
- | 3106 | if (unlikely (status)) |
|
- | 3107 | goto fail2; |
|
- | 3108 | ||
- | 3109 | element = _cairo_array_index (&index, 0); |
|
- | 3110 | status = cff_dict_read (top_dict, element->data, element->length); |
|
- | 3111 | if (unlikely (status)) |
|
- | 3112 | goto fail3; |
|
- | 3113 | ||
- | 3114 | /* check for ROS operator indicating a CID font */ |
|
- | 3115 | if (cff_dict_get_operands (top_dict, ROS_OP, &size) != NULL) |
|
- | 3116 | is_cid = TRUE; |
|
- | 3117 | ||
- | 3118 | fail3: |
|
- | 3119 | cff_dict_fini (top_dict); |
|
- | 3120 | ||
- | 3121 | fail2: |
|
- | 3122 | cff_index_fini (&index); |
|
- | 3123 | ||
- | 3124 | fail1: |
|
- | 3125 | free (data); |
|
- | 3126 | ||
- | 3127 | return is_cid; |
|
2012 | } |
3128 | } |
2013 | 3129 | ||
2014 | static cairo_int_status_t |
3130 | static cairo_int_status_t |
2015 | _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset, |
3131 | _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset, |
2016 | cairo_cff_font_t **font_return, |
3132 | cairo_cff_font_t **font_return, |
Line 2073... | Line 3189... | ||
2073 | cff_index_init (&font->charstrings_index); |
3189 | cff_index_init (&font->charstrings_index); |
2074 | cff_index_init (&font->global_sub_index); |
3190 | cff_index_init (&font->global_sub_index); |
2075 | cff_index_init (&font->local_sub_index); |
3191 | cff_index_init (&font->local_sub_index); |
2076 | cff_index_init (&font->charstrings_subset_index); |
3192 | cff_index_init (&font->charstrings_subset_index); |
2077 | cff_index_init (&font->strings_subset_index); |
3193 | cff_index_init (&font->strings_subset_index); |
- | 3194 | font->global_subs_used = NULL; |
|
- | 3195 | font->local_subs_used = NULL; |
|
- | 3196 | font->subset_subroutines = FALSE; |
|
2078 | font->fdselect = NULL; |
3197 | font->fdselect = NULL; |
2079 | font->fd_dict = NULL; |
3198 | font->fd_dict = NULL; |
2080 | font->fd_private_dict = NULL; |
3199 | font->fd_private_dict = NULL; |
2081 | font->fd_local_sub_index = NULL; |
3200 | font->fd_local_sub_index = NULL; |
2082 | font->fdselect_subset = NULL; |
3201 | font->fdselect_subset = NULL; |
Line 2090... | Line 3209... | ||
2090 | fail5: |
3209 | fail5: |
2091 | _cairo_hash_table_destroy (font->top_dict); |
3210 | _cairo_hash_table_destroy (font->top_dict); |
2092 | fail4: |
3211 | fail4: |
2093 | free (font->widths); |
3212 | free (font->widths); |
2094 | fail3: |
3213 | fail3: |
2095 | if (font->font_name) |
- | |
2096 | free (font->font_name); |
3214 | free (font->font_name); |
2097 | free (font->ps_name); |
3215 | free (font->ps_name); |
2098 | fail2: |
3216 | fail2: |
2099 | free (font->subset_font_name); |
3217 | free (font->subset_font_name); |
2100 | fail1: |
3218 | fail1: |
2101 | _cairo_array_fini (&font->output); |
3219 | _cairo_array_fini (&font->output); |
Line 2111... | Line 3229... | ||
2111 | { |
3229 | { |
2112 | cairo_int_status_t status; |
3230 | cairo_int_status_t status; |
2113 | cff_header_t header; |
3231 | cff_header_t header; |
2114 | cairo_array_t *charstring; |
3232 | cairo_array_t *charstring; |
2115 | unsigned char buf[40]; |
3233 | unsigned char buf[40]; |
2116 | unsigned char *end_buf; |
3234 | unsigned char *end_buf, *end_buf2; |
2117 | unsigned int i; |
3235 | unsigned int i; |
- | 3236 | int sid; |
|
Line 2118... | Line 3237... | ||
2118 | 3237 | ||
2119 | /* Create header */ |
3238 | /* Create header */ |
2120 | header.major = 1; |
3239 | header.major = 1; |
2121 | header.minor = 0; |
3240 | header.minor = 0; |
2122 | header.header_size = 4; |
3241 | header.header_size = 4; |
2123 | header.offset_size = 4; |
3242 | header.offset_size = 4; |
Line 2124... | Line 3243... | ||
2124 | font->header = &header; |
3243 | font->header = &header; |
2125 | 3244 | ||
- | 3245 | /* Create Top Dict */ |
|
- | 3246 | font->is_cid = FALSE; |
|
- | 3247 | ||
- | 3248 | snprintf((char*)buf, sizeof(buf), "CairoFont-%u-%u", |
|
- | 3249 | font->scaled_font_subset->font_id, |
|
- | 3250 | font->scaled_font_subset->subset_id); |
|
- | 3251 | sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); |
|
- | 3252 | status = cff_index_append_copy (&font->strings_subset_index, |
|
- | 3253 | (unsigned char *)buf, |
|
- | 3254 | strlen((char*)buf)); |
|
- | 3255 | if (unlikely (status)) |
|
- | 3256 | return status; |
|
- | 3257 | ||
- | 3258 | end_buf = encode_integer (buf, sid); |
|
- | 3259 | status = cff_dict_set_operands (font->top_dict, FULLNAME_OP, |
|
- | 3260 | buf, end_buf - buf); |
|
- | 3261 | if (unlikely (status)) |
|
- | 3262 | return status; |
|
- | 3263 | ||
- | 3264 | status = cff_dict_set_operands (font->top_dict, FAMILYNAME_OP, |
|
- | 3265 | buf, end_buf - buf); |
|
- | 3266 | if (unlikely (status)) |
|
2126 | /* Create Top Dict */ |
3267 | return status; |
2127 | font->is_cid = FALSE; |
3268 | |
2128 | end_buf = encode_integer (buf, type2_subset->x_min); |
3269 | end_buf = encode_integer (buf, type2_subset->x_min); |
2129 | end_buf = encode_integer (end_buf, type2_subset->y_min); |
3270 | end_buf = encode_integer (end_buf, type2_subset->y_min); |
2130 | end_buf = encode_integer (end_buf, type2_subset->x_max); |
3271 | end_buf = encode_integer (end_buf, type2_subset->x_max); |
Line 2138... | Line 3279... | ||
2138 | status = cff_dict_set_operands (font->top_dict, |
3279 | status = cff_dict_set_operands (font->top_dict, |
2139 | CHARSTRINGS_OP, buf, end_buf - buf); |
3280 | CHARSTRINGS_OP, buf, end_buf - buf); |
2140 | if (unlikely (status)) |
3281 | if (unlikely (status)) |
2141 | return status; |
3282 | return status; |
Line 2142... | Line -... | ||
2142 | - | ||
2143 | status = cff_dict_set_operands (font->top_dict, |
- | |
2144 | FDSELECT_OP, buf, end_buf - buf); |
- | |
2145 | if (unlikely (status)) |
- | |
Line -... | Line 3283... | ||
- | 3283 | ||
2146 | return status; |
3284 | |
2147 | 3285 | if (font->scaled_font_subset->is_latin) { |
|
- | 3286 | status = cff_dict_set_operands (font->top_dict, |
|
- | 3287 | ENCODING_OP, buf, end_buf - buf); |
|
- | 3288 | if (unlikely (status)) |
|
- | 3289 | return status; |
|
- | 3290 | ||
- | 3291 | /* Private has two operands - size and offset */ |
|
2148 | status = cff_dict_set_operands (font->top_dict, |
3292 | end_buf2 = encode_integer_max (end_buf, 0); |
- | 3293 | cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf2 - buf); |
|
- | 3294 | if (unlikely (status)) |
|
- | 3295 | return status; |
|
- | 3296 | ||
- | 3297 | } else { |
|
- | 3298 | status = cff_dict_set_operands (font->top_dict, |
|
- | 3299 | FDSELECT_OP, buf, end_buf - buf); |
|
- | 3300 | if (unlikely (status)) |
|
- | 3301 | return status; |
|
- | 3302 | ||
- | 3303 | status = cff_dict_set_operands (font->top_dict, |
|
2149 | FDARRAY_OP, buf, end_buf - buf); |
3304 | FDARRAY_OP, buf, end_buf - buf); |
- | 3305 | if (unlikely (status)) |
|
Line 2150... | Line 3306... | ||
2150 | if (unlikely (status)) |
3306 | return status; |
2151 | return status; |
3307 | } |
2152 | 3308 | ||
2153 | status = cff_dict_set_operands (font->top_dict, |
3309 | status = cff_dict_set_operands (font->top_dict, |
Line -... | Line 3310... | ||
- | 3310 | CHARSET_OP, buf, end_buf - buf); |
|
2154 | CHARSET_OP, buf, end_buf - buf); |
3311 | if (unlikely (status)) |
2155 | if (unlikely (status)) |
3312 | return status; |
2156 | return status; |
3313 | |
Line 2157... | Line 3314... | ||
2157 | 3314 | if (!font->scaled_font_subset->is_latin) { |
|
2158 | status = cairo_cff_font_set_ros_strings (font); |
3315 | status = cairo_cff_font_set_ros_strings (font); |
2159 | if (unlikely (status)) |
3316 | if (unlikely (status)) |
2160 | return status; |
3317 | return status; |
- | 3318 | ||
- | 3319 | /* Create CID FD dictionary */ |
|
- | 3320 | status = cairo_cff_font_create_cid_fontdict (font); |
|
- | 3321 | if (unlikely (status)) |
|
- | 3322 | return status; |
|
Line 2161... | Line 3323... | ||
2161 | 3323 | } else { |
|
2162 | /* Create CID FD dictionary */ |
3324 | font->private_dict_offset = malloc (sizeof (int)); |
2163 | status = cairo_cff_font_create_cid_fontdict (font); |
3325 | if (unlikely (font->private_dict_offset == NULL)) |
Line 2174... | Line 3336... | ||
2174 | 3336 | ||
2175 | if (unlikely (status)) |
3337 | if (unlikely (status)) |
2176 | return status; |
3338 | return status; |
Line -... | Line 3339... | ||
- | 3339 | } |
|
- | 3340 | ||
- | 3341 | if (font->scaled_font_subset->is_latin) |
|
2177 | } |
3342 | status = cairo_cff_font_add_euro_charset_string (font); |
2178 | 3343 | ||
2179 | status = cairo_cff_font_write_subset (font); |
3344 | status = cairo_cff_font_write_subset (font); |
Line 2180... | Line 3345... | ||
2180 | if (unlikely (status)) |
3345 | if (unlikely (status)) |
Line 2208... | Line 3373... | ||
2208 | 3373 | ||
2209 | status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length); |
3374 | status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length); |
2210 | if (unlikely (status)) |
3375 | if (unlikely (status)) |
Line 2211... | Line 3376... | ||
2211 | goto fail2; |
3376 | goto fail2; |
2212 | 3377 | ||
2213 | cff_subset->font_name = NULL; |
3378 | cff_subset->family_name_utf8 = NULL; |
2214 | cff_subset->ps_name = strdup (font->ps_name); |
3379 | cff_subset->ps_name = strdup (font->ps_name); |
2215 | if (unlikely (cff_subset->ps_name == NULL)) { |
3380 | if (unlikely (cff_subset->ps_name == NULL)) { |
2216 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
3381 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
Line 2239... | Line 3404... | ||
2239 | goto fail4; |
3404 | goto fail4; |
2240 | } |
3405 | } |
Line 2241... | Line 3406... | ||
2241 | 3406 | ||
2242 | memcpy (cff_subset->data, data, length); |
3407 | memcpy (cff_subset->data, data, length); |
2243 | cff_subset->data_length = length; |
- | |
Line 2244... | Line 3408... | ||
2244 | cff_subset->data_length = length; |
3408 | cff_subset->data_length = length; |
2245 | 3409 | ||
Line 2246... | Line 3410... | ||
2246 | _cairo_type2_charstrings_fini (&type2_subset); |
3410 | _cairo_type2_charstrings_fini (&type2_subset); |