Line data Source code
1 : /* cairo - a vector graphics library with display and print output
2 : *
3 : * Copyright © 2006 Red Hat, Inc
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it either under the terms of the GNU Lesser General Public
7 : * License version 2.1 as published by the Free Software Foundation
8 : * (the "LGPL") or, at your option, under the terms of the Mozilla
9 : * Public License Version 1.1 (the "MPL"). If you do not alter this
10 : * notice, a recipient may use your version of this file under either
11 : * the MPL or the LGPL.
12 : *
13 : * You should have received a copy of the LGPL along with this library
14 : * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 : * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 : * You should have received a copy of the MPL along with this library
17 : * in the file COPYING-MPL-1.1
18 : *
19 : * The contents of this file are subject to the Mozilla Public License
20 : * Version 1.1 (the "License"); you may not use this file except in
21 : * compliance with the License. You may obtain a copy of the License at
22 : * http://www.mozilla.org/MPL/
23 : *
24 : * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 : * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 : * the specific language governing rights and limitations.
27 : *
28 : * The Original Code is the cairo graphics library.
29 : *
30 : * The Initial Developer of the Original Code is Red Hat, Inc.
31 : *
32 : * Contributor(s):
33 : * Kristian Høgsberg <krh@redhat.com>
34 : */
35 :
36 : /*
37 : * Useful links:
38 : * http://partners.adobe.com/public/developer/en/font/T1_SPEC.PDF
39 : */
40 :
41 :
42 : #define _BSD_SOURCE /* for snprintf(), strdup() */
43 : #include "cairoint.h"
44 : #include "cairo-error-private.h"
45 :
46 : #if CAIRO_HAS_FONT_SUBSET
47 :
48 : #include "cairo-type1-private.h"
49 : #include "cairo-scaled-font-subsets-private.h"
50 : #include "cairo-output-stream-private.h"
51 :
52 : /* XXX: Eventually, we need to handle other font backends */
53 : #if CAIRO_HAS_FT_FONT
54 :
55 : #include "cairo-ft-private.h"
56 :
57 : #include <ft2build.h>
58 : #include FT_FREETYPE_H
59 : #include FT_OUTLINE_H
60 : #include FT_TYPE1_TABLES_H
61 :
62 : #include <ctype.h>
63 :
64 : typedef struct _cairo_type1_font_subset {
65 : cairo_scaled_font_subset_t *scaled_font_subset;
66 :
67 : struct {
68 : cairo_unscaled_font_t *unscaled_font;
69 : unsigned int font_id;
70 : char *base_font;
71 : unsigned int num_glyphs;
72 : double x_min, y_min, x_max, y_max;
73 : double ascent, descent;
74 :
75 : const char *data;
76 : unsigned long header_size;
77 : unsigned long data_size;
78 : unsigned long trailer_size;
79 : } base;
80 :
81 : FT_Face face;
82 : int num_glyphs;
83 :
84 : struct {
85 : int subset_index;
86 : double width;
87 : char *name;
88 : } *glyphs;
89 :
90 : cairo_output_stream_t *output;
91 : cairo_array_t contents;
92 :
93 : const char *rd, *nd;
94 :
95 : char *type1_data;
96 : unsigned int type1_length;
97 : char *type1_end;
98 :
99 : char *header_segment;
100 : int header_segment_size;
101 : char *eexec_segment;
102 : int eexec_segment_size;
103 : cairo_bool_t eexec_segment_is_ascii;
104 :
105 : char *cleartext;
106 : char *cleartext_end;
107 :
108 : int header_size;
109 :
110 : unsigned short eexec_key;
111 : cairo_bool_t hex_encode;
112 : int hex_column;
113 : } cairo_type1_font_subset_t;
114 :
115 :
116 : static cairo_status_t
117 0 : _cairo_type1_font_subset_init (cairo_type1_font_subset_t *font,
118 : cairo_unscaled_font_t *unscaled_font,
119 : cairo_bool_t hex_encode)
120 : {
121 : cairo_ft_unscaled_font_t *ft_unscaled_font;
122 : cairo_status_t status;
123 : FT_Face face;
124 : PS_FontInfoRec font_info;
125 : int i, j;
126 :
127 0 : ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
128 :
129 0 : face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
130 0 : if (unlikely (face == NULL))
131 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
132 :
133 0 : if (FT_Get_PS_Font_Info(face, &font_info) != 0) {
134 0 : status = CAIRO_INT_STATUS_UNSUPPORTED;
135 0 : goto fail1;
136 : }
137 :
138 : /* OpenType/CFF fonts also have a PS_FontInfoRec */
139 : #if HAVE_FT_LOAD_SFNT_TABLE
140 0 : if (FT_IS_SFNT (face)) {
141 0 : status = CAIRO_INT_STATUS_UNSUPPORTED;
142 0 : goto fail1;
143 : }
144 : #endif
145 :
146 0 : memset (font, 0, sizeof (*font));
147 0 : font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
148 0 : font->base.num_glyphs = face->num_glyphs;
149 0 : font->base.x_min = face->bbox.xMin / (double)face->units_per_EM;
150 0 : font->base.y_min = face->bbox.yMin / (double)face->units_per_EM;
151 0 : font->base.x_max = face->bbox.xMax / (double)face->units_per_EM;
152 0 : font->base.y_max = face->bbox.yMax / (double)face->units_per_EM;
153 0 : font->base.ascent = face->ascender / (double)face->units_per_EM;
154 0 : font->base.descent = face->descender / (double)face->units_per_EM;
155 :
156 0 : if (face->family_name) {
157 0 : font->base.base_font = strdup (face->family_name);
158 0 : if (unlikely (font->base.base_font == NULL)) {
159 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
160 0 : goto fail2;
161 : }
162 0 : for (i = 0, j = 0; font->base.base_font[j]; j++) {
163 0 : if (font->base.base_font[j] == ' ')
164 0 : continue;
165 0 : font->base.base_font[i++] = font->base.base_font[j];
166 : }
167 0 : font->base.base_font[i] = '\0';
168 : }
169 :
170 0 : font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]);
171 0 : if (unlikely (font->glyphs == NULL)) {
172 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
173 0 : goto fail3;
174 : }
175 :
176 0 : font->hex_encode = hex_encode;
177 0 : font->num_glyphs = 0;
178 0 : for (i = 0; i < face->num_glyphs; i++)
179 0 : font->glyphs[i].subset_index = -1;
180 :
181 0 : _cairo_array_init (&font->contents, sizeof (char));
182 :
183 0 : _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
184 :
185 0 : return CAIRO_STATUS_SUCCESS;
186 :
187 : fail3:
188 0 : if (font->base.base_font)
189 0 : free (font->base.base_font);
190 : fail2:
191 0 : _cairo_unscaled_font_destroy (unscaled_font);
192 : fail1:
193 0 : _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
194 :
195 0 : return status;
196 : }
197 :
198 : static void
199 0 : cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph)
200 : {
201 0 : if (font->glyphs[glyph].subset_index >= 0)
202 0 : return;
203 :
204 0 : font->glyphs[glyph].subset_index = font->num_glyphs++;
205 : }
206 :
207 : static cairo_bool_t
208 0 : is_ps_delimiter(int c)
209 : {
210 : static const char delimiters[] = "()[]{}<>/% \t\r\n";
211 :
212 0 : return strchr (delimiters, c) != NULL;
213 : }
214 :
215 : static const char *
216 0 : find_token (const char *buffer, const char *end, const char *token)
217 : {
218 : int i, length;
219 : /* FIXME: find substring really must be find_token */
220 :
221 0 : if (buffer == NULL)
222 0 : return NULL;
223 :
224 0 : length = strlen (token);
225 0 : for (i = 0; buffer + i < end - length + 1; i++)
226 0 : if (memcmp (buffer + i, token, length) == 0)
227 0 : if ((i == 0 || token[0] == '/' || is_ps_delimiter(buffer[i - 1])) &&
228 0 : (buffer + i == end - length || is_ps_delimiter(buffer[i + length])))
229 0 : return buffer + i;
230 :
231 0 : return NULL;
232 : }
233 :
234 : static cairo_status_t
235 0 : cairo_type1_font_subset_find_segments (cairo_type1_font_subset_t *font)
236 : {
237 : unsigned char *p;
238 : const char *eexec_token;
239 : int size, i;
240 :
241 0 : p = (unsigned char *) font->type1_data;
242 0 : font->type1_end = font->type1_data + font->type1_length;
243 0 : if (p[0] == 0x80 && p[1] == 0x01) {
244 0 : font->header_segment_size =
245 0 : p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
246 0 : font->header_segment = (char *) p + 6;
247 :
248 0 : p += 6 + font->header_segment_size;
249 0 : font->eexec_segment_size =
250 0 : p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
251 0 : font->eexec_segment = (char *) p + 6;
252 0 : font->eexec_segment_is_ascii = (p[1] == 1);
253 :
254 0 : p += 6 + font->eexec_segment_size;
255 0 : while (p < (unsigned char *) (font->type1_end) && p[1] != 0x03) {
256 0 : size = p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
257 0 : p += 6 + size;
258 : }
259 0 : font->type1_end = (char *) p;
260 : } else {
261 0 : eexec_token = find_token ((char *) p, font->type1_end, "eexec");
262 0 : if (eexec_token == NULL)
263 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
264 :
265 0 : font->header_segment_size = eexec_token - (char *) p + strlen ("eexec\n");
266 0 : font->header_segment = (char *) p;
267 0 : font->eexec_segment_size = font->type1_length - font->header_segment_size;
268 0 : font->eexec_segment = (char *) p + font->header_segment_size;
269 0 : font->eexec_segment_is_ascii = TRUE;
270 0 : for (i = 0; i < 4; i++) {
271 0 : if (!isxdigit(font->eexec_segment[i]))
272 0 : font->eexec_segment_is_ascii = FALSE;
273 : }
274 : }
275 :
276 0 : return CAIRO_STATUS_SUCCESS;
277 : }
278 :
279 : /* Search for the definition of key and erase it by overwriting with spaces.
280 : * This function is looks for definitions of the form:
281 : *
282 : * /key1 1234 def
283 : * /key2 [12 34 56] def
284 : *
285 : * ie a key defined as an integer or array of integers.
286 : *
287 : */
288 : static void
289 0 : cairo_type1_font_erase_dict_key (cairo_type1_font_subset_t *font,
290 : const char *key)
291 : {
292 : const char *start, *p, *segment_end;
293 :
294 0 : segment_end = font->header_segment + font->header_segment_size;
295 :
296 0 : start = font->header_segment;
297 : do {
298 0 : start = find_token (start, segment_end, key);
299 0 : if (start) {
300 0 : p = start + strlen(key);
301 : /* skip integers or array of integers */
302 0 : while (p < segment_end &&
303 0 : (_cairo_isspace(*p) ||
304 0 : _cairo_isdigit(*p) ||
305 0 : *p == '[' ||
306 0 : *p == ']'))
307 : {
308 0 : p++;
309 : }
310 :
311 0 : if (p + 3 < segment_end && memcmp(p, "def", 3) == 0) {
312 : /* erase definition of the key */
313 0 : memset((char *) start, ' ', p + 3 - start);
314 : }
315 0 : start += strlen(key);
316 : }
317 0 : } while (start);
318 0 : }
319 :
320 : static cairo_status_t
321 0 : cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
322 : const char *name)
323 : {
324 : const char *start, *end, *segment_end;
325 : unsigned int i;
326 :
327 : /* FIXME:
328 : * This function assumes that /FontName always appears
329 : * before /Encoding. This appears to always be the case with Type1
330 : * fonts.
331 : *
332 : * The more recently added code for removing the UniqueID and XUID
333 : * keys can not make any assumptions about the position of the
334 : * keys in the dictionary so it is implemented by overwriting the
335 : * key definition with spaces before we start copying the font to
336 : * the output.
337 : *
338 : * This code should be rewritten to not make any assumptions about
339 : * the order of dictionary keys. This will allow UniqueID to be
340 : * stripped out instead of leaving a bunch of spaces in the
341 : * output.
342 : */
343 0 : cairo_type1_font_erase_dict_key (font, "/UniqueID");
344 0 : cairo_type1_font_erase_dict_key (font, "/XUID");
345 :
346 0 : segment_end = font->header_segment + font->header_segment_size;
347 :
348 : /* Type 1 fonts created by Fontforge have some PostScript code at
349 : * the start of the font that skips the font if the printer has a
350 : * cached copy of the font with the same unique id. This breaks
351 : * our subsetted font so we disable it by searching for the
352 : * PostScript operator "known" when used to check for the
353 : * "/UniqueID" dictionary key. We append " pop false " after it to
354 : * pop the result of this check off the stack and replace it with
355 : * "false" to make the PostScript code think "/UniqueID" does not
356 : * exist.
357 : */
358 0 : end = font->header_segment;
359 0 : start = find_token (font->header_segment, segment_end, "/UniqueID");
360 0 : if (start) {
361 0 : start += 9;
362 0 : while (start < segment_end && _cairo_isspace (*start))
363 0 : start++;
364 0 : if (start + 5 < segment_end && memcmp(start, "known", 5) == 0) {
365 0 : _cairo_output_stream_write (font->output, font->header_segment,
366 0 : start + 5 - font->header_segment);
367 0 : _cairo_output_stream_printf (font->output, " pop false ");
368 0 : end = start + 5;
369 : }
370 : }
371 :
372 0 : start = find_token (end, segment_end, "/FontName");
373 0 : if (start == NULL)
374 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
375 :
376 0 : _cairo_output_stream_write (font->output, end,
377 0 : start - end);
378 :
379 0 : _cairo_output_stream_printf (font->output, "/FontName /%s def", name);
380 :
381 0 : end = find_token (start, segment_end, "def");
382 0 : if (end == NULL)
383 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
384 0 : end += 3;
385 :
386 0 : start = find_token (end, segment_end, "/Encoding");
387 0 : if (start == NULL)
388 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
389 0 : _cairo_output_stream_write (font->output, end, start - end);
390 :
391 0 : _cairo_output_stream_printf (font->output,
392 : "/Encoding 256 array\n"
393 : "0 1 255 {1 index exch /.notdef put} for\n");
394 0 : for (i = 1; i < font->base.num_glyphs; i++) {
395 0 : if (font->glyphs[i].subset_index < 0)
396 0 : continue;
397 0 : _cairo_output_stream_printf (font->output,
398 : "dup %d /%s put\n",
399 0 : font->glyphs[i].subset_index,
400 0 : font->glyphs[i].name);
401 : }
402 0 : _cairo_output_stream_printf (font->output, "readonly def");
403 :
404 0 : end = find_token (start, segment_end, "def");
405 0 : if (end == NULL)
406 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
407 0 : end += 3;
408 :
409 0 : _cairo_output_stream_write (font->output, end, segment_end - end);
410 :
411 0 : return font->output->status;
412 : }
413 :
414 : static int
415 0 : hex_to_int (int ch)
416 : {
417 0 : if (ch <= '9')
418 0 : return ch - '0';
419 0 : else if (ch <= 'F')
420 0 : return ch - 'A' + 10;
421 : else
422 0 : return ch - 'a' + 10;
423 : }
424 :
425 : static cairo_status_t
426 0 : cairo_type1_font_subset_write_encrypted (cairo_type1_font_subset_t *font,
427 : const char *data, unsigned int length)
428 : {
429 : const unsigned char *in, *end;
430 : int c, p;
431 : static const char hex_digits[16] = "0123456789abcdef";
432 : char digits[3];
433 :
434 0 : in = (const unsigned char *) data;
435 0 : end = (const unsigned char *) data + length;
436 0 : while (in < end) {
437 0 : p = *in++;
438 0 : c = p ^ (font->eexec_key >> 8);
439 0 : font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
440 :
441 0 : if (font->hex_encode) {
442 0 : digits[0] = hex_digits[c >> 4];
443 0 : digits[1] = hex_digits[c & 0x0f];
444 0 : digits[2] = '\n';
445 0 : font->hex_column += 2;
446 :
447 0 : if (font->hex_column == 78) {
448 0 : _cairo_output_stream_write (font->output, digits, 3);
449 0 : font->hex_column = 0;
450 : } else {
451 0 : _cairo_output_stream_write (font->output, digits, 2);
452 : }
453 : } else {
454 0 : digits[0] = c;
455 0 : _cairo_output_stream_write (font->output, digits, 1);
456 : }
457 : }
458 :
459 0 : return font->output->status;
460 : }
461 :
462 : static cairo_status_t
463 0 : cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font)
464 : {
465 0 : unsigned short r = CAIRO_TYPE1_PRIVATE_DICT_KEY;
466 : unsigned char *in, *end;
467 : char *out;
468 : int c, p;
469 : int i;
470 :
471 0 : in = (unsigned char *) font->eexec_segment;
472 0 : end = (unsigned char *) in + font->eexec_segment_size;
473 :
474 0 : font->cleartext = malloc (font->eexec_segment_size);
475 0 : if (unlikely (font->cleartext == NULL))
476 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
477 :
478 0 : out = font->cleartext;
479 0 : while (in < end) {
480 0 : if (font->eexec_segment_is_ascii) {
481 0 : c = *in++;
482 0 : if (_cairo_isspace (c))
483 0 : continue;
484 0 : c = (hex_to_int (c) << 4) | hex_to_int (*in++);
485 : } else {
486 0 : c = *in++;
487 : }
488 0 : p = c ^ (r >> 8);
489 0 : r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
490 :
491 0 : *out++ = p;
492 : }
493 0 : font->cleartext_end = out;
494 :
495 : /* Overwrite random bytes with spaces.
496 : *
497 : * The first 4 bytes of the cleartext are the random bytes
498 : * required by the encryption algorithm. When encrypting the
499 : * cleartext, the first ciphertext byte must not be a white space
500 : * character and the first 4 bytes must not be an ASCII Hex
501 : * character. Some fonts do not check that their randomly chosen
502 : * bytes results in ciphertext that complies with this
503 : * restriction. This may cause problems for some PDF consumers. By
504 : * replacing the random bytes with spaces, the first four bytes of
505 : * ciphertext will always be 0xf9, 0x83, 0xef, 0x00 which complies
506 : * with this restriction. Using spaces also means we don't have to
507 : * skip over the random bytes when parsing the cleartext.
508 : */
509 0 : for (i = 0; i < 4 && i < font->eexec_segment_size; i++)
510 0 : font->cleartext[i] = ' ';
511 :
512 0 : return CAIRO_STATUS_SUCCESS;
513 : }
514 :
515 : static const char *
516 0 : skip_token (const char *p, const char *end)
517 : {
518 0 : while (p < end && _cairo_isspace(*p))
519 0 : p++;
520 :
521 0 : while (p < end && !_cairo_isspace(*p))
522 0 : p++;
523 :
524 0 : if (p == end)
525 0 : return NULL;
526 :
527 0 : return p;
528 : }
529 :
530 : static int
531 0 : cairo_type1_font_subset_lookup_glyph (cairo_type1_font_subset_t *font,
532 : const char *glyph_name, int length)
533 : {
534 : unsigned int i;
535 :
536 0 : for (i = 0; i < font->base.num_glyphs; i++) {
537 0 : if (font->glyphs[i].name &&
538 0 : strncmp (font->glyphs[i].name, glyph_name, length) == 0 &&
539 0 : font->glyphs[i].name[length] == '\0')
540 0 : return i;
541 : }
542 :
543 0 : return -1;
544 : }
545 :
546 : static cairo_status_t
547 0 : cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *font)
548 : {
549 : unsigned int i;
550 : char buffer[256];
551 : FT_Error error;
552 :
553 : /* Get glyph names and width using the freetype API */
554 0 : for (i = 0; i < font->base.num_glyphs; i++) {
555 0 : if (font->glyphs[i].name != NULL)
556 0 : continue;
557 :
558 0 : error = FT_Load_Glyph (font->face, i,
559 : FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING |
560 : FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
561 0 : if (error != FT_Err_Ok) {
562 : /* propagate fatal errors from FreeType */
563 0 : if (error == FT_Err_Out_Of_Memory)
564 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
565 :
566 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
567 : }
568 :
569 0 : font->glyphs[i].width = font->face->glyph->metrics.horiAdvance / (double)font->face->units_per_EM;
570 :
571 0 : error = FT_Get_Glyph_Name(font->face, i, buffer, sizeof buffer);
572 0 : if (error != FT_Err_Ok) {
573 : /* propagate fatal errors from FreeType */
574 0 : if (error == FT_Err_Out_Of_Memory)
575 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
576 :
577 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
578 : }
579 :
580 0 : font->glyphs[i].name = strdup (buffer);
581 0 : if (unlikely (font->glyphs[i].name == NULL))
582 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
583 : }
584 :
585 0 : return CAIRO_STATUS_SUCCESS;
586 : }
587 :
588 : static void
589 0 : cairo_type1_font_subset_decrypt_charstring (const unsigned char *in, int size, unsigned char *out)
590 : {
591 0 : unsigned short r = CAIRO_TYPE1_CHARSTRING_KEY;
592 : int c, p, i;
593 :
594 0 : for (i = 0; i < size; i++) {
595 0 : c = *in++;
596 0 : p = c ^ (r >> 8);
597 0 : r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
598 0 : *out++ = p;
599 : }
600 0 : }
601 :
602 : static const unsigned char *
603 0 : cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer)
604 : {
605 0 : if (*p <= 246) {
606 0 : *integer = *p++ - 139;
607 0 : } else if (*p <= 250) {
608 0 : *integer = (p[0] - 247) * 256 + p[1] + 108;
609 0 : p += 2;
610 0 : } else if (*p <= 254) {
611 0 : *integer = -(p[0] - 251) * 256 - p[1] - 108;
612 0 : p += 2;
613 : } else {
614 0 : *integer = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
615 0 : p += 5;
616 : }
617 :
618 0 : return p;
619 : }
620 :
621 : #if 0
622 : /*
623 : * The two tables that follow are generated using this perl code:
624 : */
625 :
626 : @encoding = (
627 : /* 0 */
628 : NULL, NULL, NULL, NULL,
629 : NULL, NULL, NULL, NULL,
630 : NULL, NULL, NULL, NULL,
631 : NULL, NULL, NULL, NULL,
632 : /* 16 */
633 : NULL, NULL, NULL, NULL,
634 : NULL, NULL, NULL, NULL,
635 : NULL, NULL, NULL, NULL,
636 : NULL, NULL, NULL, NULL,
637 : /* 32 */
638 : "space", "exclam", "quotedbl", "numbersign",
639 : "dollar", "percent", "ampersand", "quoteright",
640 : "parenleft", "parenright", "asterisk", "plus",
641 : "comma", "hyphen", "period", "slash",
642 : /* 48 */
643 : "zero", "one", "two", "three",
644 : "four", "five", "six", "seven",
645 : "eight", "nine", "colon", "semicolon",
646 : "less", "equal", "greater", "question",
647 : /* 64 */
648 : "at", "A", "B", "C",
649 : "D", "E", "F", "G",
650 : "H", "I", "J", "K",
651 : "L", "M", "N", "O",
652 : /* 80 */
653 : "P", "Q", "R", "S",
654 : "T", "U", "V", "W",
655 : "X", "Y", "Z", "bracketleft",
656 : "backslash", "bracketright", "asciicircum", "underscore",
657 : /* 96 */
658 : "quoteleft", "a", "b", "c",
659 : "d", "e", "f", "g",
660 : "h", "i", "j", "k",
661 : "l", "m", "n", "o",
662 : /* 112 */
663 : "p", "q", "r", "s",
664 : "t", "u", "v", "w",
665 : "x", "y", "z", "braceleft",
666 : "bar", "braceright", "asciitilde", NULL,
667 : /* 128 */
668 : NULL, NULL, NULL, NULL,
669 : NULL, NULL, NULL, NULL,
670 : NULL, NULL, NULL, NULL,
671 : NULL, NULL, NULL, NULL,
672 : /* 144 */
673 : NULL, NULL, NULL, NULL,
674 : NULL, NULL, NULL, NULL,
675 : NULL, NULL, NULL, NULL,
676 : NULL, NULL, NULL, NULL,
677 : /* 160 */
678 : NULL, "exclamdown", "cent", "sterling",
679 : "fraction", "yen", "florin", "section",
680 : "currency", "quotesingle", "quotedblleft", "guillemotleft",
681 : "guilsinglleft","guilsinglright","fi", "fl",
682 : /* 176 */
683 : NULL, "endash", "dagger", "daggerdbl",
684 : "periodcentered",NULL, "paragraph", "bullet",
685 : "quotesinglbase","quotedblbase","quotedblright","guillemotright",
686 : "ellipsis", "perthousand", NULL, "questiondown",
687 : /* 192 */
688 : NULL, "grave", "acute", "circumflex",
689 : "tilde", "macron", "breve", "dotaccent",
690 : "dieresis", NULL, "ring", "cedilla",
691 : NULL, "hungarumlaut", "ogonek", "caron",
692 : /* 208 */
693 : "emdash", NULL, NULL, NULL,
694 : NULL, NULL, NULL, NULL,
695 : NULL, NULL, NULL, NULL,
696 : NULL, NULL, NULL, NULL,
697 : /* 224 */
698 : NULL, "AE", NULL, "ordfeminine",
699 : NULL, NULL, NULL, NULL,
700 : "Lslash", "Oslash", "OE", "ordmasculine",
701 : NULL, NULL, NULL, NULL,
702 : /* 240 */
703 : NULL, "ae", NULL, NULL,
704 : NULL, "dotlessi", NULL, NULL,
705 : "lslash", "oslash", "oe", "germandbls",
706 : NULL, NULL, NULL, NULL
707 : );
708 :
709 : print "static const char ps_standard_encoding_symbol[] = {\n";
710 : $s = qq( "\\0");
711 : for $sym (@encoding) {
712 : if (! ($sym eq NULL)) {
713 : $ss = qq( "$sym\\0");
714 : if (length($s) + length($ss) > 78) {
715 : print qq( $s\n);
716 : $s = "";
717 : }
718 : $s .= $ss;
719 : }
720 : }
721 : print qq( $s\n);
722 : print "};\n\n";
723 : print "static const int16_t ps_standard_encoding_offset[256] = {\n";
724 : $offset = 1;
725 : $s = qq();
726 : for $sym (@encoding) {
727 : if (! ($sym eq NULL)) {
728 : $ss = qq( $offset/*$sym*/,);
729 : $offset += length($sym) + 1;
730 : } else {
731 : $ss = qq( 0,);
732 : }
733 : if (length($s) + length($ss) > 78) {
734 : print qq( $s\n);
735 : $s = "";
736 : }
737 : $s .= $ss;
738 : }
739 : print qq( $s\n);
740 : print "};\n";
741 : exit;
742 : #endif
743 :
744 : static const char ps_standard_encoding_symbol[] = {
745 : "\0" "space\0" "exclam\0" "quotedbl\0" "numbersign\0" "dollar\0" "percent\0"
746 : "ampersand\0" "quoteright\0" "parenleft\0" "parenright\0" "asterisk\0"
747 : "plus\0" "comma\0" "hyphen\0" "period\0" "slash\0" "zero\0" "one\0" "two\0"
748 : "three\0" "four\0" "five\0" "six\0" "seven\0" "eight\0" "nine\0" "colon\0"
749 : "semicolon\0" "less\0" "equal\0" "greater\0" "question\0" "at\0" "A\0" "B\0"
750 : "C\0" "D\0" "E\0" "F\0" "G\0" "H\0" "I\0" "J\0" "K\0" "L\0" "M\0" "N\0" "O\0"
751 : "P\0" "Q\0" "R\0" "S\0" "T\0" "U\0" "V\0" "W\0" "X\0" "Y\0" "Z\0"
752 : "bracketleft\0" "backslash\0" "bracketright\0" "asciicircum\0" "underscore\0"
753 : "quoteleft\0" "a\0" "b\0" "c\0" "d\0" "e\0" "f\0" "g\0" "h\0" "i\0" "j\0"
754 : "k\0" "l\0" "m\0" "n\0" "o\0" "p\0" "q\0" "r\0" "s\0" "t\0" "u\0" "v\0" "w\0"
755 : "x\0" "y\0" "z\0" "braceleft\0" "bar\0" "braceright\0" "asciitilde\0"
756 : "exclamdown\0" "cent\0" "sterling\0" "fraction\0" "yen\0" "florin\0"
757 : "section\0" "currency\0" "quotesingle\0" "quotedblleft\0" "guillemotleft\0"
758 : "guilsinglleft\0" "guilsinglright\0" "fi\0" "fl\0" "endash\0" "dagger\0"
759 : "daggerdbl\0" "periodcentered\0" "paragraph\0" "bullet\0" "quotesinglbase\0"
760 : "quotedblbase\0" "quotedblright\0" "guillemotright\0" "ellipsis\0"
761 : "perthousand\0" "questiondown\0" "grave\0" "acute\0" "circumflex\0" "tilde\0"
762 : "macron\0" "breve\0" "dotaccent\0" "dieresis\0" "ring\0" "cedilla\0"
763 : "hungarumlaut\0" "ogonek\0" "caron\0" "emdash\0" "AE\0" "ordfeminine\0"
764 : "Lslash\0" "Oslash\0" "OE\0" "ordmasculine\0" "ae\0" "dotlessi\0" "lslash\0"
765 : "oslash\0" "oe\0" "germandbls\0"
766 : };
767 :
768 : static const int16_t ps_standard_encoding_offset[256] = {
769 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
770 : 0, 0, 0, 0, 0, 0, 1/*space*/, 7/*exclam*/, 14/*quotedbl*/, 23/*numbersign*/,
771 : 34/*dollar*/, 41/*percent*/, 49/*ampersand*/, 59/*quoteright*/,
772 : 70/*parenleft*/, 80/*parenright*/, 91/*asterisk*/, 100/*plus*/, 105/*comma*/,
773 : 111/*hyphen*/, 118/*period*/, 125/*slash*/, 131/*zero*/, 136/*one*/,
774 : 140/*two*/, 144/*three*/, 150/*four*/, 155/*five*/, 160/*six*/, 164/*seven*/,
775 : 170/*eight*/, 176/*nine*/, 181/*colon*/, 187/*semicolon*/, 197/*less*/,
776 : 202/*equal*/, 208/*greater*/, 216/*question*/, 225/*at*/, 228/*A*/, 230/*B*/,
777 : 232/*C*/, 234/*D*/, 236/*E*/, 238/*F*/, 240/*G*/, 242/*H*/, 244/*I*/,
778 : 246/*J*/, 248/*K*/, 250/*L*/, 252/*M*/, 254/*N*/, 256/*O*/, 258/*P*/,
779 : 260/*Q*/, 262/*R*/, 264/*S*/, 266/*T*/, 268/*U*/, 270/*V*/, 272/*W*/,
780 : 274/*X*/, 276/*Y*/, 278/*Z*/, 280/*bracketleft*/, 292/*backslash*/,
781 : 302/*bracketright*/, 315/*asciicircum*/, 327/*underscore*/, 338/*quoteleft*/,
782 : 348/*a*/, 350/*b*/, 352/*c*/, 354/*d*/, 356/*e*/, 358/*f*/, 360/*g*/,
783 : 362/*h*/, 364/*i*/, 366/*j*/, 368/*k*/, 370/*l*/, 372/*m*/, 374/*n*/,
784 : 376/*o*/, 378/*p*/, 380/*q*/, 382/*r*/, 384/*s*/, 386/*t*/, 388/*u*/,
785 : 390/*v*/, 392/*w*/, 394/*x*/, 396/*y*/, 398/*z*/, 400/*braceleft*/,
786 : 410/*bar*/, 414/*braceright*/, 425/*asciitilde*/, 0, 0, 0, 0, 0, 0, 0, 0, 0,
787 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
788 : 436/*exclamdown*/, 447/*cent*/, 452/*sterling*/, 461/*fraction*/, 470/*yen*/,
789 : 474/*florin*/, 481/*section*/, 489/*currency*/, 498/*quotesingle*/,
790 : 510/*quotedblleft*/, 523/*guillemotleft*/, 537/*guilsinglleft*/,
791 : 551/*guilsinglright*/, 566/*fi*/, 569/*fl*/, 0, 572/*endash*/, 579/*dagger*/,
792 : 586/*daggerdbl*/, 596/*periodcentered*/, 0, 611/*paragraph*/, 621/*bullet*/,
793 : 628/*quotesinglbase*/, 643/*quotedblbase*/, 656/*quotedblright*/,
794 : 670/*guillemotright*/, 685/*ellipsis*/, 694/*perthousand*/, 0,
795 : 706/*questiondown*/, 0, 719/*grave*/, 725/*acute*/, 731/*circumflex*/,
796 : 742/*tilde*/, 748/*macron*/, 755/*breve*/, 761/*dotaccent*/, 771/*dieresis*/,
797 : 0, 780/*ring*/, 785/*cedilla*/, 0, 793/*hungarumlaut*/, 806/*ogonek*/,
798 : 813/*caron*/, 819/*emdash*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
799 : 826/*AE*/, 0, 829/*ordfeminine*/, 0, 0, 0, 0, 841/*Lslash*/, 848/*Oslash*/,
800 : 855/*OE*/, 858/*ordmasculine*/, 0, 0, 0, 0, 0, 871/*ae*/, 0, 0, 0,
801 : 874/*dotlessi*/, 0, 0, 883/*lslash*/, 890/*oslash*/, 897/*oe*/,
802 : 900/*germandbls*/, 0, 0, 0, 0,
803 : };
804 :
805 : #define ps_standard_encoding(index) ((index) ? ps_standard_encoding_symbol+ps_standard_encoding_offset[(index)] : NULL)
806 :
807 : static cairo_status_t
808 0 : use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
809 : {
810 : const char *glyph_name;
811 :
812 0 : if (index < 0 || index > 255)
813 0 : return CAIRO_STATUS_SUCCESS;
814 :
815 0 : glyph_name = ps_standard_encoding(index);
816 0 : if (glyph_name == NULL)
817 0 : return CAIRO_STATUS_SUCCESS;
818 :
819 0 : index = cairo_type1_font_subset_lookup_glyph (font,
820 : glyph_name,
821 0 : strlen(glyph_name));
822 0 : if (index < 0)
823 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
824 :
825 0 : cairo_type1_font_subset_use_glyph (font, index);
826 :
827 0 : return CAIRO_STATUS_SUCCESS;
828 : }
829 :
830 : #define TYPE1_CHARSTRING_COMMAND_ESCAPE (12)
831 : #define TYPE1_CHARSTRING_COMMAND_SEAC (32 + 6)
832 :
833 : static cairo_status_t
834 0 : cairo_type1_font_subset_look_for_seac(cairo_type1_font_subset_t *font,
835 : const char *name, int name_length,
836 : const char *encrypted_charstring, int encrypted_charstring_length)
837 : {
838 : cairo_status_t status;
839 : unsigned char *charstring;
840 : const unsigned char *end;
841 : const unsigned char *p;
842 : int stack[5], sp, value;
843 : int command;
844 :
845 0 : charstring = malloc (encrypted_charstring_length);
846 0 : if (unlikely (charstring == NULL))
847 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
848 :
849 0 : cairo_type1_font_subset_decrypt_charstring ((const unsigned char *)
850 : encrypted_charstring,
851 : encrypted_charstring_length,
852 : charstring);
853 0 : end = charstring + encrypted_charstring_length;
854 :
855 0 : p = charstring + 4;
856 0 : sp = 0;
857 :
858 0 : while (p < end) {
859 0 : if (*p < 32) {
860 0 : command = *p++;
861 :
862 0 : if (command == TYPE1_CHARSTRING_COMMAND_ESCAPE)
863 0 : command = 32 + *p++;
864 :
865 0 : switch (command) {
866 : case TYPE1_CHARSTRING_COMMAND_SEAC:
867 : /* The seac command takes five integer arguments. The
868 : * last two are glyph indices into the PS standard
869 : * encoding give the names of the glyphs that this
870 : * glyph is composed from. All we need to do is to
871 : * make sure those glyphs are present in the subset
872 : * under their standard names. */
873 0 : if (unlikely (sp < 5))
874 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
875 :
876 0 : status = use_standard_encoding_glyph (font, stack[3]);
877 0 : if (unlikely (status))
878 0 : return status;
879 :
880 0 : status = use_standard_encoding_glyph (font, stack[4]);
881 0 : if (unlikely (status))
882 0 : return status;
883 :
884 0 : sp = 0;
885 0 : break;
886 :
887 : default:
888 0 : sp = 0;
889 0 : break;
890 : }
891 : } else {
892 : /* integer argument */
893 0 : p = cairo_type1_font_subset_decode_integer (p, &value);
894 0 : if (sp < 5)
895 0 : stack[sp++] = value;
896 : }
897 : }
898 :
899 0 : free (charstring);
900 :
901 0 : return CAIRO_STATUS_SUCCESS;
902 : }
903 :
904 : static cairo_status_t
905 0 : write_used_glyphs (cairo_type1_font_subset_t *font,
906 : const char *name, int name_length,
907 : const char *charstring, int charstring_length)
908 : {
909 : cairo_status_t status;
910 : char buffer[256];
911 : int length;
912 :
913 0 : length = snprintf (buffer, sizeof buffer,
914 : "/%.*s %d %s ",
915 : name_length, name, charstring_length, font->rd);
916 0 : status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
917 0 : if (unlikely (status))
918 0 : return status;
919 :
920 0 : status = cairo_type1_font_subset_write_encrypted (font,
921 : charstring,
922 : charstring_length);
923 0 : if (unlikely (status))
924 0 : return status;
925 :
926 0 : length = snprintf (buffer, sizeof buffer, "%s\n", font->nd);
927 0 : status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
928 0 : if (unlikely (status))
929 0 : return status;
930 :
931 0 : return CAIRO_STATUS_SUCCESS;
932 : }
933 :
934 : typedef cairo_status_t (*glyph_func_t) (cairo_type1_font_subset_t *font,
935 : const char *name, int name_length,
936 : const char *charstring, int charstring_length);
937 :
938 : static cairo_status_t
939 0 : cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font,
940 : const char *dict_start,
941 : const char *dict_end,
942 : glyph_func_t func,
943 : const char **dict_out)
944 : {
945 : int charstring_length, name_length, glyph_index;
946 : const char *p, *charstring, *name;
947 : char *end;
948 :
949 : /* We're looking at '/' in the name of the first glyph. The glyph
950 : * definitions are on the form:
951 : *
952 : * /name 23 RD <23 binary bytes> ND
953 : *
954 : * or alternatively using -| and |- instead of RD and ND.
955 : *
956 : * We parse the glyph name and see if it is in the subset. If it
957 : * is, we call the specified callback with the glyph name and
958 : * glyph data, otherwise we just skip it. We need to parse
959 : * through a glyph definition; we can't just find the next '/',
960 : * since the binary data could contain a '/'.
961 : */
962 :
963 0 : p = dict_start;
964 :
965 0 : while (*p == '/') {
966 0 : name = p + 1;
967 0 : p = skip_token (p, dict_end);
968 0 : name_length = p - name;
969 :
970 0 : charstring_length = strtol (p, &end, 10);
971 0 : if (p == end)
972 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
973 :
974 : /* Skip past -| or RD to binary data. There is exactly one space
975 : * between the -| or RD token and the encrypted data, thus '+ 1'. */
976 0 : charstring = skip_token (end, dict_end) + 1;
977 :
978 : /* Skip binary data and |- or ND token. */
979 0 : p = skip_token (charstring + charstring_length, dict_end);
980 0 : while (p < dict_end && _cairo_isspace(*p))
981 0 : p++;
982 :
983 : /* In case any of the skip_token() calls above reached EOF, p will
984 : * be equal to dict_end. */
985 0 : if (p == dict_end)
986 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
987 :
988 0 : glyph_index = cairo_type1_font_subset_lookup_glyph (font,
989 : name, name_length);
990 0 : if (font->glyphs[glyph_index].subset_index >= 0) {
991 0 : cairo_status_t status = func (font,
992 : name, name_length,
993 : charstring, charstring_length);
994 0 : if (unlikely (status))
995 0 : return status;
996 : }
997 : }
998 :
999 0 : *dict_out = p;
1000 :
1001 0 : return CAIRO_STATUS_SUCCESS;
1002 : }
1003 :
1004 :
1005 : static cairo_status_t
1006 0 : cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
1007 : const char *name)
1008 : {
1009 : cairo_status_t status;
1010 : const char *p, *charstrings, *dict_start;
1011 : const char *closefile_token;
1012 : char buffer[32], *glyph_count_end;
1013 : int num_charstrings, length;
1014 :
1015 : /* The private dict holds hint information, common subroutines and
1016 : * the actual glyph definitions (charstrings).
1017 : *
1018 : * FIXME: update this comment.
1019 : *
1020 : * What we do here is scan directly the /CharString token, which
1021 : * marks the beginning of the glyph definitions. Then we parse
1022 : * through the glyph definitions and weed out the glyphs not in
1023 : * our subset. Everything else before and after the glyph
1024 : * definitions is copied verbatim to the output. It might be
1025 : * worthwile to figure out which of the common subroutines are
1026 : * used by the glyphs in the subset and get rid of the rest. */
1027 :
1028 : /* FIXME: The /Subrs array contains binary data and could
1029 : * conceivably have "/CharStrings" in it, so we might need to skip
1030 : * this more cleverly. */
1031 0 : charstrings = find_token (font->cleartext, font->cleartext_end, "/CharStrings");
1032 0 : if (charstrings == NULL)
1033 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
1034 :
1035 : /* Scan past /CharStrings and the integer following it. */
1036 0 : p = charstrings + strlen ("/CharStrings");
1037 0 : num_charstrings = strtol (p, &glyph_count_end, 10);
1038 0 : if (p == glyph_count_end)
1039 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
1040 :
1041 : /* Look for a '/' which marks the beginning of the first glyph
1042 : * definition. */
1043 0 : for (p = glyph_count_end; p < font->cleartext_end; p++)
1044 0 : if (*p == '/')
1045 0 : break;
1046 0 : if (p == font->cleartext_end)
1047 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
1048 0 : dict_start = p;
1049 :
1050 0 : status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
1051 0 : if (unlikely (status))
1052 0 : return status;
1053 :
1054 : /* Now that we have the private dictionary broken down in
1055 : * sections, do the first pass through the glyph definitions to
1056 : * figure out which subrs and othersubrs are use and which extra
1057 : * glyphs may be required by the seac operator. */
1058 0 : status = cairo_type1_font_subset_for_each_glyph (font,
1059 : dict_start,
1060 0 : font->cleartext_end,
1061 : cairo_type1_font_subset_look_for_seac,
1062 : &p);
1063 0 : if (unlikely (status))
1064 0 : return status;
1065 :
1066 0 : closefile_token = find_token (p, font->cleartext_end, "closefile");
1067 0 : if (closefile_token == NULL)
1068 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
1069 :
1070 0 : status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
1071 0 : if (unlikely (status))
1072 0 : return status;
1073 :
1074 : /* We're ready to start outputting. First write the header,
1075 : * i.e. the public part of the font dict.*/
1076 0 : status = cairo_type1_font_subset_write_header (font, name);
1077 0 : if (unlikely (status))
1078 0 : return status;
1079 :
1080 0 : font->base.header_size = _cairo_output_stream_get_position (font->output);
1081 :
1082 :
1083 : /* Start outputting the private dict. First output everything up
1084 : * to the /CharStrings token. */
1085 0 : status = cairo_type1_font_subset_write_encrypted (font, font->cleartext,
1086 0 : charstrings - font->cleartext);
1087 0 : if (unlikely (status))
1088 0 : return status;
1089 :
1090 : /* Write out new charstring count */
1091 0 : length = snprintf (buffer, sizeof buffer,
1092 : "/CharStrings %d", font->num_glyphs);
1093 0 : status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
1094 0 : if (unlikely (status))
1095 0 : return status;
1096 :
1097 : /* Write out text between the charstring count and the first
1098 : * charstring definition */
1099 0 : status = cairo_type1_font_subset_write_encrypted (font, glyph_count_end,
1100 0 : dict_start - glyph_count_end);
1101 0 : if (unlikely (status))
1102 0 : return status;
1103 :
1104 : /* Write out the charstring definitions for each of the glyphs in
1105 : * the subset. */
1106 0 : status = cairo_type1_font_subset_for_each_glyph (font,
1107 : dict_start,
1108 0 : font->cleartext_end,
1109 : write_used_glyphs,
1110 : &p);
1111 0 : if (unlikely (status))
1112 0 : return status;
1113 :
1114 : /* Output what's left between the end of the glyph definitions and
1115 : * the end of the private dict to the output. */
1116 0 : status = cairo_type1_font_subset_write_encrypted (font, p,
1117 0 : closefile_token - p + strlen ("closefile") + 1);
1118 0 : if (unlikely (status))
1119 0 : return status;
1120 :
1121 0 : if (font->hex_encode)
1122 0 : _cairo_output_stream_write (font->output, "\n", 1);
1123 :
1124 0 : return CAIRO_STATUS_SUCCESS;
1125 : }
1126 :
1127 : static cairo_status_t
1128 0 : cairo_type1_font_subset_write_trailer(cairo_type1_font_subset_t *font)
1129 : {
1130 : const char *cleartomark_token;
1131 : int i;
1132 : static const char zeros[65] =
1133 : "0000000000000000000000000000000000000000000000000000000000000000\n";
1134 :
1135 :
1136 0 : for (i = 0; i < 8; i++)
1137 0 : _cairo_output_stream_write (font->output, zeros, sizeof zeros);
1138 :
1139 0 : cleartomark_token = find_token (font->type1_data, font->type1_end, "cleartomark");
1140 0 : if (cleartomark_token) {
1141 : /* Some fonts have conditional save/restore around the entire
1142 : * font dict, so we need to retain whatever postscript code
1143 : * that may come after 'cleartomark'. */
1144 :
1145 0 : _cairo_output_stream_write (font->output, cleartomark_token,
1146 0 : font->type1_end - cleartomark_token);
1147 0 : } else if (!font->eexec_segment_is_ascii) {
1148 : /* Fonts embedded in PDF may omit the fixed-content portion
1149 : * that includes the 'cleartomark' operator. Type 1 in PDF is
1150 : * always binary. */
1151 :
1152 0 : _cairo_output_stream_printf (font->output, "cleartomark");
1153 : } else {
1154 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
1155 : }
1156 :
1157 : /* some fonts do not have a newline at the end of the last line */
1158 0 : _cairo_output_stream_printf (font->output, "\n");
1159 :
1160 0 : return CAIRO_STATUS_SUCCESS;
1161 : }
1162 :
1163 : static cairo_status_t
1164 0 : type1_font_write (void *closure, const unsigned char *data, unsigned int length)
1165 : {
1166 0 : cairo_type1_font_subset_t *font = closure;
1167 :
1168 0 : return _cairo_array_append_multiple (&font->contents, data, length);
1169 : }
1170 :
1171 : static cairo_status_t
1172 0 : cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
1173 : const char *name)
1174 : {
1175 : cairo_status_t status;
1176 :
1177 0 : status = cairo_type1_font_subset_find_segments (font);
1178 0 : if (unlikely (status))
1179 0 : return status;
1180 :
1181 0 : status = cairo_type1_font_subset_decrypt_eexec_segment (font);
1182 0 : if (unlikely (status))
1183 0 : return status;
1184 :
1185 : /* Determine which glyph definition delimiters to use. */
1186 0 : if (find_token (font->cleartext, font->cleartext_end, "/-|") != NULL) {
1187 0 : font->rd = "-|";
1188 0 : font->nd = "|-";
1189 0 : } else if (find_token (font->cleartext, font->cleartext_end, "/RD") != NULL) {
1190 0 : font->rd = "RD";
1191 0 : font->nd = "ND";
1192 : } else {
1193 : /* Don't know *what* kind of font this is... */
1194 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
1195 : }
1196 :
1197 0 : font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
1198 0 : font->hex_column = 0;
1199 :
1200 0 : status = cairo_type1_font_subset_write_private_dict (font, name);
1201 0 : if (unlikely (status))
1202 0 : return status;
1203 :
1204 0 : font->base.data_size = _cairo_output_stream_get_position (font->output) -
1205 0 : font->base.header_size;
1206 :
1207 0 : status = cairo_type1_font_subset_write_trailer (font);
1208 0 : if (unlikely (status))
1209 0 : return status;
1210 :
1211 0 : font->base.trailer_size =
1212 0 : _cairo_output_stream_get_position (font->output) -
1213 0 : font->base.header_size - font->base.data_size;
1214 :
1215 0 : return CAIRO_STATUS_SUCCESS;
1216 : }
1217 :
1218 : static cairo_status_t
1219 0 : cairo_type1_font_subset_generate (void *abstract_font,
1220 : const char *name)
1221 :
1222 : {
1223 0 : cairo_type1_font_subset_t *font = abstract_font;
1224 : cairo_ft_unscaled_font_t *ft_unscaled_font;
1225 : unsigned long ret;
1226 : cairo_status_t status;
1227 :
1228 0 : ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font;
1229 0 : font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
1230 0 : if (unlikely (font->face == NULL))
1231 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1232 :
1233 0 : font->type1_length = font->face->stream->size;
1234 0 : font->type1_data = malloc (font->type1_length);
1235 0 : if (unlikely (font->type1_data == NULL)) {
1236 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1237 0 : goto fail;
1238 : }
1239 :
1240 0 : if (font->face->stream->read != NULL) {
1241 : /* Note that read() may be implemented as a macro, thanks POSIX!, so we
1242 : * need to wrap the following usage in parentheses in order to
1243 : * disambiguate it for the pre-processor - using the verbose function
1244 : * pointer dereference for clarity.
1245 : */
1246 0 : ret = (* font->face->stream->read) (font->face->stream, 0,
1247 0 : (unsigned char *) font->type1_data,
1248 0 : font->type1_length);
1249 0 : if (ret != font->type1_length) {
1250 0 : status = _cairo_error (CAIRO_STATUS_READ_ERROR);
1251 0 : goto fail;
1252 : }
1253 : } else {
1254 0 : memcpy (font->type1_data,
1255 0 : font->face->stream->base, font->type1_length);
1256 : }
1257 :
1258 0 : status = _cairo_array_grow_by (&font->contents, 4096);
1259 0 : if (unlikely (status))
1260 0 : goto fail;
1261 :
1262 0 : font->output = _cairo_output_stream_create (type1_font_write, NULL, font);
1263 0 : if (unlikely ((status = font->output->status)))
1264 0 : goto fail;
1265 :
1266 0 : status = cairo_type1_font_subset_write (font, name);
1267 0 : if (unlikely (status))
1268 0 : goto fail;
1269 :
1270 0 : font->base.data = _cairo_array_index (&font->contents, 0);
1271 :
1272 : fail:
1273 0 : _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
1274 :
1275 0 : return status;
1276 : }
1277 :
1278 : static cairo_status_t
1279 0 : _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
1280 : {
1281 0 : cairo_status_t status = CAIRO_STATUS_SUCCESS;
1282 : unsigned int i;
1283 :
1284 : /* If the subset generation failed, some of the pointers below may
1285 : * be NULL depending on at which point the error occurred. */
1286 :
1287 0 : _cairo_array_fini (&font->contents);
1288 :
1289 0 : free (font->type1_data);
1290 0 : if (font->glyphs != NULL) {
1291 0 : for (i = 0; i < font->base.num_glyphs; i++)
1292 0 : free (font->glyphs[i].name);
1293 : }
1294 :
1295 0 : _cairo_unscaled_font_destroy (font->base.unscaled_font);
1296 :
1297 0 : if (font->output != NULL)
1298 0 : status = _cairo_output_stream_destroy (font->output);
1299 :
1300 0 : if (font->base.base_font)
1301 0 : free (font->base.base_font);
1302 0 : free (font->glyphs);
1303 :
1304 0 : return status;
1305 : }
1306 :
1307 : cairo_status_t
1308 0 : _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
1309 : const char *name,
1310 : cairo_scaled_font_subset_t *scaled_font_subset,
1311 : cairo_bool_t hex_encode)
1312 : {
1313 : cairo_type1_font_subset_t font;
1314 : cairo_status_t status, status_ignored;
1315 : unsigned long parent_glyph, length;
1316 : unsigned int i;
1317 : cairo_unscaled_font_t *unscaled_font;
1318 : char buf[30];
1319 :
1320 : /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
1321 0 : if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
1322 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
1323 :
1324 0 : if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font))
1325 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
1326 :
1327 0 : unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
1328 :
1329 0 : status = _cairo_type1_font_subset_init (&font, unscaled_font, hex_encode);
1330 0 : if (unlikely (status))
1331 0 : return status;
1332 :
1333 0 : for (i = 0; i < scaled_font_subset->num_glyphs; i++) {
1334 0 : parent_glyph = scaled_font_subset->glyphs[i];
1335 0 : cairo_type1_font_subset_use_glyph (&font, parent_glyph);
1336 : }
1337 :
1338 0 : status = cairo_type1_font_subset_generate (&font, name);
1339 0 : if (unlikely (status))
1340 0 : goto fail1;
1341 :
1342 0 : if (font.base.base_font) {
1343 0 : type1_subset->base_font = strdup (font.base.base_font);
1344 : } else {
1345 0 : snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
1346 : scaled_font_subset->font_id, scaled_font_subset->subset_id);
1347 0 : type1_subset->base_font = strdup (buf);
1348 : }
1349 0 : if (unlikely (type1_subset->base_font == NULL))
1350 0 : goto fail1;
1351 :
1352 0 : type1_subset->widths = calloc (sizeof (double), font.num_glyphs);
1353 0 : if (unlikely (type1_subset->widths == NULL))
1354 0 : goto fail2;
1355 0 : for (i = 0; i < font.base.num_glyphs; i++) {
1356 0 : if (font.glyphs[i].subset_index < 0)
1357 0 : continue;
1358 0 : type1_subset->widths[font.glyphs[i].subset_index] =
1359 0 : font.glyphs[i].width;
1360 : }
1361 :
1362 0 : type1_subset->x_min = font.base.x_min/1000.0;
1363 0 : type1_subset->y_min = font.base.y_min/1000.0;
1364 0 : type1_subset->x_max = font.base.x_max/1000.0;
1365 0 : type1_subset->y_max = font.base.y_max/1000.0;
1366 0 : type1_subset->ascent = font.base.ascent/1000.0;
1367 0 : type1_subset->descent = font.base.descent/1000.0;
1368 :
1369 0 : length = font.base.header_size +
1370 0 : font.base.data_size +
1371 0 : font.base.trailer_size;
1372 0 : type1_subset->data = malloc (length);
1373 0 : if (unlikely (type1_subset->data == NULL))
1374 0 : goto fail3;
1375 :
1376 0 : memcpy (type1_subset->data,
1377 0 : _cairo_array_index (&font.contents, 0), length);
1378 :
1379 0 : type1_subset->header_length = font.base.header_size;
1380 0 : type1_subset->data_length = font.base.data_size;
1381 0 : type1_subset->trailer_length = font.base.trailer_size;
1382 :
1383 0 : return _cairo_type1_font_subset_fini (&font);
1384 :
1385 : fail3:
1386 0 : free (type1_subset->widths);
1387 : fail2:
1388 0 : free (type1_subset->base_font);
1389 : fail1:
1390 0 : status_ignored = _cairo_type1_font_subset_fini (&font);
1391 :
1392 0 : return status;
1393 : }
1394 :
1395 : void
1396 0 : _cairo_type1_subset_fini (cairo_type1_subset_t *subset)
1397 : {
1398 0 : free (subset->base_font);
1399 0 : free (subset->widths);
1400 0 : free (subset->data);
1401 0 : }
1402 :
1403 : cairo_bool_t
1404 0 : _cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
1405 : {
1406 : cairo_ft_unscaled_font_t *unscaled;
1407 : FT_Face face;
1408 : PS_FontInfoRec font_info;
1409 0 : cairo_bool_t is_type1 = FALSE;
1410 :
1411 0 : if (!_cairo_scaled_font_is_ft (scaled_font))
1412 0 : return FALSE;
1413 0 : unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
1414 0 : face = _cairo_ft_unscaled_font_lock_face (unscaled);
1415 0 : if (!face)
1416 0 : return FALSE;
1417 :
1418 0 : if (FT_Get_PS_Font_Info(face, &font_info) == 0)
1419 0 : is_type1 = TRUE;
1420 :
1421 : /* OpenType/CFF fonts also have a PS_FontInfoRec */
1422 : #if HAVE_FT_LOAD_SFNT_TABLE
1423 0 : if (FT_IS_SFNT (face))
1424 0 : is_type1 = FALSE;
1425 : #endif
1426 :
1427 0 : _cairo_ft_unscaled_font_unlock_face (unscaled);
1428 :
1429 0 : return is_type1;
1430 : }
1431 :
1432 : #endif /* CAIRO_HAS_FT_FONT */
1433 :
1434 : #endif /* CAIRO_HAS_FONT_SUBSET */
|