Rev 1897 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1897 | Rev 3959 | ||
---|---|---|---|
- | 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 |
6 | * modify it either under the terms of the GNU Lesser General Public |
7 | * modify it either under the terms of the GNU Lesser General Public |
7 | * License version 2.1 as published by the Free Software Foundation |
8 | * License version 2.1 as published by the Free Software Foundation |
8 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
9 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
9 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
10 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
10 | * notice, a recipient may use your version of this file under either |
11 | * notice, a recipient may use your version of this file under either |
11 | * the MPL or the LGPL. |
12 | * the MPL or the LGPL. |
12 | * |
13 | * |
13 | * You should have received a copy of the LGPL along with this library |
14 | * You should have received a copy of the LGPL along with this library |
14 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
15 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
15 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
16 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
16 | * You should have received a copy of the MPL along with this library |
17 | * You should have received a copy of the MPL along with this library |
17 | * in the file COPYING-MPL-1.1 |
18 | * in the file COPYING-MPL-1.1 |
18 | * |
19 | * |
19 | * The contents of this file are subject to the Mozilla Public License |
20 | * The contents of this file are subject to the Mozilla Public License |
20 | * Version 1.1 (the "License"); you may not use this file except in |
21 | * Version 1.1 (the "License"); you may not use this file except in |
21 | * compliance with the License. You may obtain a copy of the License at |
22 | * compliance with the License. You may obtain a copy of the License at |
22 | * http://www.mozilla.org/MPL/ |
23 | * http://www.mozilla.org/MPL/ |
23 | * |
24 | * |
24 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
25 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
25 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
26 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
26 | * the specific language governing rights and limitations. |
27 | * the specific language governing rights and limitations. |
27 | * |
28 | * |
28 | * The Original Code is the cairo graphics library. |
29 | * The Original Code is the cairo graphics library. |
29 | * |
30 | * |
30 | * The Initial Developer of the Original Code is Adrian Johnson. |
31 | * The Initial Developer of the Original Code is Adrian Johnson. |
31 | * |
32 | * |
32 | * Contributor(s): |
33 | * Contributor(s): |
33 | * Adrian Johnson |
34 | * Adrian Johnson |
34 | * Eugeniy Meshcheryakov |
35 | * Eugeniy Meshcheryakov |
35 | */ |
36 | */ |
36 | 37 | ||
37 | /* |
38 | /* |
38 | * Useful links: |
39 | * Useful links: |
39 | * http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf |
40 | * http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5176.CFF.pdf |
- | 41 | * http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5177.Type2.pdf |
|
40 | */ |
42 | */ |
41 | 43 | ||
42 | #define _BSD_SOURCE /* for snprintf(), strdup() */ |
44 | #define _BSD_SOURCE /* for snprintf(), strdup() */ |
43 | #include "cairoint.h" |
45 | #include "cairoint.h" |
- | 46 | ||
- | 47 | #include "cairo-array-private.h" |
|
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 |
47 | 51 | ||
48 | #include "cairo-scaled-font-subsets-private.h" |
52 | #include "cairo-scaled-font-subsets-private.h" |
49 | #include "cairo-truetype-subset-private.h" |
53 | #include "cairo-truetype-subset-private.h" |
50 | #include |
54 | #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. */ |
54 | #define BASEFONTNAME_OP 0x0c16 |
59 | #define BASEFONTNAME_OP 0x0c16 |
55 | #define CIDCOUNT_OP 0x0c22 |
60 | #define CIDCOUNT_OP 0x0c22 |
56 | #define CHARSET_OP 0x000f |
61 | #define CHARSET_OP 0x000f |
57 | #define CHARSTRINGS_OP 0x0011 |
62 | #define CHARSTRINGS_OP 0x0011 |
58 | #define COPYRIGHT_OP 0x0c00 |
63 | #define COPYRIGHT_OP 0x0c00 |
- | 64 | #define DEFAULTWIDTH_OP 0x0014 |
|
59 | #define ENCODING_OP 0x0010 |
65 | #define ENCODING_OP 0x0010 |
60 | #define FAMILYNAME_OP 0x0003 |
66 | #define FAMILYNAME_OP 0x0003 |
61 | #define FDARRAY_OP 0x0c24 |
67 | #define FDARRAY_OP 0x0c24 |
62 | #define FDSELECT_OP 0x0c25 |
68 | #define FDSELECT_OP 0x0c25 |
63 | #define FONTBBOX_OP 0x0005 |
69 | #define FONTBBOX_OP 0x0005 |
- | 70 | #define FONTMATRIX_OP 0x0c07 |
|
64 | #define FONTNAME_OP 0x0c26 |
71 | #define FONTNAME_OP 0x0c26 |
65 | #define FULLNAME_OP 0x0002 |
72 | #define FULLNAME_OP 0x0002 |
66 | #define LOCAL_SUB_OP 0x0013 |
73 | #define LOCAL_SUB_OP 0x0013 |
- | 74 | #define NOMINALWIDTH_OP 0x0015 |
|
67 | #define NOTICE_OP 0x0001 |
75 | #define NOTICE_OP 0x0001 |
68 | #define POSTSCRIPT_OP 0x0c15 |
76 | #define POSTSCRIPT_OP 0x0c15 |
69 | #define PRIVATE_OP 0x0012 |
77 | #define PRIVATE_OP 0x0012 |
70 | #define ROS_OP 0x0c1e |
78 | #define ROS_OP 0x0c1e |
71 | #define UNIQUEID_OP 0x000d |
79 | #define UNIQUEID_OP 0x000d |
72 | #define VERSION_OP 0x0000 |
80 | #define VERSION_OP 0x0000 |
73 | #define WEIGHT_OP 0x0004 |
81 | #define WEIGHT_OP 0x0004 |
74 | #define XUID_OP 0x000e |
82 | #define XUID_OP 0x000e |
75 | 83 | ||
76 | #define NUM_STD_STRINGS 391 |
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 */ |
|
- | 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; |
81 | uint8_t header_size; |
111 | uint8_t header_size; |
82 | uint8_t offset_size; |
112 | uint8_t offset_size; |
83 | } cff_header_t; |
113 | } cff_header_t; |
84 | 114 | ||
85 | typedef struct _cff_index_element { |
115 | typedef struct _cff_index_element { |
86 | cairo_bool_t is_copy; |
116 | cairo_bool_t is_copy; |
87 | unsigned char *data; |
117 | unsigned char *data; |
88 | int length; |
118 | int length; |
89 | } cff_index_element_t; |
119 | } cff_index_element_t; |
90 | 120 | ||
91 | typedef struct _cff_dict_operator { |
121 | typedef struct _cff_dict_operator { |
92 | cairo_hash_entry_t base; |
122 | cairo_hash_entry_t base; |
93 | 123 | ||
94 | unsigned short operator; |
124 | unsigned short operator; |
95 | unsigned char *operand; |
125 | unsigned char *operand; |
96 | int operand_length; |
126 | int operand_length; |
97 | int operand_offset; |
127 | int operand_offset; |
98 | } cff_dict_operator_t; |
128 | } cff_dict_operator_t; |
99 | 129 | ||
100 | typedef struct _cairo_cff_font { |
130 | typedef struct _cairo_cff_font { |
101 | 131 | ||
102 | cairo_scaled_font_subset_t *scaled_font_subset; |
132 | cairo_scaled_font_subset_t *scaled_font_subset; |
103 | const cairo_scaled_font_backend_t *backend; |
133 | const cairo_scaled_font_backend_t *backend; |
104 | 134 | ||
105 | /* Font Data */ |
135 | /* Font Data */ |
106 | unsigned char *data; |
136 | unsigned char *data; |
107 | unsigned long data_length; |
137 | unsigned long data_length; |
108 | unsigned char *current_ptr; |
138 | unsigned char *current_ptr; |
109 | unsigned char *data_end; |
139 | unsigned char *data_end; |
110 | cff_header_t *header; |
140 | cff_header_t *header; |
111 | char *font_name; |
141 | char *font_name; |
112 | char *ps_name; |
142 | char *ps_name; |
113 | cairo_hash_table_t *top_dict; |
143 | cairo_hash_table_t *top_dict; |
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; |
|
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; |
128 | cairo_array_t *fd_local_sub_index; |
164 | cairo_array_t *fd_local_sub_index; |
- | 165 | int *fd_local_sub_bias; |
|
- | 166 | double *fd_default_width; |
|
- | 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; |
132 | cairo_array_t charstrings_subset_index; |
171 | cairo_array_t charstrings_subset_index; |
133 | cairo_array_t strings_subset_index; |
172 | 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; |
136 | int *fd_subset_map; |
176 | int *fd_subset_map; |
137 | int *private_dict_offset; |
177 | int *private_dict_offset; |
- | 178 | cairo_bool_t subset_subroutines; |
|
- | 179 | cairo_bool_t *global_subs_used; |
|
- | 180 | cairo_bool_t *local_subs_used; |
|
- | 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 */ |
141 | int *widths; |
185 | int *widths; |
142 | int x_min, y_min, x_max, y_max; |
186 | int x_min, y_min, x_max, y_max; |
143 | int ascent, descent; |
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; |
|
- | 198 | cairo_bool_t type2_found_width; |
|
- | 199 | int type2_width; |
|
- | 200 | cairo_bool_t type2_has_path; |
|
144 | 201 | ||
145 | } cairo_cff_font_t; |
202 | } cairo_cff_font_t; |
146 | 203 | ||
147 | /* Encoded integer using maximum sized encoding. This is required for |
204 | /* Encoded integer using maximum sized encoding. This is required for |
148 | * operands that are later modified after encoding. */ |
205 | * operands that are later modified after encoding. */ |
149 | static unsigned char * |
206 | static unsigned char * |
150 | encode_integer_max (unsigned char *p, int i) |
207 | encode_integer_max (unsigned char *p, int i) |
151 | { |
208 | { |
152 | *p++ = 29; |
209 | *p++ = 29; |
153 | *p++ = i >> 24; |
210 | *p++ = i >> 24; |
154 | *p++ = (i >> 16) & 0xff; |
211 | *p++ = (i >> 16) & 0xff; |
155 | *p++ = (i >> 8) & 0xff; |
212 | *p++ = (i >> 8) & 0xff; |
156 | *p++ = i & 0xff; |
213 | *p++ = i & 0xff; |
157 | return p; |
214 | return p; |
158 | } |
215 | } |
159 | 216 | ||
160 | static unsigned char * |
217 | static unsigned char * |
161 | encode_integer (unsigned char *p, int i) |
218 | encode_integer (unsigned char *p, int i) |
162 | { |
219 | { |
163 | if (i >= -107 && i <= 107) { |
220 | if (i >= -107 && i <= 107) { |
164 | *p++ = i + 139; |
221 | *p++ = i + 139; |
165 | } else if (i >= 108 && i <= 1131) { |
222 | } else if (i >= 108 && i <= 1131) { |
166 | i -= 108; |
223 | i -= 108; |
167 | *p++ = (i >> 8)+ 247; |
224 | *p++ = (i >> 8)+ 247; |
168 | *p++ = i & 0xff; |
225 | *p++ = i & 0xff; |
169 | } else if (i >= -1131 && i <= -108) { |
226 | } else if (i >= -1131 && i <= -108) { |
170 | i = -i - 108; |
227 | i = -i - 108; |
171 | *p++ = (i >> 8)+ 251; |
228 | *p++ = (i >> 8)+ 251; |
172 | *p++ = i & 0xff; |
229 | *p++ = i & 0xff; |
173 | } else if (i >= -32768 && i <= 32767) { |
230 | } else if (i >= -32768 && i <= 32767) { |
174 | *p++ = 28; |
231 | *p++ = 28; |
175 | *p++ = (i >> 8) & 0xff; |
232 | *p++ = (i >> 8) & 0xff; |
176 | *p++ = i & 0xff; |
233 | *p++ = i & 0xff; |
177 | } else { |
234 | } else { |
178 | p = encode_integer_max (p, i); |
235 | p = encode_integer_max (p, i); |
179 | } |
236 | } |
180 | return p; |
237 | return p; |
181 | } |
238 | } |
182 | 239 | ||
183 | static unsigned char * |
240 | static unsigned char * |
184 | decode_integer (unsigned char *p, int *integer) |
241 | decode_integer (unsigned char *p, int *integer) |
185 | { |
242 | { |
186 | if (*p == 28) { |
243 | if (*p == 28) { |
187 | *integer = (int)(p[1]<<8 | p[2]); |
244 | *integer = (int)(p[1]<<8 | p[2]); |
188 | p += 3; |
245 | p += 3; |
189 | } else if (*p == 29) { |
246 | } else if (*p == 29) { |
190 | *integer = (int)((p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]); |
247 | *integer = (int)((p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]); |
191 | p += 5; |
248 | p += 5; |
192 | } else if (*p >= 32 && *p <= 246) { |
249 | } else if (*p >= 32 && *p <= 246) { |
193 | *integer = *p++ - 139; |
250 | *integer = *p++ - 139; |
194 | } else if (*p <= 250) { |
251 | } else if (*p <= 250) { |
195 | *integer = (p[0] - 247) * 256 + p[1] + 108; |
252 | *integer = (p[0] - 247) * 256 + p[1] + 108; |
196 | p += 2; |
253 | p += 2; |
197 | } else if (*p <= 254) { |
254 | } else if (*p <= 254) { |
198 | *integer = -(p[0] - 251) * 256 - p[1] - 108; |
255 | *integer = -(p[0] - 251) * 256 - p[1] - 108; |
199 | p += 2; |
256 | p += 2; |
200 | } else { |
257 | } else { |
201 | *integer = 0; |
258 | *integer = 0; |
202 | p += 1; |
259 | p += 1; |
203 | } |
260 | } |
204 | return p; |
261 | return p; |
205 | } |
262 | } |
- | 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 | { |
210 | unsigned short op = 0; |
362 | unsigned short op = 0; |
211 | 363 | ||
212 | op = *p++; |
364 | op = *p++; |
213 | if (op == 12) { |
365 | if (op == 12) { |
214 | op <<= 8; |
366 | op <<= 8; |
215 | op |= *p++; |
367 | op |= *p++; |
216 | } |
368 | } |
217 | *operator = op; |
369 | *operator = op; |
218 | return p; |
370 | return p; |
219 | } |
371 | } |
220 | 372 | ||
221 | /* return 0 if not an operand */ |
373 | /* return 0 if not an operand */ |
222 | static int |
374 | static int |
223 | operand_length (unsigned char *p) |
375 | operand_length (unsigned char *p) |
224 | { |
376 | { |
225 | unsigned char *begin = p; |
377 | unsigned char *begin = p; |
226 | 378 | ||
227 | if (*p == 28) |
379 | if (*p == 28) |
228 | return 3; |
380 | return 3; |
229 | 381 | ||
230 | if (*p == 29) |
382 | if (*p == 29) |
231 | return 5; |
383 | return 5; |
232 | 384 | ||
233 | if (*p >= 32 && *p <= 246) |
385 | if (*p >= 32 && *p <= 246) |
234 | return 1; |
386 | return 1; |
235 | 387 | ||
236 | if (*p >= 247 && *p <= 254) |
388 | if (*p >= 247 && *p <= 254) |
237 | return 2; |
389 | return 2; |
238 | 390 | ||
239 | if (*p == 30) { |
391 | if (*p == 30) { |
240 | while ((*p & 0x0f) != 0x0f) |
392 | while ((*p & 0x0f) != 0x0f) |
241 | p++; |
393 | p++; |
242 | return p - begin + 1; |
394 | return p - begin + 1; |
243 | } |
395 | } |
244 | 396 | ||
245 | return 0; |
397 | return 0; |
246 | } |
398 | } |
247 | 399 | ||
248 | static unsigned char * |
400 | static unsigned char * |
249 | encode_index_offset (unsigned char *p, int offset_size, unsigned long offset) |
401 | encode_index_offset (unsigned char *p, int offset_size, unsigned long offset) |
250 | { |
402 | { |
251 | while (--offset_size >= 0) { |
403 | while (--offset_size >= 0) { |
252 | p[offset_size] = (unsigned char) (offset & 0xff); |
404 | p[offset_size] = (unsigned char) (offset & 0xff); |
253 | offset >>= 8; |
405 | offset >>= 8; |
254 | } |
406 | } |
255 | return p + offset_size; |
407 | return p + offset_size; |
256 | } |
408 | } |
257 | 409 | ||
258 | static unsigned long |
410 | static unsigned long |
259 | decode_index_offset(unsigned char *p, int off_size) |
411 | decode_index_offset(unsigned char *p, int off_size) |
260 | { |
412 | { |
261 | unsigned long offset = 0; |
413 | unsigned long offset = 0; |
262 | 414 | ||
263 | while (off_size-- > 0) |
415 | while (off_size-- > 0) |
264 | offset = offset*256 + *p++; |
416 | offset = offset*256 + *p++; |
265 | return offset; |
417 | return offset; |
266 | } |
418 | } |
267 | 419 | ||
268 | static void |
420 | static void |
269 | cff_index_init (cairo_array_t *index) |
421 | cff_index_init (cairo_array_t *index) |
270 | { |
422 | { |
271 | _cairo_array_init (index, sizeof (cff_index_element_t)); |
423 | _cairo_array_init (index, sizeof (cff_index_element_t)); |
272 | } |
424 | } |
273 | 425 | ||
274 | static cairo_int_status_t |
426 | static cairo_int_status_t |
275 | cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_ptr) |
427 | cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_ptr) |
276 | { |
428 | { |
277 | cff_index_element_t element; |
429 | cff_index_element_t element; |
278 | unsigned char *data, *p; |
430 | unsigned char *data, *p; |
279 | cairo_status_t status; |
431 | cairo_status_t status; |
280 | int offset_size, count, start, i; |
432 | int offset_size, count, start, i; |
281 | int end = 0; |
433 | int end = 0; |
282 | 434 | ||
283 | p = *ptr; |
435 | p = *ptr; |
284 | if (p + 2 > end_ptr) |
436 | if (p + 2 > end_ptr) |
285 | return CAIRO_INT_STATUS_UNSUPPORTED; |
437 | return CAIRO_INT_STATUS_UNSUPPORTED; |
286 | count = be16_to_cpu( *((uint16_t *)p) ); |
438 | count = be16_to_cpu( *((uint16_t *)p) ); |
287 | p += 2; |
439 | p += 2; |
288 | if (count > 0) { |
440 | if (count > 0) { |
289 | offset_size = *p++; |
441 | offset_size = *p++; |
290 | if (p + (count + 1)*offset_size > end_ptr) |
442 | if (p + (count + 1)*offset_size > end_ptr) |
291 | return CAIRO_INT_STATUS_UNSUPPORTED; |
443 | return CAIRO_INT_STATUS_UNSUPPORTED; |
292 | data = p + offset_size*(count + 1) - 1; |
444 | data = p + offset_size*(count + 1) - 1; |
293 | start = decode_index_offset (p, offset_size); |
445 | start = decode_index_offset (p, offset_size); |
294 | p += offset_size; |
446 | p += offset_size; |
295 | for (i = 0; i < count; i++) { |
447 | for (i = 0; i < count; i++) { |
296 | end = decode_index_offset (p, offset_size); |
448 | end = decode_index_offset (p, offset_size); |
297 | p += offset_size; |
449 | p += offset_size; |
298 | if (p > end_ptr) |
450 | if (p > end_ptr) |
299 | return CAIRO_INT_STATUS_UNSUPPORTED; |
451 | return CAIRO_INT_STATUS_UNSUPPORTED; |
300 | element.length = end - start; |
452 | element.length = end - start; |
301 | element.is_copy = FALSE; |
453 | element.is_copy = FALSE; |
302 | element.data = data + start; |
454 | element.data = data + start; |
303 | status = _cairo_array_append (index, &element); |
455 | status = _cairo_array_append (index, &element); |
304 | if (unlikely (status)) |
456 | if (unlikely (status)) |
305 | return status; |
457 | return status; |
306 | start = end; |
458 | start = end; |
307 | } |
459 | } |
308 | p = data + end; |
460 | p = data + end; |
309 | } |
461 | } |
310 | *ptr = p; |
462 | *ptr = p; |
311 | 463 | ||
312 | return CAIRO_STATUS_SUCCESS; |
464 | return CAIRO_STATUS_SUCCESS; |
313 | } |
465 | } |
314 | 466 | ||
315 | static cairo_status_t |
467 | static cairo_status_t |
316 | cff_index_write (cairo_array_t *index, cairo_array_t *output) |
468 | cff_index_write (cairo_array_t *index, cairo_array_t *output) |
317 | { |
469 | { |
318 | int offset_size; |
470 | int offset_size; |
319 | int offset; |
471 | int offset; |
320 | int num_elem; |
472 | int num_elem; |
321 | int i; |
473 | int i; |
322 | cff_index_element_t *element; |
474 | cff_index_element_t *element; |
323 | uint16_t count; |
475 | uint16_t count; |
324 | unsigned char buf[5]; |
476 | unsigned char buf[5]; |
325 | cairo_status_t status; |
477 | cairo_status_t status; |
326 | 478 | ||
327 | num_elem = _cairo_array_num_elements (index); |
479 | num_elem = _cairo_array_num_elements (index); |
328 | count = cpu_to_be16 ((uint16_t) num_elem); |
480 | count = cpu_to_be16 ((uint16_t) num_elem); |
329 | status = _cairo_array_append_multiple (output, &count, 2); |
481 | status = _cairo_array_append_multiple (output, &count, 2); |
330 | if (unlikely (status)) |
482 | if (unlikely (status)) |
331 | return status; |
483 | return status; |
332 | 484 | ||
333 | if (num_elem == 0) |
485 | if (num_elem == 0) |
334 | return CAIRO_STATUS_SUCCESS; |
486 | return CAIRO_STATUS_SUCCESS; |
335 | 487 | ||
336 | /* Find maximum offset to determine offset size */ |
488 | /* Find maximum offset to determine offset size */ |
337 | offset = 1; |
489 | offset = 1; |
338 | for (i = 0; i < num_elem; i++) { |
490 | for (i = 0; i < num_elem; i++) { |
339 | element = _cairo_array_index (index, i); |
491 | element = _cairo_array_index (index, i); |
340 | offset += element->length; |
492 | offset += element->length; |
341 | } |
493 | } |
342 | if (offset < 0x100) |
494 | if (offset < 0x100) |
343 | offset_size = 1; |
495 | offset_size = 1; |
344 | else if (offset < 0x10000) |
496 | else if (offset < 0x10000) |
345 | offset_size = 2; |
497 | offset_size = 2; |
346 | else if (offset < 0x1000000) |
498 | else if (offset < 0x1000000) |
347 | offset_size = 3; |
499 | offset_size = 3; |
348 | else |
500 | else |
349 | offset_size = 4; |
501 | offset_size = 4; |
350 | 502 | ||
351 | buf[0] = (unsigned char) offset_size; |
503 | buf[0] = (unsigned char) offset_size; |
352 | status = _cairo_array_append (output, buf); |
504 | status = _cairo_array_append (output, buf); |
353 | if (unlikely (status)) |
505 | if (unlikely (status)) |
354 | return status; |
506 | return status; |
355 | 507 | ||
356 | offset = 1; |
508 | offset = 1; |
357 | encode_index_offset (buf, offset_size, offset); |
509 | encode_index_offset (buf, offset_size, offset); |
358 | status = _cairo_array_append_multiple (output, buf, offset_size); |
510 | status = _cairo_array_append_multiple (output, buf, offset_size); |
359 | if (unlikely (status)) |
511 | if (unlikely (status)) |
360 | return status; |
512 | return status; |
361 | 513 | ||
362 | for (i = 0; i < num_elem; i++) { |
514 | for (i = 0; i < num_elem; i++) { |
363 | element = _cairo_array_index (index, i); |
515 | element = _cairo_array_index (index, i); |
364 | offset += element->length; |
516 | offset += element->length; |
365 | encode_index_offset (buf, offset_size, offset); |
517 | encode_index_offset (buf, offset_size, offset); |
366 | status = _cairo_array_append_multiple (output, buf, offset_size); |
518 | status = _cairo_array_append_multiple (output, buf, offset_size); |
367 | if (unlikely (status)) |
519 | if (unlikely (status)) |
368 | return status; |
520 | return status; |
369 | } |
521 | } |
370 | 522 | ||
371 | for (i = 0; i < num_elem; i++) { |
523 | for (i = 0; i < num_elem; i++) { |
372 | element = _cairo_array_index (index, i); |
524 | 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, |
375 | element->length); |
528 | 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; |
380 | } |
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; |
|
- | 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) |
384 | { |
553 | { |
385 | cff_index_element_t element; |
554 | cff_index_element_t element; |
386 | 555 | ||
387 | element.length = length; |
556 | element.length = length; |
388 | element.is_copy = FALSE; |
557 | element.is_copy = FALSE; |
389 | element.data = object; |
558 | element.data = object; |
390 | 559 | ||
391 | return _cairo_array_append (index, &element); |
560 | return _cairo_array_append (index, &element); |
392 | } |
561 | } |
393 | 562 | ||
394 | static cairo_status_t |
563 | static cairo_status_t |
395 | cff_index_append_copy (cairo_array_t *index, |
564 | cff_index_append_copy (cairo_array_t *index, |
396 | const unsigned char *object, |
565 | const unsigned char *object, |
397 | unsigned int length) |
566 | unsigned int length) |
398 | { |
567 | { |
399 | cff_index_element_t element; |
568 | cff_index_element_t element; |
400 | cairo_status_t status; |
569 | cairo_status_t status; |
401 | 570 | ||
402 | element.length = length; |
571 | element.length = length; |
403 | element.is_copy = TRUE; |
572 | element.is_copy = TRUE; |
404 | element.data = malloc (element.length); |
573 | element.data = malloc (element.length); |
405 | if (unlikely (element.data == NULL)) |
574 | if (unlikely (element.data == NULL)) |
406 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
575 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
407 | 576 | ||
408 | memcpy (element.data, object, element.length); |
577 | memcpy (element.data, object, element.length); |
409 | 578 | ||
410 | status = _cairo_array_append (index, &element); |
579 | status = _cairo_array_append (index, &element); |
411 | if (unlikely (status)) { |
580 | if (unlikely (status)) { |
412 | free (element.data); |
581 | free (element.data); |
413 | return status; |
582 | return status; |
414 | } |
583 | } |
415 | 584 | ||
416 | return CAIRO_STATUS_SUCCESS; |
585 | return CAIRO_STATUS_SUCCESS; |
417 | } |
586 | } |
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; |
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 | } |
430 | _cairo_array_fini (index); |
599 | _cairo_array_fini (index); |
431 | } |
600 | } |
432 | 601 | ||
433 | static cairo_bool_t |
602 | static cairo_bool_t |
434 | _cairo_cff_dict_equal (const void *key_a, const void *key_b) |
603 | _cairo_cff_dict_equal (const void *key_a, const void *key_b) |
435 | { |
604 | { |
436 | const cff_dict_operator_t *op_a = key_a; |
605 | const cff_dict_operator_t *op_a = key_a; |
437 | const cff_dict_operator_t *op_b = key_b; |
606 | const cff_dict_operator_t *op_b = key_b; |
438 | 607 | ||
439 | return op_a->operator == op_b->operator; |
608 | return op_a->operator == op_b->operator; |
440 | } |
609 | } |
441 | 610 | ||
442 | static cairo_status_t |
611 | static cairo_status_t |
443 | cff_dict_init (cairo_hash_table_t **dict) |
612 | cff_dict_init (cairo_hash_table_t **dict) |
444 | { |
613 | { |
445 | *dict = _cairo_hash_table_create (_cairo_cff_dict_equal); |
614 | *dict = _cairo_hash_table_create (_cairo_cff_dict_equal); |
446 | if (unlikely (*dict == NULL)) |
615 | if (unlikely (*dict == NULL)) |
447 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
616 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
448 | 617 | ||
449 | return CAIRO_STATUS_SUCCESS; |
618 | return CAIRO_STATUS_SUCCESS; |
450 | } |
619 | } |
451 | 620 | ||
452 | static void |
621 | static void |
453 | _cairo_dict_init_key (cff_dict_operator_t *key, int operator) |
622 | _cairo_dict_init_key (cff_dict_operator_t *key, int operator) |
454 | { |
623 | { |
455 | key->base.hash = (unsigned long) operator; |
624 | key->base.hash = (unsigned long) operator; |
456 | key->operator = operator; |
625 | key->operator = operator; |
457 | } |
626 | } |
458 | 627 | ||
459 | static cairo_status_t |
628 | static cairo_status_t |
460 | cff_dict_create_operator (int operator, |
629 | cff_dict_create_operator (int operator, |
461 | unsigned char *operand, |
630 | unsigned char *operand, |
462 | int size, |
631 | int size, |
463 | cff_dict_operator_t **out) |
632 | cff_dict_operator_t **out) |
464 | { |
633 | { |
465 | cff_dict_operator_t *op; |
634 | cff_dict_operator_t *op; |
466 | 635 | ||
467 | op = malloc (sizeof (cff_dict_operator_t)); |
636 | op = malloc (sizeof (cff_dict_operator_t)); |
468 | if (unlikely (op == NULL)) |
637 | if (unlikely (op == NULL)) |
469 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
638 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
470 | 639 | ||
471 | _cairo_dict_init_key (op, operator); |
640 | _cairo_dict_init_key (op, operator); |
472 | op->operand = malloc (size); |
641 | op->operand = malloc (size); |
473 | if (unlikely (op->operand == NULL)) { |
642 | if (unlikely (op->operand == NULL)) { |
474 | free (op); |
643 | free (op); |
475 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
644 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
476 | } |
645 | } |
477 | 646 | ||
478 | memcpy (op->operand, operand, size); |
647 | memcpy (op->operand, operand, size); |
479 | op->operand_length = size; |
648 | op->operand_length = size; |
480 | op->operand_offset = -1; |
649 | op->operand_offset = -1; |
481 | 650 | ||
482 | *out = op; |
651 | *out = op; |
483 | return CAIRO_STATUS_SUCCESS; |
652 | return CAIRO_STATUS_SUCCESS; |
484 | } |
653 | } |
485 | 654 | ||
486 | static cairo_status_t |
655 | static cairo_status_t |
487 | cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size) |
656 | cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size) |
488 | { |
657 | { |
489 | unsigned char *end; |
658 | unsigned char *end; |
490 | cairo_array_t operands; |
659 | cairo_array_t operands; |
491 | cff_dict_operator_t *op; |
660 | cff_dict_operator_t *op; |
492 | unsigned short operator; |
661 | unsigned short operator; |
493 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
662 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
494 | int size; |
663 | int size; |
495 | 664 | ||
496 | end = p + dict_size; |
665 | end = p + dict_size; |
497 | _cairo_array_init (&operands, 1); |
666 | _cairo_array_init (&operands, 1); |
498 | while (p < end) { |
667 | while (p < end) { |
499 | size = operand_length (p); |
668 | size = operand_length (p); |
500 | if (size != 0) { |
669 | if (size != 0) { |
501 | status = _cairo_array_append_multiple (&operands, p, size); |
670 | status = _cairo_array_append_multiple (&operands, p, size); |
502 | if (unlikely (status)) |
671 | if (unlikely (status)) |
503 | goto fail; |
672 | goto fail; |
504 | 673 | ||
505 | p += size; |
674 | p += size; |
506 | } else { |
675 | } else { |
507 | p = decode_operator (p, &operator); |
676 | p = decode_operator (p, &operator); |
508 | status = cff_dict_create_operator (operator, |
677 | status = cff_dict_create_operator (operator, |
509 | _cairo_array_index (&operands, 0), |
678 | _cairo_array_index (&operands, 0), |
510 | _cairo_array_num_elements (&operands), |
679 | _cairo_array_num_elements (&operands), |
511 | &op); |
680 | &op); |
512 | if (unlikely (status)) |
681 | if (unlikely (status)) |
513 | goto fail; |
682 | goto fail; |
514 | 683 | ||
515 | status = _cairo_hash_table_insert (dict, &op->base); |
684 | status = _cairo_hash_table_insert (dict, &op->base); |
516 | if (unlikely (status)) |
685 | if (unlikely (status)) |
517 | goto fail; |
686 | goto fail; |
518 | 687 | ||
519 | _cairo_array_truncate (&operands, 0); |
688 | _cairo_array_truncate (&operands, 0); |
520 | } |
689 | } |
521 | } |
690 | } |
522 | 691 | ||
523 | fail: |
692 | fail: |
524 | _cairo_array_fini (&operands); |
693 | _cairo_array_fini (&operands); |
525 | 694 | ||
526 | return status; |
695 | return status; |
527 | } |
696 | } |
528 | 697 | ||
529 | static void |
698 | static void |
530 | cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator) |
699 | cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator) |
531 | { |
700 | { |
532 | cff_dict_operator_t key, *op; |
701 | cff_dict_operator_t key, *op; |
533 | 702 | ||
534 | _cairo_dict_init_key (&key, operator); |
703 | _cairo_dict_init_key (&key, operator); |
535 | op = _cairo_hash_table_lookup (dict, &key.base); |
704 | op = _cairo_hash_table_lookup (dict, &key.base); |
536 | if (op != NULL) { |
705 | if (op != NULL) { |
537 | free (op->operand); |
706 | free (op->operand); |
538 | _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op); |
707 | _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op); |
539 | free (op); |
708 | free (op); |
540 | } |
709 | } |
541 | } |
710 | } |
542 | 711 | ||
543 | static unsigned char * |
712 | static unsigned char * |
544 | cff_dict_get_operands (cairo_hash_table_t *dict, |
713 | cff_dict_get_operands (cairo_hash_table_t *dict, |
545 | unsigned short operator, |
714 | unsigned short operator, |
546 | int *size) |
715 | int *size) |
547 | { |
716 | { |
548 | cff_dict_operator_t key, *op; |
717 | cff_dict_operator_t key, *op; |
549 | 718 | ||
550 | _cairo_dict_init_key (&key, operator); |
719 | _cairo_dict_init_key (&key, operator); |
551 | op = _cairo_hash_table_lookup (dict, &key.base); |
720 | op = _cairo_hash_table_lookup (dict, &key.base); |
552 | if (op != NULL) { |
721 | if (op != NULL) { |
553 | *size = op->operand_length; |
722 | *size = op->operand_length; |
554 | return op->operand; |
723 | return op->operand; |
555 | } |
724 | } |
556 | 725 | ||
557 | return NULL; |
726 | return NULL; |
558 | } |
727 | } |
559 | 728 | ||
560 | static cairo_status_t |
729 | static cairo_status_t |
561 | cff_dict_set_operands (cairo_hash_table_t *dict, |
730 | cff_dict_set_operands (cairo_hash_table_t *dict, |
562 | unsigned short operator, |
731 | unsigned short operator, |
563 | unsigned char *operand, |
732 | unsigned char *operand, |
564 | int size) |
733 | int size) |
565 | { |
734 | { |
566 | cff_dict_operator_t key, *op; |
735 | cff_dict_operator_t key, *op; |
567 | cairo_status_t status; |
736 | cairo_status_t status; |
568 | 737 | ||
569 | _cairo_dict_init_key (&key, operator); |
738 | _cairo_dict_init_key (&key, operator); |
570 | op = _cairo_hash_table_lookup (dict, &key.base); |
739 | op = _cairo_hash_table_lookup (dict, &key.base); |
571 | if (op != NULL) { |
740 | if (op != NULL) { |
572 | free (op->operand); |
741 | free (op->operand); |
573 | op->operand = malloc (size); |
742 | op->operand = malloc (size); |
574 | if (unlikely (op->operand == NULL)) |
743 | if (unlikely (op->operand == NULL)) |
575 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
744 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
576 | 745 | ||
577 | memcpy (op->operand, operand, size); |
746 | memcpy (op->operand, operand, size); |
578 | op->operand_length = size; |
747 | op->operand_length = size; |
579 | } |
748 | } |
580 | else |
749 | else |
581 | { |
750 | { |
582 | status = cff_dict_create_operator (operator, operand, size, &op); |
751 | status = cff_dict_create_operator (operator, operand, size, &op); |
583 | if (unlikely (status)) |
752 | if (unlikely (status)) |
584 | return status; |
753 | return status; |
585 | 754 | ||
586 | status = _cairo_hash_table_insert (dict, &op->base); |
755 | status = _cairo_hash_table_insert (dict, &op->base); |
587 | if (unlikely (status)) |
756 | if (unlikely (status)) |
588 | return status; |
757 | return status; |
589 | } |
758 | } |
590 | 759 | ||
591 | return CAIRO_STATUS_SUCCESS; |
760 | return CAIRO_STATUS_SUCCESS; |
592 | } |
761 | } |
593 | 762 | ||
594 | static int |
763 | static int |
595 | cff_dict_get_location (cairo_hash_table_t *dict, |
764 | cff_dict_get_location (cairo_hash_table_t *dict, |
596 | unsigned short operator, |
765 | unsigned short operator, |
597 | int *size) |
766 | int *size) |
598 | { |
767 | { |
599 | cff_dict_operator_t key, *op; |
768 | cff_dict_operator_t key, *op; |
600 | 769 | ||
601 | _cairo_dict_init_key (&key, operator); |
770 | _cairo_dict_init_key (&key, operator); |
602 | op = _cairo_hash_table_lookup (dict, &key.base); |
771 | op = _cairo_hash_table_lookup (dict, &key.base); |
603 | if (op != NULL) { |
772 | if (op != NULL) { |
604 | *size = op->operand_length; |
773 | *size = op->operand_length; |
605 | return op->operand_offset; |
774 | return op->operand_offset; |
606 | } |
775 | } |
607 | 776 | ||
608 | return -1; |
777 | return -1; |
609 | } |
778 | } |
610 | 779 | ||
611 | typedef struct _dict_write_info { |
780 | typedef struct _dict_write_info { |
612 | cairo_array_t *output; |
781 | cairo_array_t *output; |
613 | cairo_status_t status; |
782 | cairo_status_t status; |
614 | } dict_write_info_t; |
783 | } dict_write_info_t; |
615 | 784 | ||
616 | static void |
785 | static void |
617 | cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info) |
786 | cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info) |
618 | { |
787 | { |
619 | unsigned char data; |
788 | unsigned char data; |
620 | 789 | ||
621 | op->operand_offset = _cairo_array_num_elements (write_info->output); |
790 | op->operand_offset = _cairo_array_num_elements (write_info->output); |
622 | write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length); |
791 | write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length); |
623 | if (write_info->status) |
792 | if (write_info->status) |
624 | return; |
793 | return; |
625 | 794 | ||
626 | if (op->operator & 0xff00) { |
795 | if (op->operator & 0xff00) { |
627 | data = op->operator >> 8; |
796 | data = op->operator >> 8; |
628 | write_info->status = _cairo_array_append (write_info->output, &data); |
797 | write_info->status = _cairo_array_append (write_info->output, &data); |
629 | if (write_info->status) |
798 | if (write_info->status) |
630 | return; |
799 | return; |
631 | } |
800 | } |
632 | data = op->operator & 0xff; |
801 | data = op->operator & 0xff; |
633 | write_info->status = _cairo_array_append (write_info->output, &data); |
802 | write_info->status = _cairo_array_append (write_info->output, &data); |
634 | } |
803 | } |
635 | 804 | ||
636 | static void |
805 | static void |
637 | _cairo_dict_collect (void *entry, void *closure) |
806 | _cairo_dict_collect (void *entry, void *closure) |
638 | { |
807 | { |
639 | dict_write_info_t *write_info = closure; |
808 | dict_write_info_t *write_info = closure; |
640 | cff_dict_operator_t *op = entry; |
809 | cff_dict_operator_t *op = entry; |
641 | 810 | ||
642 | if (write_info->status) |
811 | if (write_info->status) |
643 | return; |
812 | return; |
644 | 813 | ||
645 | /* The ROS operator is handled separately in cff_dict_write() */ |
814 | /* The ROS operator is handled separately in cff_dict_write() */ |
646 | if (op->operator != ROS_OP) |
815 | if (op->operator != ROS_OP) |
647 | cairo_dict_write_operator (op, write_info); |
816 | cairo_dict_write_operator (op, write_info); |
648 | } |
817 | } |
649 | 818 | ||
650 | static cairo_status_t |
819 | static cairo_status_t |
651 | cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output) |
820 | cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output) |
652 | { |
821 | { |
653 | dict_write_info_t write_info; |
822 | dict_write_info_t write_info; |
654 | cff_dict_operator_t key, *op; |
823 | cff_dict_operator_t key, *op; |
655 | 824 | ||
656 | write_info.output = output; |
825 | write_info.output = output; |
657 | write_info.status = CAIRO_STATUS_SUCCESS; |
826 | write_info.status = CAIRO_STATUS_SUCCESS; |
658 | 827 | ||
659 | /* The CFF specification requires that the Top Dict of CID fonts |
828 | /* The CFF specification requires that the Top Dict of CID fonts |
660 | * begin with the ROS operator. */ |
829 | * begin with the ROS operator. */ |
661 | _cairo_dict_init_key (&key, ROS_OP); |
830 | _cairo_dict_init_key (&key, ROS_OP); |
662 | op = _cairo_hash_table_lookup (dict, &key.base); |
831 | op = _cairo_hash_table_lookup (dict, &key.base); |
663 | if (op != NULL) |
832 | if (op != NULL) |
664 | cairo_dict_write_operator (op, &write_info); |
833 | cairo_dict_write_operator (op, &write_info); |
665 | 834 | ||
666 | _cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info); |
835 | _cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info); |
667 | 836 | ||
668 | return write_info.status; |
837 | return write_info.status; |
669 | } |
838 | } |
670 | 839 | ||
671 | static void |
840 | static void |
672 | _cff_dict_entry_pluck (void *_entry, void *dict) |
841 | _cff_dict_entry_pluck (void *_entry, void *dict) |
673 | { |
842 | { |
674 | cff_dict_operator_t *entry = _entry; |
843 | cff_dict_operator_t *entry = _entry; |
675 | 844 | ||
676 | _cairo_hash_table_remove (dict, &entry->base); |
845 | _cairo_hash_table_remove (dict, &entry->base); |
677 | free (entry->operand); |
846 | free (entry->operand); |
678 | free (entry); |
847 | free (entry); |
679 | } |
848 | } |
680 | 849 | ||
681 | static void |
850 | static void |
682 | cff_dict_fini (cairo_hash_table_t *dict) |
851 | cff_dict_fini (cairo_hash_table_t *dict) |
683 | { |
852 | { |
684 | _cairo_hash_table_foreach (dict, _cff_dict_entry_pluck, dict); |
853 | _cairo_hash_table_foreach (dict, _cff_dict_entry_pluck, dict); |
685 | _cairo_hash_table_destroy (dict); |
854 | _cairo_hash_table_destroy (dict); |
686 | } |
855 | } |
687 | 856 | ||
688 | static cairo_int_status_t |
857 | static cairo_int_status_t |
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; |
- | 862 | ||
693 | 863 | ||
694 | font->header = (cff_header_t *) font->data; |
864 | font->header = (cff_header_t *) font->data; |
695 | font->current_ptr = font->data + font->header->header_size; |
865 | font->current_ptr = font->data + font->header->header_size; |
696 | 866 | ||
697 | return CAIRO_STATUS_SUCCESS; |
867 | return CAIRO_STATUS_SUCCESS; |
698 | } |
868 | } |
699 | 869 | ||
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; |
|
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 | } |
710 | cff_index_fini (&index); |
903 | cff_index_fini (&index); |
711 | 904 | ||
712 | return status; |
905 | return status; |
713 | } |
906 | } |
714 | 907 | ||
715 | static cairo_int_status_t |
908 | static cairo_int_status_t |
716 | cairo_cff_font_read_private_dict (cairo_cff_font_t *font, |
909 | cairo_cff_font_read_private_dict (cairo_cff_font_t *font, |
717 | cairo_hash_table_t *private_dict, |
910 | cairo_hash_table_t *private_dict, |
718 | cairo_array_t *local_sub_index, |
911 | cairo_array_t *local_sub_index, |
- | 912 | int *local_sub_bias, |
|
- | 913 | cairo_bool_t **local_subs_used, |
|
- | 914 | double *default_width, |
|
- | 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; |
726 | int i; |
923 | int i; |
727 | unsigned char *operand; |
924 | unsigned char *operand; |
728 | unsigned char *p; |
925 | unsigned char *p; |
- | 926 | int num_subs; |
|
729 | 927 | ||
730 | status = cff_dict_read (private_dict, ptr, size); |
928 | status = cff_dict_read (private_dict, ptr, size); |
731 | if (unlikely (status)) |
929 | if (unlikely (status)) |
732 | return status; |
930 | return status; |
733 | 931 | ||
734 | operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i); |
932 | operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i); |
735 | if (operand) { |
933 | if (operand) { |
736 | decode_integer (operand, &offset); |
934 | decode_integer (operand, &offset); |
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; |
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; |
747 | } |
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 |
|
- | 967 | *local_sub_bias = 32768; |
|
748 | 968 | ||
749 | return CAIRO_STATUS_SUCCESS; |
969 | return CAIRO_STATUS_SUCCESS; |
750 | } |
970 | } |
751 | 971 | ||
752 | static cairo_int_status_t |
972 | static cairo_int_status_t |
753 | cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p) |
973 | cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p) |
754 | { |
974 | { |
755 | int type, num_ranges, first, last, fd, i, j; |
975 | int type, num_ranges, first, last, fd, i, j; |
756 | 976 | ||
757 | font->fdselect = calloc (font->num_glyphs, sizeof (int)); |
977 | font->fdselect = calloc (font->num_glyphs, sizeof (int)); |
758 | if (unlikely (font->fdselect == NULL)) |
978 | if (unlikely (font->fdselect == NULL)) |
759 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
979 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
760 | 980 | ||
761 | type = *p++; |
981 | type = *p++; |
762 | if (type == 0) |
982 | if (type == 0) |
763 | { |
983 | { |
764 | for (i = 0; i < font->num_glyphs; i++) |
984 | for (i = 0; i < font->num_glyphs; i++) |
765 | font->fdselect[i] = *p++; |
985 | font->fdselect[i] = *p++; |
766 | } else if (type == 3) { |
986 | } else if (type == 3) { |
767 | num_ranges = be16_to_cpu( *((uint16_t *)p) ); |
987 | num_ranges = be16_to_cpu( *((uint16_t *)p) ); |
768 | p += 2; |
988 | p += 2; |
769 | for (i = 0; i < num_ranges; i++) |
989 | for (i = 0; i < num_ranges; i++) |
770 | { |
990 | { |
771 | first = be16_to_cpu( *((uint16_t *)p) ); |
991 | first = be16_to_cpu( *((uint16_t *)p) ); |
772 | p += 2; |
992 | p += 2; |
773 | fd = *p++; |
993 | fd = *p++; |
774 | last = be16_to_cpu( *((uint16_t *)p) ); |
994 | last = be16_to_cpu( *((uint16_t *)p) ); |
775 | for (j = first; j < last; j++) |
995 | for (j = first; j < last; j++) |
776 | font->fdselect[j] = fd; |
996 | font->fdselect[j] = fd; |
777 | } |
997 | } |
778 | } else { |
998 | } else { |
779 | return CAIRO_INT_STATUS_UNSUPPORTED; |
999 | return CAIRO_INT_STATUS_UNSUPPORTED; |
780 | } |
1000 | } |
781 | 1001 | ||
782 | return CAIRO_STATUS_SUCCESS; |
1002 | return CAIRO_STATUS_SUCCESS; |
783 | } |
1003 | } |
784 | 1004 | ||
785 | static cairo_int_status_t |
1005 | static cairo_int_status_t |
786 | cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr) |
1006 | cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr) |
787 | { |
1007 | { |
788 | cairo_array_t index; |
1008 | cairo_array_t index; |
789 | cff_index_element_t *element; |
1009 | cff_index_element_t *element; |
790 | unsigned int i; |
1010 | unsigned int i; |
791 | int size; |
1011 | int size; |
792 | unsigned char *operand; |
1012 | unsigned char *operand; |
793 | int offset; |
1013 | int offset; |
794 | cairo_int_status_t status; |
1014 | cairo_int_status_t status; |
795 | unsigned char buf[100]; |
1015 | unsigned char buf[100]; |
796 | unsigned char *end_buf; |
1016 | unsigned char *end_buf; |
797 | 1017 | ||
798 | cff_index_init (&index); |
1018 | cff_index_init (&index); |
799 | status = cff_index_read (&index, &ptr, font->data_end); |
1019 | status = cff_index_read (&index, &ptr, font->data_end); |
800 | if (unlikely (status)) |
1020 | if (unlikely (status)) |
801 | goto fail; |
1021 | goto fail; |
802 | 1022 | ||
803 | font->num_fontdicts = _cairo_array_num_elements (&index); |
1023 | font->num_fontdicts = _cairo_array_num_elements (&index); |
804 | 1024 | ||
805 | font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts); |
1025 | font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts); |
806 | if (unlikely (font->fd_dict == NULL)) { |
1026 | if (unlikely (font->fd_dict == NULL)) { |
807 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1027 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
808 | goto fail; |
1028 | goto fail; |
809 | } |
1029 | } |
810 | 1030 | ||
811 | font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts); |
1031 | font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts); |
812 | if (unlikely (font->fd_private_dict == NULL)) { |
1032 | if (unlikely (font->fd_private_dict == NULL)) { |
813 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1033 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
814 | goto fail; |
1034 | goto fail; |
815 | } |
1035 | } |
816 | 1036 | ||
817 | font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts); |
1037 | font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts); |
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 | } |
- | 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)) |
826 | goto fail; |
1070 | goto fail; |
827 | 1071 | ||
828 | element = _cairo_array_index (&index, i); |
1072 | element = _cairo_array_index (&index, i); |
829 | status = cff_dict_read (font->fd_dict[i], element->data, element->length); |
1073 | status = cff_dict_read (font->fd_dict[i], element->data, element->length); |
830 | if (unlikely (status)) |
1074 | if (unlikely (status)) |
831 | goto fail; |
1075 | goto fail; |
832 | 1076 | ||
833 | operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size); |
1077 | operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size); |
834 | if (operand == NULL) { |
1078 | if (operand == NULL) { |
835 | status = CAIRO_INT_STATUS_UNSUPPORTED; |
1079 | status = CAIRO_INT_STATUS_UNSUPPORTED; |
836 | goto fail; |
1080 | goto fail; |
837 | } |
1081 | } |
838 | operand = decode_integer (operand, &size); |
1082 | operand = decode_integer (operand, &size); |
839 | decode_integer (operand, &offset); |
1083 | decode_integer (operand, &offset); |
840 | status = cff_dict_init (&font->fd_private_dict[i]); |
1084 | status = cff_dict_init (&font->fd_private_dict[i]); |
841 | if (unlikely (status)) |
1085 | if (unlikely (status)) |
842 | goto fail; |
1086 | goto fail; |
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], |
847 | &font->fd_local_sub_index[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], |
|
- | 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)) |
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); |
857 | status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf); |
1105 | status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf); |
858 | if (unlikely (status)) |
1106 | if (unlikely (status)) |
859 | goto fail; |
1107 | goto fail; |
860 | } |
1108 | } |
861 | 1109 | ||
862 | return CAIRO_STATUS_SUCCESS; |
1110 | return CAIRO_STATUS_SUCCESS; |
863 | 1111 | ||
864 | fail: |
1112 | fail: |
865 | cff_index_fini (&index); |
1113 | cff_index_fini (&index); |
866 | 1114 | ||
867 | return status; |
1115 | return status; |
868 | } |
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); |
|
- | 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 | { |
873 | cairo_array_t index; |
1173 | cairo_array_t index; |
874 | cff_index_element_t *element; |
1174 | cff_index_element_t *element; |
875 | unsigned char buf[20]; |
1175 | unsigned char buf[20]; |
876 | unsigned char *end_buf; |
1176 | unsigned char *end_buf; |
877 | unsigned char *operand; |
1177 | unsigned char *operand; |
878 | cairo_int_status_t status; |
1178 | cairo_int_status_t status; |
879 | unsigned char *p; |
1179 | unsigned char *p; |
880 | int size; |
1180 | int size; |
881 | int offset; |
1181 | int offset; |
882 | 1182 | ||
883 | cff_index_init (&index); |
1183 | cff_index_init (&index); |
884 | status = cff_index_read (&index, &font->current_ptr, font->data_end); |
1184 | status = cff_index_read (&index, &font->current_ptr, font->data_end); |
885 | if (unlikely (status)) |
1185 | if (unlikely (status)) |
886 | goto fail; |
1186 | goto fail; |
887 | 1187 | ||
888 | element = _cairo_array_index (&index, 0); |
1188 | element = _cairo_array_index (&index, 0); |
889 | status = cff_dict_read (font->top_dict, element->data, element->length); |
1189 | status = cff_dict_read (font->top_dict, element->data, element->length); |
890 | if (unlikely (status)) |
1190 | if (unlikely (status)) |
891 | goto fail; |
1191 | goto fail; |
892 | 1192 | ||
893 | if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL) |
1193 | if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL) |
894 | font->is_cid = TRUE; |
1194 | font->is_cid = TRUE; |
895 | else |
1195 | else |
896 | font->is_cid = FALSE; |
1196 | font->is_cid = FALSE; |
897 | 1197 | ||
898 | operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size); |
1198 | operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size); |
899 | decode_integer (operand, &offset); |
1199 | decode_integer (operand, &offset); |
900 | p = font->data + offset; |
1200 | p = font->data + offset; |
901 | status = cff_index_read (&font->charstrings_index, &p, font->data_end); |
1201 | status = cff_index_read (&font->charstrings_index, &p, font->data_end); |
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); |
905 | 1205 | ||
906 | if (font->is_cid) { |
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 | ||
- | 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)) |
911 | goto fail; |
1225 | goto fail; |
912 | 1226 | ||
913 | operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size); |
1227 | operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size); |
914 | decode_integer (operand, &offset); |
1228 | decode_integer (operand, &offset); |
915 | status = cairo_cff_font_read_cid_fontdict (font, font->data + offset); |
1229 | status = cairo_cff_font_read_cid_fontdict (font, font->data + offset); |
916 | if (unlikely (status)) |
1230 | if (unlikely (status)) |
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 | } |
930 | 1248 | ||
931 | /* Use maximum sized encoding to reserve space for later modification. */ |
1249 | /* Use maximum sized encoding to reserve space for later modification. */ |
932 | end_buf = encode_integer_max (buf, 0); |
1250 | end_buf = encode_integer_max (buf, 0); |
933 | status = cff_dict_set_operands (font->top_dict, |
1251 | status = cff_dict_set_operands (font->top_dict, |
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; |
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)) |
941 | goto fail; |
1259 | 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); |
945 | if (unlikely (status)) |
1264 | 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); |
949 | CHARSET_OP, buf, end_buf - buf); |
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, |
|
- | 1280 | FDARRAY_OP, buf, end_buf - buf); |
|
950 | if (unlikely (status)) |
1281 | if (unlikely (status)) |
951 | goto fail; |
1282 | 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 | } |
955 | 1287 | ||
956 | /* Remove the unique identifier operators as the subsetted font is |
1288 | /* Remove the unique identifier operators as the subsetted font is |
957 | * not the same is the original font. */ |
1289 | * not the same is the original font. */ |
958 | cff_dict_remove (font->top_dict, UNIQUEID_OP); |
1290 | cff_dict_remove (font->top_dict, UNIQUEID_OP); |
959 | cff_dict_remove (font->top_dict, XUID_OP); |
1291 | cff_dict_remove (font->top_dict, XUID_OP); |
960 | 1292 | ||
961 | fail: |
1293 | fail: |
962 | cff_index_fini (&index); |
1294 | cff_index_fini (&index); |
963 | 1295 | ||
964 | return status; |
1296 | return status; |
965 | } |
1297 | } |
966 | 1298 | ||
967 | static cairo_int_status_t |
1299 | static cairo_int_status_t |
968 | cairo_cff_font_read_strings (cairo_cff_font_t *font) |
1300 | cairo_cff_font_read_strings (cairo_cff_font_t *font) |
969 | { |
1301 | { |
970 | return cff_index_read (&font->strings_index, &font->current_ptr, font->data_end); |
1302 | return cff_index_read (&font->strings_index, &font->current_ptr, font->data_end); |
971 | } |
1303 | } |
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) |
975 | { |
1307 | { |
- | 1308 | cairo_int_status_t status; |
|
- | 1309 | int num_subs; |
|
- | 1310 | ||
976 | return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end); |
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 | ||
- | 1327 | return CAIRO_STATUS_SUCCESS; |
|
977 | } |
1328 | } |
978 | 1329 | ||
979 | typedef cairo_int_status_t |
1330 | typedef cairo_int_status_t |
980 | (*font_read_t) (cairo_cff_font_t *font); |
1331 | (*font_read_t) (cairo_cff_font_t *font); |
981 | 1332 | ||
982 | static const font_read_t font_read_funcs[] = { |
1333 | static const font_read_t font_read_funcs[] = { |
983 | cairo_cff_font_read_header, |
1334 | cairo_cff_font_read_header, |
984 | cairo_cff_font_read_name, |
1335 | cairo_cff_font_read_name, |
985 | cairo_cff_font_read_top_dict, |
1336 | cairo_cff_font_read_top_dict, |
986 | cairo_cff_font_read_strings, |
1337 | cairo_cff_font_read_strings, |
987 | cairo_cff_font_read_global_subroutines, |
1338 | cairo_cff_font_read_global_subroutines, |
988 | }; |
1339 | }; |
989 | 1340 | ||
990 | static cairo_int_status_t |
1341 | static cairo_int_status_t |
991 | cairo_cff_font_read_font (cairo_cff_font_t *font) |
1342 | cairo_cff_font_read_font (cairo_cff_font_t *font) |
992 | { |
1343 | { |
993 | cairo_int_status_t status; |
1344 | cairo_int_status_t status; |
994 | unsigned int i; |
1345 | unsigned int i; |
995 | 1346 | ||
996 | for (i = 0; i < ARRAY_LENGTH (font_read_funcs); i++) { |
1347 | for (i = 0; i < ARRAY_LENGTH (font_read_funcs); i++) { |
997 | status = font_read_funcs[i] (font); |
1348 | status = font_read_funcs[i] (font); |
998 | if (unlikely (status)) |
1349 | if (unlikely (status)) |
999 | return status; |
1350 | return status; |
1000 | } |
1351 | } |
1001 | 1352 | ||
1002 | return CAIRO_STATUS_SUCCESS; |
1353 | return CAIRO_STATUS_SUCCESS; |
1003 | } |
1354 | } |
1004 | 1355 | ||
1005 | static cairo_status_t |
1356 | static cairo_status_t |
1006 | cairo_cff_font_set_ros_strings (cairo_cff_font_t *font) |
1357 | cairo_cff_font_set_ros_strings (cairo_cff_font_t *font) |
1007 | { |
1358 | { |
1008 | cairo_status_t status; |
1359 | cairo_status_t status; |
1009 | unsigned char buf[30]; |
1360 | unsigned char buf[30]; |
1010 | unsigned char *p; |
1361 | unsigned char *p; |
1011 | int sid1, sid2; |
1362 | int sid1, sid2; |
1012 | const char *registry = "Adobe"; |
1363 | const char *registry = "Adobe"; |
1013 | const char *ordering = "Identity"; |
1364 | const char *ordering = "Identity"; |
1014 | 1365 | ||
1015 | sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); |
1366 | sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); |
1016 | status = cff_index_append_copy (&font->strings_subset_index, |
1367 | status = cff_index_append_copy (&font->strings_subset_index, |
1017 | (unsigned char *)registry, |
1368 | (unsigned char *)registry, |
1018 | strlen(registry)); |
1369 | strlen(registry)); |
1019 | if (unlikely (status)) |
1370 | if (unlikely (status)) |
1020 | return status; |
1371 | return status; |
1021 | 1372 | ||
1022 | sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); |
1373 | sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); |
1023 | status = cff_index_append_copy (&font->strings_subset_index, |
1374 | status = cff_index_append_copy (&font->strings_subset_index, |
1024 | (unsigned char *)ordering, |
1375 | (unsigned char *)ordering, |
1025 | strlen(ordering)); |
1376 | strlen(ordering)); |
1026 | if (unlikely (status)) |
1377 | if (unlikely (status)) |
1027 | return status; |
1378 | return status; |
1028 | 1379 | ||
1029 | p = encode_integer (buf, sid1); |
1380 | p = encode_integer (buf, sid1); |
1030 | p = encode_integer (p, sid2); |
1381 | p = encode_integer (p, sid2); |
1031 | p = encode_integer (p, 0); |
1382 | p = encode_integer (p, 0); |
1032 | status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf); |
1383 | status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf); |
1033 | if (unlikely (status)) |
1384 | if (unlikely (status)) |
1034 | return status; |
1385 | return status; |
1035 | 1386 | ||
1036 | p = encode_integer (buf, font->scaled_font_subset->num_glyphs); |
1387 | p = encode_integer (buf, font->scaled_font_subset->num_glyphs); |
1037 | status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf); |
1388 | status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf); |
1038 | if (unlikely (status)) |
1389 | if (unlikely (status)) |
1039 | return status; |
1390 | return status; |
1040 | 1391 | ||
1041 | return CAIRO_STATUS_SUCCESS; |
1392 | return CAIRO_STATUS_SUCCESS; |
1042 | } |
1393 | } |
1043 | 1394 | ||
1044 | static cairo_status_t |
1395 | static cairo_status_t |
1045 | cairo_cff_font_subset_dict_string(cairo_cff_font_t *font, |
1396 | cairo_cff_font_subset_dict_string(cairo_cff_font_t *font, |
1046 | cairo_hash_table_t *dict, |
1397 | cairo_hash_table_t *dict, |
1047 | int operator) |
1398 | int operator) |
1048 | { |
1399 | { |
1049 | int size; |
1400 | int size; |
1050 | unsigned char *p; |
1401 | unsigned char *p; |
1051 | int sid; |
1402 | int sid; |
1052 | unsigned char buf[100]; |
1403 | unsigned char buf[100]; |
1053 | cff_index_element_t *element; |
1404 | cff_index_element_t *element; |
1054 | cairo_status_t status; |
1405 | cairo_status_t status; |
1055 | 1406 | ||
1056 | p = cff_dict_get_operands (dict, operator, &size); |
1407 | p = cff_dict_get_operands (dict, operator, &size); |
1057 | if (!p) |
1408 | if (!p) |
1058 | return CAIRO_STATUS_SUCCESS; |
1409 | return CAIRO_STATUS_SUCCESS; |
1059 | 1410 | ||
1060 | decode_integer (p, &sid); |
1411 | decode_integer (p, &sid); |
1061 | if (sid < NUM_STD_STRINGS) |
1412 | if (sid < NUM_STD_STRINGS) |
1062 | return CAIRO_STATUS_SUCCESS; |
1413 | return CAIRO_STATUS_SUCCESS; |
1063 | 1414 | ||
1064 | element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS); |
1415 | element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS); |
1065 | sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); |
1416 | sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); |
1066 | status = cff_index_append (&font->strings_subset_index, element->data, element->length); |
1417 | status = cff_index_append (&font->strings_subset_index, element->data, element->length); |
1067 | if (unlikely (status)) |
1418 | if (unlikely (status)) |
1068 | return status; |
1419 | return status; |
1069 | 1420 | ||
1070 | p = encode_integer (buf, sid); |
1421 | p = encode_integer (buf, sid); |
1071 | status = cff_dict_set_operands (dict, operator, buf, p - buf); |
1422 | status = cff_dict_set_operands (dict, operator, buf, p - buf); |
1072 | if (unlikely (status)) |
1423 | if (unlikely (status)) |
1073 | return status; |
1424 | return status; |
1074 | 1425 | ||
1075 | return CAIRO_STATUS_SUCCESS; |
1426 | return CAIRO_STATUS_SUCCESS; |
1076 | } |
1427 | } |
1077 | 1428 | ||
1078 | static const int dict_strings[] = { |
1429 | static const int dict_strings[] = { |
1079 | VERSION_OP, |
1430 | VERSION_OP, |
1080 | NOTICE_OP, |
1431 | NOTICE_OP, |
1081 | COPYRIGHT_OP, |
1432 | COPYRIGHT_OP, |
1082 | FULLNAME_OP, |
1433 | FULLNAME_OP, |
1083 | FAMILYNAME_OP, |
1434 | FAMILYNAME_OP, |
1084 | WEIGHT_OP, |
1435 | WEIGHT_OP, |
1085 | POSTSCRIPT_OP, |
1436 | POSTSCRIPT_OP, |
1086 | BASEFONTNAME_OP, |
1437 | BASEFONTNAME_OP, |
1087 | FONTNAME_OP, |
1438 | FONTNAME_OP, |
1088 | }; |
1439 | }; |
1089 | 1440 | ||
1090 | static cairo_status_t |
1441 | static cairo_status_t |
1091 | cairo_cff_font_subset_dict_strings (cairo_cff_font_t *font, |
1442 | cairo_cff_font_subset_dict_strings (cairo_cff_font_t *font, |
1092 | cairo_hash_table_t *dict) |
1443 | cairo_hash_table_t *dict) |
1093 | { |
1444 | { |
1094 | cairo_status_t status; |
1445 | cairo_status_t status; |
1095 | unsigned int i; |
1446 | unsigned int i; |
1096 | 1447 | ||
1097 | for (i = 0; i < ARRAY_LENGTH (dict_strings); i++) { |
1448 | for (i = 0; i < ARRAY_LENGTH (dict_strings); i++) { |
1098 | status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]); |
1449 | status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]); |
1099 | if (unlikely (status)) |
1450 | if (unlikely (status)) |
1100 | return status; |
1451 | return status; |
1101 | } |
1452 | } |
1102 | 1453 | ||
1103 | return CAIRO_STATUS_SUCCESS; |
1454 | return CAIRO_STATUS_SUCCESS; |
1104 | } |
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; |
|
- | 1659 | } |
|
1105 | 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 | } |
|
- | 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; |
1110 | unsigned int i; |
1777 | unsigned int i; |
1111 | cairo_status_t status; |
1778 | cairo_int_status_t status; |
- | 1779 | unsigned long glyph, cid; |
|
- | 1780 | ||
1112 | 1781 | font->subset_subroutines = TRUE; |
|
- | 1782 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
|
- | 1783 | if (font->is_cid) { |
|
1113 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
1784 | cid = font->scaled_font_subset->glyphs[i]; |
- | 1785 | status = cairo_cff_font_get_gid_for_cid (font, cid, &glyph); |
|
- | 1786 | if (unlikely (status)) |
|
- | 1787 | return status; |
|
1114 | element = _cairo_array_index (&font->charstrings_index, |
1788 | } else { |
- | 1789 | glyph = font->scaled_font_subset->glyphs[i]; |
|
- | 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, |
1118 | element->length); |
1794 | element->length); |
1119 | if (unlikely (status)) |
1795 | if (unlikely (status)) |
1120 | return 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)) { |
|
- | 1811 | return status; |
|
- | 1812 | } |
|
- | 1813 | } |
|
1121 | } |
1814 | } |
1122 | 1815 | ||
1123 | return CAIRO_STATUS_SUCCESS; |
1816 | return CAIRO_STATUS_SUCCESS; |
1124 | } |
1817 | } |
1125 | 1818 | ||
1126 | static cairo_status_t |
1819 | static cairo_status_t |
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; |
|
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)) |
1136 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1831 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1137 | 1832 | ||
1138 | font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int)); |
1833 | font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int)); |
1139 | if (unlikely (font->fd_subset_map == NULL)) |
1834 | if (unlikely (font->fd_subset_map == NULL)) |
1140 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1835 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1141 | 1836 | ||
1142 | font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int)); |
1837 | font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int)); |
1143 | if (unlikely (font->private_dict_offset == NULL)) |
1838 | if (unlikely (font->private_dict_offset == NULL)) |
1144 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1839 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1145 | 1840 | ||
1146 | reverse_map = calloc (font->num_fontdicts, sizeof (int)); |
1841 | reverse_map = calloc (font->num_fontdicts, sizeof (int)); |
1147 | if (unlikely (reverse_map == NULL)) |
1842 | if (unlikely (reverse_map == NULL)) |
1148 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1843 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1149 | 1844 | ||
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; |
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++) { |
1155 | fd = font->fdselect[font->scaled_font_subset->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 | ||
- | 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 | } |
1160 | font->fdselect_subset[i] = reverse_map[fd]; |
1860 | font->fdselect_subset[i] = reverse_map[fd]; |
1161 | } |
1861 | } |
1162 | 1862 | ||
1163 | free (reverse_map); |
1863 | free (reverse_map); |
1164 | 1864 | ||
1165 | return CAIRO_STATUS_SUCCESS; |
1865 | return CAIRO_STATUS_SUCCESS; |
1166 | } |
1866 | } |
1167 | 1867 | ||
1168 | static cairo_status_t |
1868 | static cairo_status_t |
1169 | cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font) |
1869 | cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font) |
1170 | { |
1870 | { |
1171 | unsigned char buf[100]; |
1871 | unsigned char buf[100]; |
1172 | unsigned char *end_buf; |
1872 | unsigned char *end_buf; |
1173 | cairo_status_t status; |
1873 | cairo_status_t status; |
1174 | 1874 | ||
1175 | font->num_fontdicts = 1; |
1875 | font->num_fontdicts = 1; |
1176 | font->fd_dict = malloc (sizeof (cairo_hash_table_t *)); |
1876 | font->fd_dict = malloc (sizeof (cairo_hash_table_t *)); |
1177 | if (unlikely (font->fd_dict == NULL)) |
1877 | if (unlikely (font->fd_dict == NULL)) |
1178 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1878 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1179 | 1879 | ||
1180 | if (cff_dict_init (&font->fd_dict[0])) { |
1880 | if (cff_dict_init (&font->fd_dict[0])) { |
1181 | free (font->fd_dict); |
1881 | free (font->fd_dict); |
1182 | font->fd_dict = NULL; |
1882 | font->fd_dict = NULL; |
1183 | font->num_fontdicts = 0; |
1883 | font->num_fontdicts = 0; |
1184 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1884 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1185 | } |
1885 | } |
1186 | 1886 | ||
1187 | font->fd_subset_map = malloc (sizeof (int)); |
1887 | font->fd_subset_map = malloc (sizeof (int)); |
1188 | if (unlikely (font->fd_subset_map == NULL)) |
1888 | if (unlikely (font->fd_subset_map == NULL)) |
1189 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1889 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1190 | 1890 | ||
1191 | font->private_dict_offset = malloc (sizeof (int)); |
1891 | font->private_dict_offset = malloc (sizeof (int)); |
1192 | if (unlikely (font->private_dict_offset == NULL)) |
1892 | if (unlikely (font->private_dict_offset == NULL)) |
1193 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1893 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1194 | 1894 | ||
1195 | font->fd_subset_map[0] = 0; |
1895 | font->fd_subset_map[0] = 0; |
1196 | font->num_subset_fontdicts = 1; |
1896 | font->num_subset_fontdicts = 1; |
1197 | 1897 | ||
1198 | /* Set integer operand to max value to use max size encoding to reserve |
1898 | /* Set integer operand to max value to use max size encoding to reserve |
1199 | * space for any value later */ |
1899 | * space for any value later */ |
1200 | end_buf = encode_integer_max (buf, 0); |
1900 | end_buf = encode_integer_max (buf, 0); |
1201 | end_buf = encode_integer_max (end_buf, 0); |
1901 | end_buf = encode_integer_max (end_buf, 0); |
1202 | status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf); |
1902 | status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf); |
1203 | if (unlikely (status)) |
1903 | if (unlikely (status)) |
1204 | return status; |
1904 | return status; |
1205 | 1905 | ||
1206 | return CAIRO_STATUS_SUCCESS; |
1906 | return CAIRO_STATUS_SUCCESS; |
1207 | } |
1907 | } |
1208 | 1908 | ||
1209 | static cairo_status_t |
1909 | static cairo_status_t |
1210 | cairo_cff_font_subset_strings (cairo_cff_font_t *font) |
1910 | cairo_cff_font_subset_strings (cairo_cff_font_t *font) |
1211 | { |
1911 | { |
1212 | cairo_status_t status; |
1912 | cairo_status_t status; |
1213 | unsigned int i; |
1913 | unsigned int i; |
1214 | 1914 | ||
1215 | status = cairo_cff_font_subset_dict_strings (font, font->top_dict); |
1915 | status = cairo_cff_font_subset_dict_strings (font, font->top_dict); |
1216 | if (unlikely (status)) |
1916 | if (unlikely (status)) |
1217 | return status; |
1917 | return status; |
1218 | 1918 | ||
1219 | if (font->is_cid) { |
1919 | if (font->is_cid) { |
1220 | for (i = 0; i < font->num_subset_fontdicts; i++) { |
1920 | for (i = 0; i < font->num_subset_fontdicts; i++) { |
1221 | status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]); |
1921 | status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]); |
1222 | if (unlikely (status)) |
1922 | if (unlikely (status)) |
1223 | return status; |
1923 | return status; |
1224 | 1924 | ||
1225 | status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]); |
1925 | status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]); |
1226 | if (unlikely (status)) |
1926 | if (unlikely (status)) |
1227 | return status; |
1927 | return status; |
1228 | } |
1928 | } |
1229 | } else { |
1929 | } else { |
1230 | status = cairo_cff_font_subset_dict_strings (font, font->private_dict); |
1930 | status = cairo_cff_font_subset_dict_strings (font, font->private_dict); |
1231 | } |
1931 | } |
1232 | 1932 | ||
1233 | return status; |
1933 | return status; |
1234 | } |
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; |
|
- | 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) |
1238 | { |
1965 | { |
1239 | cairo_status_t status; |
1966 | cairo_status_t status; |
- | 1967 | ||
1240 | 1968 | if (!font->scaled_font_subset->is_latin) { |
|
1241 | status = cairo_cff_font_set_ros_strings (font); |
1969 | status = cairo_cff_font_set_ros_strings (font); |
1242 | if (unlikely (status)) |
1970 | if (unlikely (status)) |
- | 1971 | return status; |
|
1243 | return status; |
1972 | } |
1244 | 1973 | ||
1245 | status = cairo_cff_font_subset_charstrings (font); |
1974 | status = cairo_cff_font_subset_charstrings_and_subroutines (font); |
1246 | if (unlikely (status)) |
1975 | if (unlikely (status)) |
1247 | return status; |
1976 | return status; |
- | 1977 | ||
1248 | 1978 | if (!font->scaled_font_subset->is_latin) { |
|
1249 | if (font->is_cid) |
1979 | if (font->is_cid) |
1250 | status = cairo_cff_font_subset_fontdict (font); |
1980 | status = cairo_cff_font_subset_fontdict (font); |
1251 | else |
1981 | else |
1252 | status = cairo_cff_font_create_cid_fontdict (font); |
1982 | status = cairo_cff_font_create_cid_fontdict (font); |
1253 | if (unlikely (status)) |
1983 | if (unlikely (status)) |
- | 1984 | return status; |
|
- | 1985 | } else { |
|
- | 1986 | font->private_dict_offset = malloc (sizeof (int)); |
|
- | 1987 | if (unlikely (font->private_dict_offset == NULL)) |
|
- | 1988 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
1254 | return status; |
1989 | } |
1255 | 1990 | ||
1256 | status = cairo_cff_font_subset_strings (font); |
1991 | status = cairo_cff_font_subset_strings (font); |
1257 | if (unlikely (status)) |
1992 | if (unlikely (status)) |
1258 | return status; |
1993 | return status; |
- | 1994 | ||
- | 1995 | if (font->scaled_font_subset->is_latin) |
|
- | 1996 | status = cairo_cff_font_add_euro_charset_string (font); |
|
1259 | 1997 | ||
1260 | return status; |
1998 | return status; |
1261 | } |
1999 | } |
1262 | 2000 | ||
1263 | /* Set the operand of the specified operator in the (already written) |
2001 | /* Set the operand of the specified operator in the (already written) |
1264 | * top dict to point to the current position in the output |
2002 | * top dict to point to the current position in the output |
1265 | * array. Operands updated with this function must have previously |
2003 | * array. Operands updated with this function must have previously |
1266 | * been encoded with the 5-byte (max) integer encoding. */ |
2004 | * been encoded with the 5-byte (max) integer encoding. */ |
1267 | static void |
2005 | static void |
1268 | cairo_cff_font_set_topdict_operator_to_cur_pos (cairo_cff_font_t *font, |
2006 | cairo_cff_font_set_topdict_operator_to_cur_pos (cairo_cff_font_t *font, |
1269 | int operator) |
2007 | int operator) |
1270 | { |
2008 | { |
1271 | int cur_pos; |
2009 | int cur_pos; |
1272 | int offset; |
2010 | int offset; |
1273 | int size; |
2011 | int size; |
1274 | unsigned char buf[10]; |
2012 | unsigned char buf[10]; |
1275 | unsigned char *buf_end; |
2013 | unsigned char *buf_end; |
1276 | unsigned char *op_ptr; |
2014 | unsigned char *op_ptr; |
1277 | 2015 | ||
1278 | cur_pos = _cairo_array_num_elements (&font->output); |
2016 | cur_pos = _cairo_array_num_elements (&font->output); |
1279 | buf_end = encode_integer_max (buf, cur_pos); |
2017 | buf_end = encode_integer_max (buf, cur_pos); |
1280 | offset = cff_dict_get_location (font->top_dict, operator, &size); |
2018 | offset = cff_dict_get_location (font->top_dict, operator, &size); |
1281 | assert (offset > 0); |
2019 | assert (offset > 0); |
1282 | op_ptr = _cairo_array_index (&font->output, offset); |
2020 | op_ptr = _cairo_array_index (&font->output, offset); |
1283 | memcpy (op_ptr, buf, buf_end - buf); |
2021 | memcpy (op_ptr, buf, buf_end - buf); |
1284 | } |
2022 | } |
1285 | 2023 | ||
1286 | static cairo_status_t |
2024 | static cairo_status_t |
1287 | cairo_cff_font_write_header (cairo_cff_font_t *font) |
2025 | cairo_cff_font_write_header (cairo_cff_font_t *font) |
1288 | { |
2026 | { |
1289 | return _cairo_array_append_multiple (&font->output, |
2027 | return _cairo_array_append_multiple (&font->output, |
1290 | font->header, |
2028 | font->header, |
1291 | font->header->header_size); |
2029 | font->header->header_size); |
1292 | } |
2030 | } |
1293 | 2031 | ||
1294 | static cairo_status_t |
2032 | static cairo_status_t |
1295 | cairo_cff_font_write_name (cairo_cff_font_t *font) |
2033 | cairo_cff_font_write_name (cairo_cff_font_t *font) |
1296 | { |
2034 | { |
1297 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
2035 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
1298 | cairo_array_t index; |
2036 | cairo_array_t index; |
1299 | 2037 | ||
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)); |
1305 | if (unlikely (status)) |
2043 | if (unlikely (status)) |
1306 | goto FAIL; |
2044 | goto FAIL; |
1307 | 2045 | ||
1308 | status = cff_index_write (&index, &font->output); |
2046 | status = cff_index_write (&index, &font->output); |
1309 | if (unlikely (status)) |
2047 | if (unlikely (status)) |
1310 | goto FAIL; |
2048 | goto FAIL; |
1311 | 2049 | ||
1312 | FAIL: |
2050 | FAIL: |
1313 | cff_index_fini (&index); |
2051 | cff_index_fini (&index); |
1314 | 2052 | ||
1315 | return status; |
2053 | return status; |
1316 | } |
2054 | } |
1317 | 2055 | ||
1318 | static cairo_status_t |
2056 | static cairo_status_t |
1319 | cairo_cff_font_write_top_dict (cairo_cff_font_t *font) |
2057 | cairo_cff_font_write_top_dict (cairo_cff_font_t *font) |
1320 | { |
2058 | { |
1321 | uint16_t count; |
2059 | uint16_t count; |
1322 | unsigned char buf[10]; |
2060 | unsigned char buf[10]; |
1323 | unsigned char *p; |
2061 | unsigned char *p; |
1324 | int offset_index; |
2062 | int offset_index; |
1325 | int dict_start, dict_size; |
2063 | int dict_start, dict_size; |
1326 | int offset_size = 4; |
2064 | int offset_size = 4; |
1327 | cairo_status_t status; |
2065 | cairo_status_t status; |
1328 | 2066 | ||
1329 | /* Write an index containing the top dict */ |
2067 | /* Write an index containing the top dict */ |
1330 | 2068 | ||
1331 | count = cpu_to_be16 (1); |
2069 | count = cpu_to_be16 (1); |
1332 | status = _cairo_array_append_multiple (&font->output, &count, 2); |
2070 | status = _cairo_array_append_multiple (&font->output, &count, 2); |
1333 | if (unlikely (status)) |
2071 | if (unlikely (status)) |
1334 | return status; |
2072 | return status; |
1335 | buf[0] = offset_size; |
2073 | buf[0] = offset_size; |
1336 | status = _cairo_array_append (&font->output, buf); |
2074 | status = _cairo_array_append (&font->output, buf); |
1337 | if (unlikely (status)) |
2075 | if (unlikely (status)) |
1338 | return status; |
2076 | return status; |
1339 | encode_index_offset (buf, offset_size, 1); |
2077 | encode_index_offset (buf, offset_size, 1); |
1340 | status = _cairo_array_append_multiple (&font->output, buf, offset_size); |
2078 | status = _cairo_array_append_multiple (&font->output, buf, offset_size); |
1341 | if (unlikely (status)) |
2079 | if (unlikely (status)) |
1342 | return status; |
2080 | return status; |
1343 | 2081 | ||
1344 | /* Reserve space for last element of offset array and update after |
2082 | /* Reserve space for last element of offset array and update after |
1345 | * dict is written */ |
2083 | * dict is written */ |
1346 | offset_index = _cairo_array_num_elements (&font->output); |
2084 | offset_index = _cairo_array_num_elements (&font->output); |
1347 | status = _cairo_array_append_multiple (&font->output, buf, offset_size); |
2085 | status = _cairo_array_append_multiple (&font->output, buf, offset_size); |
1348 | if (unlikely (status)) |
2086 | if (unlikely (status)) |
1349 | return status; |
2087 | return status; |
1350 | 2088 | ||
1351 | dict_start = _cairo_array_num_elements (&font->output); |
2089 | dict_start = _cairo_array_num_elements (&font->output); |
1352 | status = cff_dict_write (font->top_dict, &font->output); |
2090 | status = cff_dict_write (font->top_dict, &font->output); |
1353 | if (unlikely (status)) |
2091 | if (unlikely (status)) |
1354 | return status; |
2092 | return status; |
1355 | dict_size = _cairo_array_num_elements (&font->output) - dict_start; |
2093 | dict_size = _cairo_array_num_elements (&font->output) - dict_start; |
1356 | 2094 | ||
1357 | encode_index_offset (buf, offset_size, dict_size + 1); |
2095 | encode_index_offset (buf, offset_size, dict_size + 1); |
1358 | p = _cairo_array_index (&font->output, offset_index); |
2096 | p = _cairo_array_index (&font->output, offset_index); |
1359 | memcpy (p, buf, offset_size); |
2097 | memcpy (p, buf, offset_size); |
1360 | 2098 | ||
1361 | return CAIRO_STATUS_SUCCESS; |
2099 | return CAIRO_STATUS_SUCCESS; |
1362 | } |
2100 | } |
1363 | 2101 | ||
1364 | static cairo_status_t |
2102 | static cairo_status_t |
1365 | cairo_cff_font_write_strings (cairo_cff_font_t *font) |
2103 | cairo_cff_font_write_strings (cairo_cff_font_t *font) |
1366 | { |
2104 | { |
1367 | return cff_index_write (&font->strings_subset_index, &font->output); |
2105 | return cff_index_write (&font->strings_subset_index, &font->output); |
1368 | } |
2106 | } |
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) |
1372 | { |
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 | } |
|
- | 2122 | ||
1373 | return cff_index_write (&font->global_sub_index, &font->output); |
2123 | return cff_index_write (&font->global_sub_index, &font->output); |
1374 | } |
2124 | } |
1375 | 2125 | ||
1376 | static cairo_status_t |
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 | } |
|
- | 2149 | ||
- | 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; |
1380 | unsigned int i; |
2154 | unsigned int i; |
1381 | cairo_int_status_t status; |
2155 | cairo_int_status_t status; |
1382 | 2156 | ||
1383 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP); |
2157 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP); |
1384 | 2158 | ||
1385 | if (font->is_cid) { |
2159 | if (font->is_cid) { |
1386 | data = 0; |
2160 | data = 0; |
1387 | status = _cairo_array_append (&font->output, &data); |
2161 | status = _cairo_array_append (&font->output, &data); |
1388 | if (unlikely (status)) |
2162 | if (unlikely (status)) |
1389 | return status; |
2163 | return status; |
1390 | 2164 | ||
1391 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
2165 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
1392 | data = font->fdselect_subset[i]; |
2166 | data = font->fdselect_subset[i]; |
1393 | status = _cairo_array_append (&font->output, &data); |
2167 | status = _cairo_array_append (&font->output, &data); |
1394 | if (unlikely (status)) |
2168 | if (unlikely (status)) |
1395 | return status; |
2169 | return status; |
1396 | } |
2170 | } |
1397 | } else { |
2171 | } else { |
1398 | unsigned char byte; |
2172 | unsigned char byte; |
1399 | uint16_t word; |
2173 | uint16_t word; |
1400 | 2174 | ||
1401 | status = _cairo_array_grow_by (&font->output, 9); |
2175 | status = _cairo_array_grow_by (&font->output, 9); |
1402 | if (unlikely (status)) |
2176 | if (unlikely (status)) |
1403 | return status; |
2177 | return status; |
1404 | 2178 | ||
1405 | byte = 3; |
2179 | byte = 3; |
1406 | status = _cairo_array_append (&font->output, &byte); |
2180 | status = _cairo_array_append (&font->output, &byte); |
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); |
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 | ||
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); |
1416 | 2190 | ||
1417 | byte = 0; |
2191 | byte = 0; |
1418 | status = _cairo_array_append (&font->output, &byte); |
2192 | status = _cairo_array_append (&font->output, &byte); |
1419 | assert (status == CAIRO_STATUS_SUCCESS); |
2193 | assert (status == CAIRO_INT_STATUS_SUCCESS); |
1420 | 2194 | ||
1421 | word = cpu_to_be16 (font->scaled_font_subset->num_glyphs); |
2195 | word = cpu_to_be16 (font->scaled_font_subset->num_glyphs); |
1422 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
2196 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
1423 | assert (status == CAIRO_STATUS_SUCCESS); |
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; |
|
- | 2278 | ||
- | 2279 | sid_be16 = cpu_to_be16(sid); |
|
- | 2280 | status = _cairo_array_append_multiple (&font->output, &sid_be16, sizeof(sid_be16)); |
|
- | 2281 | if (unlikely (status)) |
|
- | 2282 | return status; |
|
1424 | } |
2283 | } |
1425 | 2284 | ||
1426 | return CAIRO_STATUS_SUCCESS; |
2285 | return CAIRO_STATUS_SUCCESS; |
1427 | } |
2286 | } |
1428 | 2287 | ||
1429 | static cairo_status_t |
2288 | static cairo_status_t |
1430 | cairo_cff_font_write_charset (cairo_cff_font_t *font) |
2289 | cairo_cff_font_write_cid_charset (cairo_cff_font_t *font) |
1431 | { |
2290 | { |
1432 | unsigned char byte; |
2291 | unsigned char byte; |
1433 | uint16_t word; |
2292 | uint16_t word; |
1434 | cairo_status_t status; |
2293 | cairo_status_t status; |
1435 | 2294 | ||
1436 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP); |
2295 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP); |
1437 | status = _cairo_array_grow_by (&font->output, 5); |
2296 | status = _cairo_array_grow_by (&font->output, 5); |
1438 | if (unlikely (status)) |
2297 | if (unlikely (status)) |
1439 | return status; |
2298 | return status; |
1440 | 2299 | ||
1441 | byte = 2; |
2300 | byte = 2; |
1442 | status = _cairo_array_append (&font->output, &byte); |
2301 | status = _cairo_array_append (&font->output, &byte); |
1443 | assert (status == CAIRO_STATUS_SUCCESS); |
2302 | assert (status == CAIRO_STATUS_SUCCESS); |
1444 | 2303 | ||
1445 | word = cpu_to_be16 (1); |
2304 | word = cpu_to_be16 (1); |
1446 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
2305 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
1447 | assert (status == CAIRO_STATUS_SUCCESS); |
2306 | assert (status == CAIRO_STATUS_SUCCESS); |
1448 | 2307 | ||
1449 | word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2); |
2308 | word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2); |
1450 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
2309 | status = _cairo_array_append_multiple (&font->output, &word, 2); |
1451 | assert (status == CAIRO_STATUS_SUCCESS); |
2310 | assert (status == CAIRO_STATUS_SUCCESS); |
1452 | 2311 | ||
1453 | return CAIRO_STATUS_SUCCESS; |
2312 | return CAIRO_STATUS_SUCCESS; |
1454 | } |
2313 | } |
1455 | 2314 | ||
1456 | static cairo_status_t |
2315 | static cairo_status_t |
1457 | cairo_cff_font_write_charstrings (cairo_cff_font_t *font) |
2316 | cairo_cff_font_write_charstrings (cairo_cff_font_t *font) |
1458 | { |
2317 | { |
1459 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP); |
2318 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP); |
1460 | 2319 | ||
1461 | return cff_index_write (&font->charstrings_subset_index, &font->output); |
2320 | return cff_index_write (&font->charstrings_subset_index, &font->output); |
1462 | } |
2321 | } |
1463 | 2322 | ||
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; |
1473 | 2333 | ||
1474 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP); |
2334 | cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP); |
1475 | count = cpu_to_be16 (font->num_subset_fontdicts); |
2335 | count = cpu_to_be16 (font->num_subset_fontdicts); |
1476 | status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t)); |
2336 | status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t)); |
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 | } |
1496 | 2362 | ||
1497 | return CAIRO_STATUS_SUCCESS; |
2363 | return CAIRO_STATUS_SUCCESS; |
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; |
1508 | unsigned char buf[10]; |
2374 | unsigned char buf[10]; |
1509 | unsigned char *buf_end; |
2375 | unsigned char *buf_end; |
1510 | unsigned char *p; |
2376 | unsigned char *p; |
1511 | cairo_status_t status; |
2377 | cairo_status_t status; |
1512 | 2378 | ||
1513 | /* Write private dict and update offset and size in top dict */ |
2379 | /* Write private dict and update offset and size in top dict */ |
1514 | font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output); |
2380 | font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output); |
1515 | status = cff_dict_write (private_dict, &font->output); |
2381 | status = cff_dict_write (private_dict, &font->output); |
1516 | if (unlikely (status)) |
2382 | if (unlikely (status)) |
1517 | return status; |
2383 | return status; |
1518 | 2384 | ||
1519 | size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num]; |
2385 | size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num]; |
1520 | /* private entry has two operands - size and offset */ |
2386 | /* private entry has two operands - size and offset */ |
1521 | buf_end = encode_integer_max (buf, size); |
2387 | buf_end = encode_integer_max (buf, size); |
1522 | buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]); |
2388 | buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]); |
1523 | offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size); |
2389 | offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size); |
1524 | assert (offset > 0); |
2390 | assert (offset > 0); |
1525 | p = _cairo_array_index (&font->output, offset); |
2391 | p = _cairo_array_index (&font->output, offset); |
1526 | memcpy (p, buf, buf_end - buf); |
2392 | memcpy (p, buf, buf_end - buf); |
1527 | 2393 | ||
1528 | return CAIRO_STATUS_SUCCESS; |
2394 | return CAIRO_STATUS_SUCCESS; |
1529 | } |
2395 | } |
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, |
1535 | cairo_array_t *local_sub_index) |
2401 | 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; |
1542 | cairo_status_t status; |
2409 | cairo_status_t status; |
- | 2410 | unsigned int i; |
|
- | 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 |
1546 | * dict. Local subroutines offset is relative to start of |
2415 | * dict. Local subroutines offset is relative to start of |
1547 | * private dict */ |
2416 | * private dict */ |
1548 | offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num]; |
2417 | offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num]; |
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 | } |
1558 | 2437 | ||
1559 | return CAIRO_STATUS_SUCCESS; |
2438 | return CAIRO_STATUS_SUCCESS; |
1560 | } |
2439 | } |
1561 | 2440 | ||
1562 | 2441 | ||
1563 | static cairo_status_t |
2442 | static cairo_status_t |
1564 | cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font) |
2443 | cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font) |
1565 | { |
2444 | { |
1566 | unsigned int i; |
2445 | unsigned int i; |
1567 | cairo_int_status_t status; |
2446 | cairo_int_status_t status; |
1568 | 2447 | ||
1569 | if (font->is_cid) { |
2448 | if (font->is_cid) { |
1570 | for (i = 0; i < font->num_subset_fontdicts; i++) { |
2449 | for (i = 0; i < font->num_subset_fontdicts; i++) { |
1571 | status = cairo_cff_font_write_private_dict ( |
2450 | status = cairo_cff_font_write_private_dict ( |
1572 | font, |
2451 | font, |
1573 | i, |
2452 | i, |
1574 | font->fd_dict[font->fd_subset_map[i]], |
2453 | font->fd_dict[font->fd_subset_map[i]], |
1575 | font->fd_private_dict[font->fd_subset_map[i]]); |
2454 | font->fd_private_dict[font->fd_subset_map[i]]); |
1576 | if (unlikely (status)) |
2455 | if (unlikely (status)) |
1577 | return status; |
2456 | return status; |
1578 | } |
2457 | } |
1579 | 2458 | ||
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, |
1591 | 0, |
2471 | 0, |
1592 | font->fd_dict[0], |
2472 | font->fd_dict[0], |
1593 | font->private_dict); |
2473 | font->private_dict); |
1594 | if (unlikely (status)) |
2474 | if (unlikely (status)) |
1595 | return status; |
2475 | return status; |
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, |
1600 | &font->local_sub_index); |
2480 | &font->local_sub_index, |
- | 2481 | font->local_subs_used); |
|
1601 | if (unlikely (status)) |
2482 | if (unlikely (status)) |
1602 | return status; |
2483 | return status; |
1603 | } |
2484 | } |
1604 | 2485 | ||
1605 | return CAIRO_STATUS_SUCCESS; |
2486 | return CAIRO_STATUS_SUCCESS; |
1606 | } |
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; |
|
- | 2510 | } |
|
- | 2511 | ||
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, |
1619 | cairo_cff_font_write_charstrings, |
2524 | cairo_cff_font_write_charstrings, |
1620 | cairo_cff_font_write_cid_fontdict, |
2525 | cairo_cff_font_write_cid_fontdict, |
1621 | cairo_cff_font_write_cid_private_dict_and_local_sub, |
2526 | cairo_cff_font_write_cid_private_dict_and_local_sub, |
1622 | }; |
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, |
|
- | 2536 | cairo_cff_font_write_type1_charset, |
|
- | 2537 | cairo_cff_font_write_charstrings, |
|
- | 2538 | cairo_cff_font_write_type1_private_dict_and_local_sub, |
|
- | 2539 | }; |
|
1623 | 2540 | ||
1624 | static cairo_status_t |
2541 | static cairo_status_t |
1625 | cairo_cff_font_write_subset (cairo_cff_font_t *font) |
2542 | cairo_cff_font_write_subset (cairo_cff_font_t *font) |
1626 | { |
2543 | { |
1627 | cairo_int_status_t status; |
2544 | cairo_int_status_t status; |
1628 | unsigned int i; |
2545 | unsigned int i; |
- | 2546 | ||
- | 2547 | if (font->scaled_font_subset->is_latin) { |
|
- | 2548 | for (i = 0; i < ARRAY_LENGTH (font_write_type1_funcs); i++) { |
|
- | 2549 | status = font_write_type1_funcs[i] (font); |
|
- | 2550 | if (unlikely (status)) |
|
- | 2551 | return status; |
|
- | 2552 | } |
|
1629 | 2553 | } else { |
|
1630 | for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) { |
2554 | for (i = 0; i < ARRAY_LENGTH (font_write_cid_funcs); i++) { |
1631 | status = font_write_funcs[i] (font); |
2555 | status = font_write_cid_funcs[i] (font); |
1632 | if (unlikely (status)) |
2556 | if (unlikely (status)) |
- | 2557 | return status; |
|
1633 | return status; |
2558 | } |
1634 | } |
2559 | } |
1635 | 2560 | ||
1636 | return CAIRO_STATUS_SUCCESS; |
2561 | return CAIRO_STATUS_SUCCESS; |
1637 | } |
2562 | } |
1638 | 2563 | ||
1639 | static cairo_int_status_t |
2564 | static cairo_int_status_t |
1640 | cairo_cff_font_generate (cairo_cff_font_t *font, |
2565 | cairo_cff_font_generate (cairo_cff_font_t *font, |
1641 | const char **data, |
2566 | const char **data, |
1642 | unsigned long *length) |
2567 | unsigned long *length) |
1643 | { |
2568 | { |
1644 | cairo_int_status_t status; |
2569 | cairo_int_status_t status; |
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)) |
1648 | return status; |
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); |
|
- | 2584 | } |
|
1649 | 2585 | ||
1650 | status = cairo_cff_font_subset_font (font); |
2586 | status = cairo_cff_font_subset_font (font); |
1651 | if (unlikely (status)) |
2587 | if (unlikely (status)) |
1652 | return status; |
2588 | return status; |
1653 | 2589 | ||
1654 | status = cairo_cff_font_write_subset (font); |
2590 | status = cairo_cff_font_write_subset (font); |
1655 | if (unlikely (status)) |
2591 | if (unlikely (status)) |
1656 | return status; |
2592 | return status; |
- | 2593 | ||
1657 | 2594 | ||
1658 | *data = _cairo_array_index (&font->output, 0); |
2595 | *data = _cairo_array_index (&font->output, 0); |
1659 | *length = _cairo_array_num_elements (&font->output); |
2596 | *length = _cairo_array_num_elements (&font->output); |
1660 | 2597 | ||
1661 | return CAIRO_STATUS_SUCCESS; |
2598 | return CAIRO_STATUS_SUCCESS; |
1662 | } |
2599 | } |
1663 | 2600 | ||
1664 | static cairo_int_status_t |
2601 | static cairo_int_status_t |
1665 | cairo_cff_font_create_set_widths (cairo_cff_font_t *font) |
2602 | cairo_cff_font_create_set_widths (cairo_cff_font_t *font) |
1666 | { |
2603 | { |
1667 | unsigned long size; |
2604 | unsigned long size; |
1668 | unsigned long long_entry_size; |
2605 | unsigned long long_entry_size; |
1669 | unsigned long short_entry_size; |
2606 | unsigned long short_entry_size; |
1670 | unsigned int i; |
2607 | unsigned int i; |
1671 | tt_hhea_t hhea; |
2608 | tt_hhea_t hhea; |
1672 | int num_hmetrics; |
2609 | int num_hmetrics; |
1673 | unsigned char buf[10]; |
2610 | unsigned char buf[10]; |
1674 | int glyph_index; |
2611 | int glyph_index; |
1675 | cairo_int_status_t status; |
2612 | cairo_int_status_t status; |
1676 | 2613 | ||
1677 | size = sizeof (tt_hhea_t); |
2614 | size = sizeof (tt_hhea_t); |
1678 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
2615 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1679 | TT_TAG_hhea, 0, |
2616 | TT_TAG_hhea, 0, |
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); |
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) { |
1690 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
2627 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1691 | TT_TAG_hmtx, |
2628 | TT_TAG_hmtx, |
1692 | glyph_index * long_entry_size, |
2629 | glyph_index * long_entry_size, |
1693 | buf, &short_entry_size); |
2630 | buf, &short_entry_size); |
1694 | if (unlikely (status)) |
2631 | if (unlikely (status)) |
1695 | return status; |
2632 | return status; |
1696 | } |
2633 | } |
1697 | else |
2634 | else |
1698 | { |
2635 | { |
1699 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
2636 | status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1700 | TT_TAG_hmtx, |
2637 | TT_TAG_hmtx, |
1701 | (num_hmetrics - 1) * long_entry_size, |
2638 | (num_hmetrics - 1) * long_entry_size, |
1702 | buf, &short_entry_size); |
2639 | buf, &short_entry_size); |
1703 | if (unlikely (status)) |
2640 | if (unlikely (status)) |
1704 | return status; |
2641 | return status; |
1705 | } |
2642 | } |
1706 | font->widths[i] = be16_to_cpu (*((int16_t*)buf)); |
2643 | font->widths[i] = be16_to_cpu (*((int16_t*)buf)); |
1707 | } |
2644 | } |
1708 | 2645 | ||
1709 | return CAIRO_STATUS_SUCCESS; |
2646 | return CAIRO_STATUS_SUCCESS; |
1710 | } |
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; |
|
- | 2666 | } |
|
1711 | 2667 | ||
1712 | static cairo_int_status_t |
2668 | static cairo_int_status_t |
1713 | _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset, |
- | |
1714 | cairo_cff_font_t **font_return, |
- | |
1715 | const char *subset_name) |
2669 | _cairo_cff_font_load_opentype_cff (cairo_cff_font_t *font) |
1716 | { |
2670 | { |
1717 | const cairo_scaled_font_backend_t *backend; |
2671 | const cairo_scaled_font_backend_t *backend = font->backend; |
1718 | cairo_status_t status; |
- | |
1719 | cairo_cff_font_t *font; |
2672 | cairo_status_t status; |
1720 | tt_head_t head; |
2673 | tt_head_t head; |
1721 | tt_hhea_t hhea; |
2674 | tt_hhea_t hhea; |
1722 | unsigned long size, data_length; |
2675 | unsigned long size, data_length; |
1723 | - | ||
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; |
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); |
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 | ||
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)) |
1746 | return status; |
2698 | return status; |
1747 | 2699 | ||
1748 | size = 0; |
2700 | size = 0; |
1749 | status = backend->load_truetype_table (scaled_font_subset->scaled_font, |
2701 | status = backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1750 | TT_TAG_hmtx, 0, NULL, &size); |
2702 | TT_TAG_hmtx, 0, NULL, &size); |
1751 | if (unlikely (status)) |
2703 | if (unlikely (status)) |
1752 | return status; |
2704 | 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)) |
- | |
1764 | goto fail2; |
- | |
1765 | - | ||
1766 | font->subset_font_name = strdup (subset_name); |
- | |
1767 | if (unlikely (font->subset_font_name == NULL)) { |
- | |
1768 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
1769 | goto fail2; |
- | |
1770 | } |
2705 | |
1771 | font->x_min = (int16_t) be16_to_cpu (head.x_min); |
2706 | font->x_min = (int16_t) be16_to_cpu (head.x_min); |
1772 | font->y_min = (int16_t) be16_to_cpu (head.y_min); |
2707 | font->y_min = (int16_t) be16_to_cpu (head.y_min); |
1773 | font->x_max = (int16_t) be16_to_cpu (head.x_max); |
2708 | font->x_max = (int16_t) be16_to_cpu (head.x_max); |
1774 | font->y_max = (int16_t) be16_to_cpu (head.y_max); |
2709 | font->y_max = (int16_t) be16_to_cpu (head.y_max); |
1775 | font->ascent = (int16_t) be16_to_cpu (hhea.ascender); |
2710 | font->ascent = (int16_t) be16_to_cpu (hhea.ascender); |
1776 | font->descent = (int16_t) be16_to_cpu (hhea.descender); |
2711 | font->descent = (int16_t) be16_to_cpu (hhea.descender); |
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; |
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)) |
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)) { |
2726 | if (unlikely (font->data == NULL)) |
1792 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
1793 | goto fail3; |
- | |
1794 | } |
2727 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1795 | 2728 | ||
- | 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, |
1797 | scaled_font_subset->font_id, |
2731 | &font->data_length); |
1798 | scaled_font_subset->subset_id); |
2732 | if (unlikely (status)) |
1799 | } |
2733 | return status; |
- | 2734 | ||
1800 | 2735 | if (!check_fontdata_is_cff (font->data, data_length)) |
|
- | 2736 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 2737 | ||
1801 | font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int)); |
2738 | return CAIRO_STATUS_SUCCESS; |
- | 2739 | } |
|
1802 | if (unlikely (font->widths == NULL)) { |
2740 | |
- | 2741 | static cairo_int_status_t |
|
- | 2742 | _cairo_cff_font_load_cff (cairo_cff_font_t *font) |
|
- | 2743 | { |
|
- | 2744 | const cairo_scaled_font_backend_t *backend = font->backend; |
|
- | 2745 | cairo_status_t status; |
|
- | 2746 | unsigned long data_length; |
|
- | 2747 | ||
1803 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2748 | if (!backend->load_type1_data) |
- | 2749 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
1804 | goto fail4; |
2750 | |
1805 | } |
2751 | data_length = 0; |
- | 2752 | status = backend->load_type1_data (font->scaled_font_subset->scaled_font, |
|
- | 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; |
2757 | font->font_name = NULL; |
1810 | - | ||
1811 | font->data_length = data_length; |
2758 | font->is_opentype = FALSE; |
1812 | font->data = malloc (data_length); |
2759 | font->data_length = data_length; |
1813 | if (unlikely (font->data == NULL)) { |
- | |
1814 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2760 | font->data = malloc (data_length); |
1815 | goto fail5; |
2761 | if (unlikely (font->data == NULL)) |
1816 | } |
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; |
|
- | 2796 | ||
1817 | status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font, |
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; |
|
- | 2819 | } |
|
1818 | TT_TAG_CFF, 0, font->data, |
2820 | |
1819 | &font->data_length); |
2821 | if (font->is_opentype) { |
1820 | if (unlikely (status)) |
2822 | status = cairo_cff_font_create_set_widths (font); |
1821 | goto fail6; |
2823 | if (unlikely (status)) |
1822 | 2824 | goto fail4; |
|
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 | ||
1829 | status = cff_dict_init (&font->private_dict); |
2831 | status = cff_dict_init (&font->private_dict); |
1830 | if (unlikely (status)) |
2832 | if (unlikely (status)) |
1831 | goto fail7; |
2833 | goto fail5; |
1832 | 2834 | ||
1833 | cff_index_init (&font->strings_index); |
2835 | cff_index_init (&font->strings_index); |
1834 | cff_index_init (&font->charstrings_index); |
2836 | cff_index_init (&font->charstrings_index); |
1835 | cff_index_init (&font->global_sub_index); |
2837 | cff_index_init (&font->global_sub_index); |
1836 | cff_index_init (&font->local_sub_index); |
2838 | cff_index_init (&font->local_sub_index); |
1837 | cff_index_init (&font->charstrings_subset_index); |
2839 | cff_index_init (&font->charstrings_subset_index); |
1838 | cff_index_init (&font->strings_subset_index); |
2840 | cff_index_init (&font->strings_subset_index); |
- | 2841 | font->euro_sid = 0; |
|
1839 | font->fdselect = NULL; |
2842 | font->fdselect = NULL; |
1840 | font->fd_dict = NULL; |
2843 | font->fd_dict = NULL; |
1841 | font->fd_private_dict = NULL; |
2844 | font->fd_private_dict = NULL; |
1842 | font->fd_local_sub_index = NULL; |
2845 | font->fd_local_sub_index = NULL; |
- | 2846 | font->fd_local_sub_bias = NULL; |
|
1843 | font->fdselect_subset = NULL; |
2847 | font->fdselect_subset = NULL; |
1844 | font->fd_subset_map = NULL; |
2848 | font->fd_subset_map = NULL; |
1845 | font->private_dict_offset = NULL; |
2849 | font->private_dict_offset = NULL; |
- | 2850 | font->global_subs_used = NULL; |
|
- | 2851 | font->local_subs_used = NULL; |
|
- | 2852 | font->fd_local_subs_used = NULL; |
|
1846 | 2853 | ||
1847 | *font_return = font; |
2854 | *font_return = font; |
1848 | 2855 | ||
1849 | return CAIRO_STATUS_SUCCESS; |
2856 | return CAIRO_STATUS_SUCCESS; |
1850 | - | ||
1851 | fail7: |
- | |
1852 | _cairo_hash_table_destroy (font->top_dict); |
- | |
1853 | fail6: |
- | |
1854 | free (font->data); |
2857 | |
1855 | fail5: |
2858 | fail5: |
1856 | free (font->widths); |
2859 | _cairo_hash_table_destroy (font->top_dict); |
1857 | fail4: |
- | |
1858 | if (font->font_name) |
2860 | fail4: |
1859 | free (font->font_name); |
2861 | free (font->widths); |
1860 | fail3: |
2862 | fail3: |
1861 | free (font->subset_font_name); |
2863 | free (font->subset_font_name); |
1862 | fail2: |
2864 | fail2: |
- | 2865 | free (font->ps_name); |
|
1863 | _cairo_array_fini (&font->output); |
2866 | _cairo_array_fini (&font->output); |
- | 2867 | fail1: |
|
- | 2868 | free (font->data); |
|
- | 2869 | free (font->font_name); |
|
1864 | free (font); |
2870 | free (font); |
1865 | 2871 | ||
1866 | return status; |
2872 | return status; |
1867 | } |
2873 | } |
1868 | 2874 | ||
1869 | static void |
2875 | static void |
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; |
1873 | 2879 | ||
1874 | free (font->widths); |
2880 | free (font->widths); |
1875 | if (font->font_name) |
- | |
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); |
1881 | cff_dict_fini (font->private_dict); |
2886 | cff_dict_fini (font->private_dict); |
1882 | cff_index_fini (&font->strings_index); |
2887 | cff_index_fini (&font->strings_index); |
1883 | cff_index_fini (&font->charstrings_index); |
2888 | cff_index_fini (&font->charstrings_index); |
1884 | cff_index_fini (&font->global_sub_index); |
2889 | cff_index_fini (&font->global_sub_index); |
1885 | cff_index_fini (&font->local_sub_index); |
2890 | cff_index_fini (&font->local_sub_index); |
1886 | cff_index_fini (&font->charstrings_subset_index); |
2891 | cff_index_fini (&font->charstrings_subset_index); |
1887 | cff_index_fini (&font->strings_subset_index); |
2892 | cff_index_fini (&font->strings_subset_index); |
1888 | 2893 | ||
1889 | /* If we bailed out early as a result of an error some of the |
2894 | /* If we bailed out early as a result of an error some of the |
1890 | * following cairo_cff_font_t members may still be NULL */ |
2895 | * following cairo_cff_font_t members may still be NULL */ |
1891 | if (font->fd_dict) { |
2896 | if (font->fd_dict) { |
1892 | for (i = 0; i < font->num_fontdicts; i++) { |
2897 | for (i = 0; i < font->num_fontdicts; i++) { |
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); |
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]); |
1912 | } |
2915 | } |
1913 | free (font->fd_private_dict); |
2916 | free (font->fd_private_dict); |
1914 | } |
2917 | } |
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 | } |
1921 | - | ||
1922 | if (font->data) |
2933 | |
1923 | free (font->data); |
2934 | free (font->data); |
1924 | 2935 | ||
1925 | free (font); |
2936 | free (font); |
1926 | } |
2937 | } |
1927 | 2938 | ||
1928 | cairo_status_t |
2939 | cairo_status_t |
1929 | _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset, |
2940 | _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset, |
1930 | const char *subset_name, |
2941 | const char *subset_name, |
1931 | cairo_scaled_font_subset_t *font_subset) |
2942 | cairo_scaled_font_subset_t *font_subset) |
1932 | { |
2943 | { |
1933 | cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */ |
2944 | cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */ |
1934 | cairo_status_t status; |
2945 | cairo_status_t status; |
1935 | const char *data = NULL; /* squelch bogus compiler warning */ |
2946 | const char *data = NULL; /* squelch bogus compiler warning */ |
1936 | unsigned long length = 0; /* squelch bogus compiler warning */ |
2947 | unsigned long length = 0; /* squelch bogus compiler warning */ |
1937 | unsigned int i; |
2948 | unsigned int i; |
1938 | 2949 | ||
1939 | status = _cairo_cff_font_create (font_subset, &font, subset_name); |
2950 | status = _cairo_cff_font_create (font_subset, &font, subset_name); |
1940 | if (unlikely (status)) |
2951 | if (unlikely (status)) |
1941 | return status; |
2952 | return status; |
1942 | 2953 | ||
1943 | status = cairo_cff_font_generate (font, &data, &length); |
2954 | status = cairo_cff_font_generate (font, &data, &length); |
1944 | if (unlikely (status)) |
2955 | if (unlikely (status)) |
1945 | goto fail1; |
2956 | goto fail1; |
1946 | 2957 | ||
1947 | cff_subset->ps_name = strdup (font->ps_name); |
2958 | cff_subset->ps_name = strdup (font->ps_name); |
1948 | if (unlikely (cff_subset->ps_name == NULL)) { |
2959 | if (unlikely (cff_subset->ps_name == NULL)) { |
1949 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2960 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1950 | goto fail1; |
2961 | goto fail1; |
1951 | } |
2962 | } |
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; |
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); |
1964 | if (unlikely (cff_subset->widths == NULL)) { |
2975 | if (unlikely (cff_subset->widths == NULL)) { |
1965 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2976 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1966 | goto fail3; |
2977 | goto fail3; |
1967 | } |
2978 | } |
1968 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) |
2979 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) |
1969 | cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em; |
2980 | cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em; |
1970 | 2981 | ||
1971 | cff_subset->x_min = (double)font->x_min/font->units_per_em; |
2982 | cff_subset->x_min = (double)font->x_min/font->units_per_em; |
1972 | cff_subset->y_min = (double)font->y_min/font->units_per_em; |
2983 | cff_subset->y_min = (double)font->y_min/font->units_per_em; |
1973 | cff_subset->x_max = (double)font->x_max/font->units_per_em; |
2984 | cff_subset->x_max = (double)font->x_max/font->units_per_em; |
1974 | cff_subset->y_max = (double)font->y_max/font->units_per_em; |
2985 | cff_subset->y_max = (double)font->y_max/font->units_per_em; |
1975 | cff_subset->ascent = (double)font->ascent/font->units_per_em; |
2986 | cff_subset->ascent = (double)font->ascent/font->units_per_em; |
1976 | cff_subset->descent = (double)font->descent/font->units_per_em; |
2987 | cff_subset->descent = (double)font->descent/font->units_per_em; |
1977 | 2988 | ||
1978 | cff_subset->data = malloc (length); |
2989 | cff_subset->data = malloc (length); |
1979 | if (unlikely (cff_subset->data == NULL)) { |
2990 | if (unlikely (cff_subset->data == NULL)) { |
1980 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2991 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1981 | goto fail4; |
2992 | goto fail4; |
1982 | } |
2993 | } |
1983 | 2994 | ||
1984 | memcpy (cff_subset->data, data, length); |
2995 | memcpy (cff_subset->data, data, length); |
1985 | cff_subset->data_length = length; |
2996 | cff_subset->data_length = length; |
1986 | 2997 | ||
1987 | cairo_cff_font_destroy (font); |
2998 | cairo_cff_font_destroy (font); |
1988 | 2999 | ||
1989 | return CAIRO_STATUS_SUCCESS; |
3000 | return CAIRO_STATUS_SUCCESS; |
1990 | 3001 | ||
1991 | fail4: |
3002 | fail4: |
1992 | free (cff_subset->widths); |
3003 | free (cff_subset->widths); |
1993 | fail3: |
3004 | fail3: |
1994 | if (cff_subset->font_name) |
- | |
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: |
1999 | cairo_cff_font_destroy (font); |
3009 | cairo_cff_font_destroy (font); |
2000 | 3010 | ||
2001 | return status; |
3011 | return status; |
2002 | } |
3012 | } |
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); |
3017 | free (subset->ps_name); |
2008 | if (subset->font_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); |
2012 | } |
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; |
|
- | 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, |
2017 | const char *subset_name) |
3133 | const char *subset_name) |
2018 | { |
3134 | { |
2019 | cairo_status_t status; |
3135 | cairo_status_t status; |
2020 | cairo_cff_font_t *font; |
3136 | cairo_cff_font_t *font; |
2021 | 3137 | ||
2022 | font = malloc (sizeof (cairo_cff_font_t)); |
3138 | font = malloc (sizeof (cairo_cff_font_t)); |
2023 | if (unlikely (font == NULL)) |
3139 | if (unlikely (font == NULL)) |
2024 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
3140 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2025 | 3141 | ||
2026 | font->backend = NULL; |
3142 | font->backend = NULL; |
2027 | font->scaled_font_subset = scaled_font_subset; |
3143 | font->scaled_font_subset = scaled_font_subset; |
2028 | 3144 | ||
2029 | _cairo_array_init (&font->output, sizeof (char)); |
3145 | _cairo_array_init (&font->output, sizeof (char)); |
2030 | status = _cairo_array_grow_by (&font->output, 4096); |
3146 | status = _cairo_array_grow_by (&font->output, 4096); |
2031 | if (unlikely (status)) |
3147 | if (unlikely (status)) |
2032 | goto fail1; |
3148 | goto fail1; |
2033 | 3149 | ||
2034 | font->subset_font_name = strdup (subset_name); |
3150 | font->subset_font_name = strdup (subset_name); |
2035 | if (unlikely (font->subset_font_name == NULL)) { |
3151 | if (unlikely (font->subset_font_name == NULL)) { |
2036 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
3152 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2037 | goto fail1; |
3153 | goto fail1; |
2038 | } |
3154 | } |
2039 | 3155 | ||
2040 | font->ps_name = strdup (subset_name); |
3156 | font->ps_name = strdup (subset_name); |
2041 | if (unlikely (font->ps_name == NULL)) { |
3157 | if (unlikely (font->ps_name == NULL)) { |
2042 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
3158 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2043 | goto fail2; |
3159 | goto fail2; |
2044 | } |
3160 | } |
2045 | font->font_name = NULL; |
3161 | font->font_name = NULL; |
2046 | 3162 | ||
2047 | font->x_min = 0; |
3163 | font->x_min = 0; |
2048 | font->y_min = 0; |
3164 | font->y_min = 0; |
2049 | font->x_max = 0; |
3165 | font->x_max = 0; |
2050 | font->y_max = 0; |
3166 | font->y_max = 0; |
2051 | font->ascent = 0; |
3167 | font->ascent = 0; |
2052 | font->descent = 0; |
3168 | font->descent = 0; |
2053 | 3169 | ||
2054 | font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int)); |
3170 | font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int)); |
2055 | if (unlikely (font->widths == NULL)) { |
3171 | if (unlikely (font->widths == NULL)) { |
2056 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
3172 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2057 | goto fail3; |
3173 | goto fail3; |
2058 | } |
3174 | } |
2059 | 3175 | ||
2060 | font->data_length = 0; |
3176 | font->data_length = 0; |
2061 | font->data = NULL; |
3177 | font->data = NULL; |
2062 | font->data_end = NULL; |
3178 | font->data_end = NULL; |
2063 | 3179 | ||
2064 | status = cff_dict_init (&font->top_dict); |
3180 | status = cff_dict_init (&font->top_dict); |
2065 | if (unlikely (status)) |
3181 | if (unlikely (status)) |
2066 | goto fail4; |
3182 | goto fail4; |
2067 | 3183 | ||
2068 | status = cff_dict_init (&font->private_dict); |
3184 | status = cff_dict_init (&font->private_dict); |
2069 | if (unlikely (status)) |
3185 | if (unlikely (status)) |
2070 | goto fail5; |
3186 | goto fail5; |
2071 | 3187 | ||
2072 | cff_index_init (&font->strings_index); |
3188 | cff_index_init (&font->strings_index); |
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; |
2083 | font->fd_subset_map = NULL; |
3202 | font->fd_subset_map = NULL; |
2084 | font->private_dict_offset = NULL; |
3203 | font->private_dict_offset = NULL; |
2085 | 3204 | ||
2086 | *font_return = font; |
3205 | *font_return = font; |
2087 | 3206 | ||
2088 | return CAIRO_STATUS_SUCCESS; |
3207 | return CAIRO_STATUS_SUCCESS; |
2089 | 3208 | ||
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); |
2102 | free (font); |
3220 | free (font); |
2103 | return status; |
3221 | return status; |
2104 | } |
3222 | } |
2105 | 3223 | ||
2106 | static cairo_int_status_t |
3224 | static cairo_int_status_t |
2107 | cairo_cff_font_fallback_generate (cairo_cff_font_t *font, |
3225 | cairo_cff_font_fallback_generate (cairo_cff_font_t *font, |
2108 | cairo_type2_charstrings_t *type2_subset, |
3226 | cairo_type2_charstrings_t *type2_subset, |
2109 | const char **data, |
3227 | const char **data, |
2110 | unsigned long *length) |
3228 | unsigned long *length) |
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; |
|
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; |
2124 | font->header = &header; |
3243 | font->header = &header; |
2125 | 3244 | ||
2126 | /* Create Top Dict */ |
3245 | /* Create Top Dict */ |
2127 | font->is_cid = FALSE; |
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)) |
|
- | 3267 | return status; |
|
- | 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); |
2131 | end_buf = encode_integer (end_buf, type2_subset->y_max); |
3272 | end_buf = encode_integer (end_buf, type2_subset->y_max); |
2132 | status = cff_dict_set_operands (font->top_dict, |
3273 | status = cff_dict_set_operands (font->top_dict, |
2133 | FONTBBOX_OP, buf, end_buf - buf); |
3274 | FONTBBOX_OP, buf, end_buf - buf); |
2134 | if (unlikely (status)) |
3275 | if (unlikely (status)) |
2135 | return status; |
3276 | return status; |
2136 | 3277 | ||
2137 | end_buf = encode_integer_max (buf, 0); |
3278 | end_buf = encode_integer_max (buf, 0); |
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; |
2142 | - | ||
2143 | status = cff_dict_set_operands (font->top_dict, |
- | |
2144 | FDSELECT_OP, buf, end_buf - buf); |
- | |
2145 | if (unlikely (status)) |
- | |
- | 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)) |
|
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, |
2154 | CHARSET_OP, buf, end_buf - buf); |
3310 | CHARSET_OP, buf, end_buf - buf); |
2155 | if (unlikely (status)) |
3311 | if (unlikely (status)) |
2156 | return status; |
3312 | return status; |
- | 3313 | ||
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; |
2161 | 3318 | ||
2162 | /* Create CID FD dictionary */ |
3319 | /* Create CID FD dictionary */ |
2163 | status = cairo_cff_font_create_cid_fontdict (font); |
3320 | status = cairo_cff_font_create_cid_fontdict (font); |
- | 3321 | if (unlikely (status)) |
|
- | 3322 | return status; |
|
- | 3323 | } else { |
|
- | 3324 | font->private_dict_offset = malloc (sizeof (int)); |
|
- | 3325 | if (unlikely (font->private_dict_offset == NULL)) |
|
2164 | if (unlikely (status)) |
3326 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2165 | return status; |
3327 | } |
2166 | 3328 | ||
2167 | /* Create charstrings */ |
3329 | /* Create charstrings */ |
2168 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
3330 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { |
2169 | charstring = _cairo_array_index(&type2_subset->charstrings, i); |
3331 | charstring = _cairo_array_index(&type2_subset->charstrings, i); |
2170 | 3332 | ||
2171 | status = cff_index_append (&font->charstrings_subset_index, |
3333 | status = cff_index_append (&font->charstrings_subset_index, |
2172 | _cairo_array_index (charstring, 0), |
3334 | _cairo_array_index (charstring, 0), |
2173 | _cairo_array_num_elements (charstring)); |
3335 | _cairo_array_num_elements (charstring)); |
2174 | 3336 | ||
2175 | if (unlikely (status)) |
3337 | if (unlikely (status)) |
2176 | return status; |
3338 | return status; |
2177 | } |
3339 | } |
- | 3340 | ||
- | 3341 | if (font->scaled_font_subset->is_latin) |
|
- | 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); |
2180 | if (unlikely (status)) |
3345 | if (unlikely (status)) |
2181 | return status; |
3346 | return status; |
2182 | 3347 | ||
2183 | *data = _cairo_array_index (&font->output, 0); |
3348 | *data = _cairo_array_index (&font->output, 0); |
2184 | *length = _cairo_array_num_elements (&font->output); |
3349 | *length = _cairo_array_num_elements (&font->output); |
2185 | 3350 | ||
2186 | return CAIRO_STATUS_SUCCESS; |
3351 | return CAIRO_STATUS_SUCCESS; |
2187 | } |
3352 | } |
2188 | 3353 | ||
2189 | cairo_status_t |
3354 | cairo_status_t |
2190 | _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset, |
3355 | _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset, |
2191 | const char *subset_name, |
3356 | const char *subset_name, |
2192 | cairo_scaled_font_subset_t *font_subset) |
3357 | cairo_scaled_font_subset_t *font_subset) |
2193 | { |
3358 | { |
2194 | cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */ |
3359 | cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */ |
2195 | cairo_status_t status; |
3360 | cairo_status_t status; |
2196 | const char *data = NULL; /* squelch bogus compiler warning */ |
3361 | const char *data = NULL; /* squelch bogus compiler warning */ |
2197 | unsigned long length = 0; /* squelch bogus compiler warning */ |
3362 | unsigned long length = 0; /* squelch bogus compiler warning */ |
2198 | unsigned int i; |
3363 | unsigned int i; |
2199 | cairo_type2_charstrings_t type2_subset; |
3364 | cairo_type2_charstrings_t type2_subset; |
2200 | 3365 | ||
2201 | status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name); |
3366 | status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name); |
2202 | if (unlikely (status)) |
3367 | if (unlikely (status)) |
2203 | return status; |
3368 | return status; |
2204 | 3369 | ||
2205 | status = _cairo_type2_charstrings_init (&type2_subset, font_subset); |
3370 | status = _cairo_type2_charstrings_init (&type2_subset, font_subset); |
2206 | if (unlikely (status)) |
3371 | if (unlikely (status)) |
2207 | goto fail1; |
3372 | goto fail1; |
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)) |
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); |
2217 | goto fail2; |
3382 | goto fail2; |
2218 | } |
3383 | } |
2219 | 3384 | ||
2220 | cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs); |
3385 | cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs); |
2221 | if (unlikely (cff_subset->widths == NULL)) { |
3386 | if (unlikely (cff_subset->widths == NULL)) { |
2222 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
3387 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2223 | goto fail3; |
3388 | goto fail3; |
2224 | } |
3389 | } |
2225 | 3390 | ||
2226 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) |
3391 | for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) |
2227 | cff_subset->widths[i] = (double)type2_subset.widths[i]/1000; |
3392 | cff_subset->widths[i] = (double)type2_subset.widths[i]/1000; |
2228 | 3393 | ||
2229 | cff_subset->x_min = (double)type2_subset.x_min/1000; |
3394 | cff_subset->x_min = (double)type2_subset.x_min/1000; |
2230 | cff_subset->y_min = (double)type2_subset.y_min/1000; |
3395 | cff_subset->y_min = (double)type2_subset.y_min/1000; |
2231 | cff_subset->x_max = (double)type2_subset.x_max/1000; |
3396 | cff_subset->x_max = (double)type2_subset.x_max/1000; |
2232 | cff_subset->y_max = (double)type2_subset.y_max/1000; |
3397 | cff_subset->y_max = (double)type2_subset.y_max/1000; |
2233 | cff_subset->ascent = (double)type2_subset.y_max/1000; |
3398 | cff_subset->ascent = (double)type2_subset.y_max/1000; |
2234 | cff_subset->descent = (double)type2_subset.y_min/1000; |
3399 | cff_subset->descent = (double)type2_subset.y_min/1000; |
2235 | 3400 | ||
2236 | cff_subset->data = malloc (length); |
3401 | cff_subset->data = malloc (length); |
2237 | if (unlikely (cff_subset->data == NULL)) { |
3402 | if (unlikely (cff_subset->data == NULL)) { |
2238 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
3403 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2239 | goto fail4; |
3404 | goto fail4; |
2240 | } |
3405 | } |
2241 | 3406 | ||
2242 | memcpy (cff_subset->data, data, length); |
3407 | memcpy (cff_subset->data, data, length); |
2243 | cff_subset->data_length = length; |
3408 | cff_subset->data_length = length; |
2244 | cff_subset->data_length = length; |
- | |
2245 | 3409 | ||
2246 | _cairo_type2_charstrings_fini (&type2_subset); |
3410 | _cairo_type2_charstrings_fini (&type2_subset); |
2247 | cairo_cff_font_destroy (font); |
3411 | cairo_cff_font_destroy (font); |
2248 | 3412 | ||
2249 | return CAIRO_STATUS_SUCCESS; |
3413 | return CAIRO_STATUS_SUCCESS; |
2250 | 3414 | ||
2251 | fail4: |
3415 | fail4: |
2252 | free (cff_subset->widths); |
3416 | free (cff_subset->widths); |
2253 | fail3: |
3417 | fail3: |
2254 | free (cff_subset->ps_name); |
3418 | free (cff_subset->ps_name); |
2255 | fail2: |
3419 | fail2: |
2256 | _cairo_type2_charstrings_fini (&type2_subset); |
3420 | _cairo_type2_charstrings_fini (&type2_subset); |
2257 | fail1: |
3421 | fail1: |
2258 | cairo_cff_font_destroy (font); |
3422 | cairo_cff_font_destroy (font); |
2259 | 3423 | ||
2260 | return status; |
3424 | return status; |
2261 | } |
3425 | } |
2262 | 3426 | ||
2263 | void |
3427 | void |
2264 | _cairo_cff_fallback_fini (cairo_cff_subset_t *subset) |
3428 | _cairo_cff_fallback_fini (cairo_cff_subset_t *subset) |
2265 | { |
3429 | { |
2266 | free (subset->ps_name); |
3430 | free (subset->ps_name); |
2267 | free (subset->widths); |
3431 | free (subset->widths); |
2268 | free (subset->data); |
3432 | free (subset->data); |
2269 | } |
3433 | } |
2270 | 3434 | ||
2271 | #endif /* CAIRO_HAS_FONT_SUBSET */>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>=>=>=><=>=>=>=>><>><>><>8><8>=>=>=>=> |
3435 | #endif /* CAIRO_HAS_FONT_SUBSET */>>>>>>>>>>>>>>>>>>=>=>>>>>>>>>>=>>=>=>>=>>=>>><>=>=>=>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>=>=>=><=>>>=>=>=>><>><>><>8><8>=>=>=>=> |