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 : * Adrian Johnson <ajohnson@redneon.com>
34 : */
35 :
36 : #define _BSD_SOURCE /* for snprintf(), strdup() */
37 : #include "cairoint.h"
38 : #include "cairo-error-private.h"
39 :
40 : #if CAIRO_HAS_FONT_SUBSET
41 :
42 : #include "cairo-type1-private.h"
43 : #include "cairo-scaled-font-subsets-private.h"
44 : #include "cairo-path-fixed-private.h"
45 : #include "cairo-output-stream-private.h"
46 :
47 : typedef enum {
48 : CAIRO_CHARSTRING_TYPE1,
49 : CAIRO_CHARSTRING_TYPE2
50 : } cairo_charstring_type_t;
51 :
52 : typedef struct _cairo_type1_font {
53 : int *widths;
54 :
55 : cairo_scaled_font_subset_t *scaled_font_subset;
56 : cairo_scaled_font_t *type1_scaled_font;
57 :
58 : cairo_array_t contents;
59 :
60 : double x_min, y_min, x_max, y_max;
61 :
62 : const char *data;
63 : unsigned long header_size;
64 : unsigned long data_size;
65 : unsigned long trailer_size;
66 : int bbox_position;
67 : int bbox_max_chars;
68 :
69 : cairo_output_stream_t *output;
70 :
71 : unsigned short eexec_key;
72 : cairo_bool_t hex_encode;
73 : int hex_column;
74 : } cairo_type1_font_t;
75 :
76 : static cairo_status_t
77 0 : cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
78 : cairo_type1_font_t **subset_return,
79 : cairo_bool_t hex_encode)
80 : {
81 : cairo_type1_font_t *font;
82 : cairo_font_face_t *font_face;
83 : cairo_matrix_t font_matrix;
84 : cairo_matrix_t ctm;
85 : cairo_font_options_t font_options;
86 : cairo_status_t status;
87 :
88 0 : font = calloc (1, sizeof (cairo_type1_font_t));
89 0 : if (unlikely (font == NULL))
90 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
91 :
92 0 : font->widths = calloc (scaled_font_subset->num_glyphs, sizeof (int));
93 0 : if (unlikely (font->widths == NULL)) {
94 0 : free (font);
95 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
96 : }
97 :
98 0 : font->scaled_font_subset = scaled_font_subset;
99 0 : font->hex_encode = hex_encode;
100 :
101 0 : font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
102 :
103 0 : cairo_matrix_init_scale (&font_matrix, 1000, -1000);
104 0 : cairo_matrix_init_identity (&ctm);
105 :
106 0 : _cairo_font_options_init_default (&font_options);
107 0 : cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
108 0 : cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);
109 :
110 0 : font->type1_scaled_font = cairo_scaled_font_create (font_face,
111 : &font_matrix,
112 : &ctm,
113 : &font_options);
114 0 : status = font->type1_scaled_font->status;
115 0 : if (unlikely (status))
116 0 : goto fail;
117 :
118 0 : _cairo_array_init (&font->contents, sizeof (unsigned char));
119 0 : font->output = NULL;
120 :
121 0 : *subset_return = font;
122 :
123 0 : return CAIRO_STATUS_SUCCESS;
124 :
125 : fail:
126 0 : free (font->widths);
127 0 : free (font);
128 :
129 0 : return status;
130 : }
131 :
132 : /* Charstring commands. If the high byte is 0 the command is encoded
133 : * with a single byte. */
134 : #define CHARSTRING_sbw 0x0c07
135 : #define CHARSTRING_rmoveto 0x0015
136 : #define CHARSTRING_rlineto 0x0005
137 : #define CHARSTRING_rcurveto 0x0008
138 : #define CHARSTRING_closepath 0x0009
139 : #define CHARSTRING_endchar 0x000e
140 :
141 : /* Before calling this function, the caller must allocate sufficient
142 : * space in data (see _cairo_array_grow_by). The maximum number of
143 : * bytes that will be used is 2.
144 : */
145 : static void
146 0 : charstring_encode_command (cairo_array_t *data, int command)
147 : {
148 : cairo_status_t status;
149 : int orig_size;
150 : unsigned char buf[5];
151 0 : unsigned char *p = buf;
152 :
153 0 : if (command & 0xff00)
154 0 : *p++ = command >> 8;
155 0 : *p++ = command & 0x00ff;
156 :
157 : /* Ensure the array doesn't grow, which allows this function to
158 : * have no possibility of failure. */
159 0 : orig_size = _cairo_array_size (data);
160 0 : status = _cairo_array_append_multiple (data, buf, p - buf);
161 :
162 0 : assert (status == CAIRO_STATUS_SUCCESS);
163 0 : assert (_cairo_array_size (data) == orig_size);
164 0 : }
165 :
166 : /* Before calling this function, the caller must allocate sufficient
167 : * space in data (see _cairo_array_grow_by). The maximum number of
168 : * bytes that will be used is 5.
169 : */
170 : static void
171 0 : charstring_encode_integer (cairo_array_t *data,
172 : int i,
173 : cairo_charstring_type_t type)
174 : {
175 : cairo_status_t status;
176 : int orig_size;
177 : unsigned char buf[10];
178 0 : unsigned char *p = buf;
179 :
180 0 : if (i >= -107 && i <= 107) {
181 0 : *p++ = i + 139;
182 0 : } else if (i >= 108 && i <= 1131) {
183 0 : i -= 108;
184 0 : *p++ = (i >> 8)+ 247;
185 0 : *p++ = i & 0xff;
186 0 : } else if (i >= -1131 && i <= -108) {
187 0 : i = -i - 108;
188 0 : *p++ = (i >> 8)+ 251;
189 0 : *p++ = i & 0xff;
190 : } else {
191 0 : if (type == CAIRO_CHARSTRING_TYPE1) {
192 0 : *p++ = 0xff;
193 0 : *p++ = i >> 24;
194 0 : *p++ = (i >> 16) & 0xff;
195 0 : *p++ = (i >> 8) & 0xff;
196 0 : *p++ = i & 0xff;
197 : } else {
198 0 : *p++ = 0xff;
199 0 : *p++ = (i >> 8) & 0xff;
200 0 : *p++ = i & 0xff;
201 0 : *p++ = 0;
202 0 : *p++ = 0;
203 : }
204 : }
205 :
206 : /* Ensure the array doesn't grow, which allows this function to
207 : * have no possibility of failure. */
208 0 : orig_size = _cairo_array_size (data);
209 0 : status = _cairo_array_append_multiple (data, buf, p - buf);
210 :
211 0 : assert (status == CAIRO_STATUS_SUCCESS);
212 0 : assert (_cairo_array_size (data) == orig_size);
213 0 : }
214 :
215 : typedef struct _ps_path_info {
216 : cairo_array_t *data;
217 : int current_x, current_y;
218 : cairo_charstring_type_t type;
219 : } t1_path_info_t;
220 :
221 : static cairo_status_t
222 0 : _charstring_move_to (void *closure,
223 : const cairo_point_t *point)
224 : {
225 0 : t1_path_info_t *path_info = (t1_path_info_t *) closure;
226 : int dx, dy;
227 : cairo_status_t status;
228 :
229 0 : status = _cairo_array_grow_by (path_info->data, 12);
230 0 : if (unlikely (status))
231 0 : return status;
232 :
233 0 : dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
234 0 : dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
235 0 : charstring_encode_integer (path_info->data, dx, path_info->type);
236 0 : charstring_encode_integer (path_info->data, dy, path_info->type);
237 0 : path_info->current_x += dx;
238 0 : path_info->current_y += dy;
239 :
240 0 : charstring_encode_command (path_info->data, CHARSTRING_rmoveto);
241 :
242 0 : return CAIRO_STATUS_SUCCESS;
243 : }
244 :
245 : static cairo_status_t
246 0 : _charstring_line_to (void *closure,
247 : const cairo_point_t *point)
248 : {
249 0 : t1_path_info_t *path_info = (t1_path_info_t *) closure;
250 : int dx, dy;
251 : cairo_status_t status;
252 :
253 0 : status = _cairo_array_grow_by (path_info->data, 12);
254 0 : if (unlikely (status))
255 0 : return status;
256 :
257 0 : dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
258 0 : dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
259 0 : charstring_encode_integer (path_info->data, dx, path_info->type);
260 0 : charstring_encode_integer (path_info->data, dy, path_info->type);
261 0 : path_info->current_x += dx;
262 0 : path_info->current_y += dy;
263 :
264 0 : charstring_encode_command (path_info->data, CHARSTRING_rlineto);
265 :
266 0 : return CAIRO_STATUS_SUCCESS;
267 : }
268 :
269 : static cairo_status_t
270 0 : _charstring_curve_to (void *closure,
271 : const cairo_point_t *point1,
272 : const cairo_point_t *point2,
273 : const cairo_point_t *point3)
274 : {
275 0 : t1_path_info_t *path_info = (t1_path_info_t *) closure;
276 : int dx1, dy1, dx2, dy2, dx3, dy3;
277 : cairo_status_t status;
278 :
279 0 : status = _cairo_array_grow_by (path_info->data, 32);
280 0 : if (unlikely (status))
281 0 : return status;
282 :
283 0 : dx1 = _cairo_fixed_integer_part (point1->x) - path_info->current_x;
284 0 : dy1 = _cairo_fixed_integer_part (point1->y) - path_info->current_y;
285 0 : dx2 = _cairo_fixed_integer_part (point2->x) - path_info->current_x - dx1;
286 0 : dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1;
287 0 : dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2;
288 0 : dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2;
289 0 : charstring_encode_integer (path_info->data, dx1, path_info->type);
290 0 : charstring_encode_integer (path_info->data, dy1, path_info->type);
291 0 : charstring_encode_integer (path_info->data, dx2, path_info->type);
292 0 : charstring_encode_integer (path_info->data, dy2, path_info->type);
293 0 : charstring_encode_integer (path_info->data, dx3, path_info->type);
294 0 : charstring_encode_integer (path_info->data, dy3, path_info->type);
295 0 : path_info->current_x += dx1 + dx2 + dx3;
296 0 : path_info->current_y += dy1 + dy2 + dy3;
297 0 : charstring_encode_command (path_info->data, CHARSTRING_rcurveto);
298 :
299 0 : return CAIRO_STATUS_SUCCESS;
300 : }
301 :
302 : static cairo_status_t
303 0 : _charstring_close_path (void *closure)
304 : {
305 : cairo_status_t status;
306 0 : t1_path_info_t *path_info = (t1_path_info_t *) closure;
307 :
308 0 : if (path_info->type == CAIRO_CHARSTRING_TYPE2)
309 0 : return CAIRO_STATUS_SUCCESS;
310 :
311 0 : status = _cairo_array_grow_by (path_info->data, 2);
312 0 : if (unlikely (status))
313 0 : return status;
314 :
315 0 : charstring_encode_command (path_info->data, CHARSTRING_closepath);
316 :
317 0 : return CAIRO_STATUS_SUCCESS;
318 : }
319 :
320 : static void
321 0 : charstring_encrypt (cairo_array_t *data)
322 : {
323 : unsigned char *d, *end;
324 : uint16_t c, p, r;
325 :
326 0 : r = CAIRO_TYPE1_CHARSTRING_KEY;
327 0 : d = (unsigned char *) _cairo_array_index (data, 0);
328 0 : end = d + _cairo_array_num_elements (data);
329 0 : while (d < end) {
330 0 : p = *d;
331 0 : c = p ^ (r >> 8);
332 0 : r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
333 0 : *d++ = c;
334 : }
335 0 : }
336 :
337 : static cairo_int_status_t
338 0 : cairo_type1_font_create_charstring (cairo_type1_font_t *font,
339 : int subset_index,
340 : int glyph_index,
341 : cairo_charstring_type_t type,
342 : cairo_array_t *data)
343 : {
344 : cairo_int_status_t status;
345 : cairo_scaled_glyph_t *scaled_glyph;
346 : t1_path_info_t path_info;
347 : cairo_text_extents_t *metrics;
348 0 : cairo_bool_t emit_path = TRUE;
349 :
350 : /* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */
351 0 : status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
352 : glyph_index,
353 : CAIRO_SCALED_GLYPH_INFO_METRICS|
354 : CAIRO_SCALED_GLYPH_INFO_PATH,
355 : &scaled_glyph);
356 :
357 : /* It is ok for the .notdef glyph to not have a path available. We
358 : * just need the metrics to emit an empty glyph. */
359 0 : if (glyph_index == 0 && status == CAIRO_INT_STATUS_UNSUPPORTED) {
360 0 : emit_path = FALSE;
361 0 : status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
362 : glyph_index,
363 : CAIRO_SCALED_GLYPH_INFO_METRICS,
364 : &scaled_glyph);
365 : }
366 0 : if (unlikely (status))
367 0 : return status;
368 :
369 0 : metrics = &scaled_glyph->metrics;
370 0 : if (subset_index == 0) {
371 0 : font->x_min = metrics->x_bearing;
372 0 : font->y_min = metrics->y_bearing;
373 0 : font->x_max = metrics->x_bearing + metrics->width;
374 0 : font->y_max = metrics->y_bearing + metrics->height;
375 : } else {
376 0 : if (metrics->x_bearing < font->x_min)
377 0 : font->x_min = metrics->x_bearing;
378 0 : if (metrics->y_bearing < font->y_min)
379 0 : font->y_min = metrics->y_bearing;
380 0 : if (metrics->x_bearing + metrics->width > font->x_max)
381 0 : font->x_max = metrics->x_bearing + metrics->width;
382 0 : if (metrics->y_bearing + metrics->height > font->y_max)
383 0 : font->y_max = metrics->y_bearing + metrics->height;
384 : }
385 0 : font->widths[subset_index] = metrics->x_advance;
386 :
387 0 : status = _cairo_array_grow_by (data, 30);
388 0 : if (unlikely (status))
389 0 : return status;
390 :
391 0 : if (type == CAIRO_CHARSTRING_TYPE1) {
392 0 : charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing, type);
393 0 : charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing, type);
394 0 : charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type);
395 0 : charstring_encode_integer (data, (int) scaled_glyph->metrics.y_advance, type);
396 0 : charstring_encode_command (data, CHARSTRING_sbw);
397 :
398 0 : path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
399 0 : path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
400 : } else {
401 0 : charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type);
402 :
403 0 : path_info.current_x = 0;
404 0 : path_info.current_y = 0;
405 : }
406 0 : path_info.data = data;
407 0 : path_info.type = type;
408 0 : if (emit_path) {
409 0 : status = _cairo_path_fixed_interpret (scaled_glyph->path,
410 : CAIRO_DIRECTION_FORWARD,
411 : _charstring_move_to,
412 : _charstring_line_to,
413 : _charstring_curve_to,
414 : _charstring_close_path,
415 : &path_info);
416 0 : if (unlikely (status))
417 0 : return status;
418 : }
419 :
420 0 : status = _cairo_array_grow_by (data, 1);
421 0 : if (unlikely (status))
422 0 : return status;
423 0 : charstring_encode_command (path_info.data, CHARSTRING_endchar);
424 :
425 0 : return CAIRO_STATUS_SUCCESS;
426 : }
427 :
428 : static cairo_int_status_t
429 0 : cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
430 : cairo_output_stream_t *encrypted_output)
431 : {
432 : cairo_status_t status;
433 0 : unsigned char zeros[] = { 0, 0, 0, 0 };
434 : cairo_array_t data;
435 : unsigned int i;
436 : int length;
437 :
438 0 : _cairo_array_init (&data, sizeof (unsigned char));
439 0 : status = _cairo_array_grow_by (&data, 1024);
440 0 : if (unlikely (status))
441 0 : goto fail;
442 :
443 0 : _cairo_output_stream_printf (encrypted_output,
444 : "2 index /CharStrings %d dict dup begin\n",
445 0 : font->scaled_font_subset->num_glyphs + 1);
446 :
447 0 : _cairo_scaled_font_freeze_cache (font->type1_scaled_font);
448 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
449 0 : _cairo_array_truncate (&data, 0);
450 : /* four "random" bytes required by encryption algorithm */
451 0 : status = _cairo_array_append_multiple (&data, zeros, 4);
452 0 : if (unlikely (status))
453 0 : break;
454 :
455 0 : status = cairo_type1_font_create_charstring (font, i,
456 0 : font->scaled_font_subset->glyphs[i],
457 : CAIRO_CHARSTRING_TYPE1,
458 : &data);
459 0 : if (unlikely (status))
460 0 : break;
461 :
462 0 : charstring_encrypt (&data);
463 0 : length = _cairo_array_num_elements (&data);
464 0 : if (font->scaled_font_subset->glyph_names != NULL) {
465 0 : _cairo_output_stream_printf (encrypted_output, "/%s %d RD ",
466 0 : font->scaled_font_subset->glyph_names[i],
467 : length);
468 0 : } else if (i == 0) {
469 0 : _cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
470 : } else {
471 0 : _cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length);
472 : }
473 0 : _cairo_output_stream_write (encrypted_output,
474 0 : _cairo_array_index (&data, 0),
475 : length);
476 0 : _cairo_output_stream_printf (encrypted_output, " ND\n");
477 : }
478 0 : _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
479 :
480 : fail:
481 0 : _cairo_array_fini (&data);
482 0 : return status;
483 : }
484 :
485 : static void
486 0 : cairo_type1_font_write_header (cairo_type1_font_t *font,
487 : const char *name)
488 : {
489 : unsigned int i;
490 0 : const char spaces[50] = " ";
491 :
492 0 : _cairo_output_stream_printf (font->output,
493 : "%%!FontType1-1.1 %s 1.0\n"
494 : "11 dict begin\n"
495 : "/FontName /%s def\n"
496 : "/PaintType 0 def\n"
497 : "/FontType 1 def\n"
498 : "/FontMatrix [0.001 0 0 0.001 0 0] readonly def\n",
499 : name,
500 : name);
501 :
502 : /* We don't know the bbox values until after the charstrings have
503 : * been generated. Reserve some space and fill in the bbox
504 : * later. */
505 :
506 : /* Worst case for four signed ints with spaces between each number */
507 0 : font->bbox_max_chars = 50;
508 :
509 0 : _cairo_output_stream_printf (font->output, "/FontBBox {");
510 0 : font->bbox_position = _cairo_output_stream_get_position (font->output);
511 0 : _cairo_output_stream_write (font->output, spaces, font->bbox_max_chars);
512 :
513 0 : _cairo_output_stream_printf (font->output,
514 : "} readonly def\n"
515 : "/Encoding 256 array\n"
516 : "0 1 255 {1 index exch /.notdef put} for\n");
517 0 : for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
518 0 : if (font->scaled_font_subset->glyph_names != NULL) {
519 0 : _cairo_output_stream_printf (font->output, "dup %d /%s put\n",
520 0 : i, font->scaled_font_subset->glyph_names[i]);
521 : } else {
522 0 : _cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, i);
523 : }
524 : }
525 0 : _cairo_output_stream_printf (font->output,
526 : "readonly def\n"
527 : "currentdict end\n"
528 : "currentfile eexec\n");
529 0 : }
530 :
531 : static cairo_status_t
532 0 : cairo_type1_write_stream_encrypted (void *closure,
533 : const unsigned char *data,
534 : unsigned int length)
535 : {
536 : const unsigned char *in, *end;
537 : uint16_t c, p;
538 : static const char hex_digits[16] = "0123456789abcdef";
539 : char digits[3];
540 0 : cairo_type1_font_t *font = closure;
541 :
542 0 : in = (const unsigned char *) data;
543 0 : end = (const unsigned char *) data + length;
544 0 : while (in < end) {
545 0 : p = *in++;
546 0 : c = p ^ (font->eexec_key >> 8);
547 0 : font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
548 :
549 0 : if (font->hex_encode) {
550 0 : digits[0] = hex_digits[c >> 4];
551 0 : digits[1] = hex_digits[c & 0x0f];
552 0 : digits[2] = '\n';
553 0 : font->hex_column += 2;
554 :
555 0 : if (font->hex_column == 78) {
556 0 : _cairo_output_stream_write (font->output, digits, 3);
557 0 : font->hex_column = 0;
558 : } else {
559 0 : _cairo_output_stream_write (font->output, digits, 2);
560 : }
561 : } else {
562 0 : digits[0] = c;
563 0 : _cairo_output_stream_write (font->output, digits, 1);
564 : }
565 : }
566 :
567 0 : return CAIRO_STATUS_SUCCESS;
568 : }
569 :
570 : static cairo_int_status_t
571 0 : cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
572 : const char *name)
573 : {
574 : cairo_int_status_t status;
575 : cairo_status_t status2;
576 : cairo_output_stream_t *encrypted_output;
577 :
578 0 : font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
579 0 : font->hex_column = 0;
580 0 : encrypted_output = _cairo_output_stream_create (
581 : cairo_type1_write_stream_encrypted,
582 : NULL,
583 : font);
584 0 : if (_cairo_output_stream_get_status (encrypted_output))
585 0 : return _cairo_output_stream_destroy (encrypted_output);
586 :
587 : /* Note: the first four spaces at the start of this private dict
588 : * are the four "random" bytes of plaintext required by the
589 : * encryption algorithm */
590 0 : _cairo_output_stream_printf (encrypted_output,
591 : " dup /Private 9 dict dup begin\n"
592 : "/RD {string currentfile exch readstring pop}"
593 : " bind executeonly def\n"
594 : "/ND {noaccess def} executeonly def\n"
595 : "/NP {noaccess put} executeonly def\n"
596 : "/BlueValues [] def\n"
597 : "/MinFeature {16 16} def\n"
598 : "/lenIV 4 def\n"
599 : "/password 5839 def\n");
600 :
601 0 : status = cairo_type1_font_write_charstrings (font, encrypted_output);
602 0 : if (unlikely (status))
603 0 : goto fail;
604 :
605 0 : _cairo_output_stream_printf (encrypted_output,
606 : "end\n"
607 : "end\n"
608 : "readonly put\n"
609 : "noaccess put\n"
610 : "dup /FontName get exch definefont pop\n"
611 : "mark currentfile closefile\n");
612 :
613 : fail:
614 0 : status2 = _cairo_output_stream_destroy (encrypted_output);
615 0 : if (status == CAIRO_STATUS_SUCCESS)
616 0 : status = status2;
617 :
618 0 : return status;
619 : }
620 :
621 : static void
622 0 : cairo_type1_font_write_trailer(cairo_type1_font_t *font)
623 : {
624 : int i;
625 : static const char zeros[65] =
626 : "0000000000000000000000000000000000000000000000000000000000000000\n";
627 :
628 0 : for (i = 0; i < 8; i++)
629 0 : _cairo_output_stream_write (font->output, zeros, sizeof zeros);
630 :
631 0 : _cairo_output_stream_printf (font->output, "cleartomark\n");
632 0 : }
633 :
634 : static cairo_status_t
635 0 : cairo_type1_write_stream (void *closure,
636 : const unsigned char *data,
637 : unsigned int length)
638 : {
639 0 : cairo_type1_font_t *font = closure;
640 :
641 0 : return _cairo_array_append_multiple (&font->contents, data, length);
642 : }
643 :
644 : static cairo_int_status_t
645 0 : cairo_type1_font_write (cairo_type1_font_t *font,
646 : const char *name)
647 : {
648 : cairo_int_status_t status;
649 :
650 0 : cairo_type1_font_write_header (font, name);
651 0 : font->header_size = _cairo_output_stream_get_position (font->output);
652 :
653 0 : status = cairo_type1_font_write_private_dict (font, name);
654 0 : if (unlikely (status))
655 0 : return status;
656 :
657 0 : font->data_size = _cairo_output_stream_get_position (font->output) -
658 0 : font->header_size;
659 :
660 0 : cairo_type1_font_write_trailer (font);
661 0 : font->trailer_size =
662 0 : _cairo_output_stream_get_position (font->output) -
663 0 : font->header_size - font->data_size;
664 :
665 0 : return CAIRO_STATUS_SUCCESS;
666 : }
667 :
668 : static cairo_int_status_t
669 0 : cairo_type1_font_generate (cairo_type1_font_t *font, const char *name)
670 : {
671 : cairo_int_status_t status;
672 :
673 0 : status = _cairo_array_grow_by (&font->contents, 4096);
674 0 : if (unlikely (status))
675 0 : return status;
676 :
677 0 : font->output = _cairo_output_stream_create (cairo_type1_write_stream, NULL, font);
678 0 : if (_cairo_output_stream_get_status (font->output))
679 0 : return _cairo_output_stream_destroy (font->output);
680 :
681 0 : status = cairo_type1_font_write (font, name);
682 0 : if (unlikely (status))
683 0 : return status;
684 :
685 0 : font->data = _cairo_array_index (&font->contents, 0);
686 :
687 0 : return CAIRO_STATUS_SUCCESS;
688 : }
689 :
690 : static cairo_status_t
691 0 : cairo_type1_font_destroy (cairo_type1_font_t *font)
692 : {
693 0 : cairo_status_t status = CAIRO_STATUS_SUCCESS;
694 :
695 0 : free (font->widths);
696 0 : cairo_scaled_font_destroy (font->type1_scaled_font);
697 0 : _cairo_array_fini (&font->contents);
698 0 : if (font->output)
699 0 : status = _cairo_output_stream_destroy (font->output);
700 0 : free (font);
701 :
702 0 : return status;
703 : }
704 :
705 : static cairo_status_t
706 0 : _cairo_type1_fallback_init_internal (cairo_type1_subset_t *type1_subset,
707 : const char *name,
708 : cairo_scaled_font_subset_t *scaled_font_subset,
709 : cairo_bool_t hex_encode)
710 : {
711 : cairo_type1_font_t *font;
712 : cairo_status_t status;
713 : unsigned long length;
714 : unsigned int i, len;
715 :
716 0 : status = cairo_type1_font_create (scaled_font_subset, &font, hex_encode);
717 0 : if (unlikely (status))
718 0 : return status;
719 :
720 0 : status = cairo_type1_font_generate (font, name);
721 0 : if (unlikely (status))
722 0 : goto fail1;
723 :
724 0 : type1_subset->base_font = strdup (name);
725 0 : if (unlikely (type1_subset->base_font == NULL)) {
726 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
727 0 : goto fail1;
728 : }
729 :
730 0 : type1_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
731 0 : if (unlikely (type1_subset->widths == NULL)) {
732 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
733 0 : goto fail2;
734 : }
735 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
736 0 : type1_subset->widths[i] = (double)font->widths[i]/1000;
737 :
738 0 : type1_subset->x_min = (double)font->x_min/1000;
739 0 : type1_subset->y_min = (double)font->y_min/1000;
740 0 : type1_subset->x_max = (double)font->x_max/1000;
741 0 : type1_subset->y_max = (double)font->y_max/1000;
742 0 : type1_subset->ascent = (double)font->y_max/1000;
743 0 : type1_subset->descent = (double)font->y_min/1000;
744 :
745 0 : length = font->header_size + font->data_size +
746 0 : font->trailer_size;
747 0 : type1_subset->data = malloc (length);
748 0 : if (unlikely (type1_subset->data == NULL)) {
749 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
750 0 : goto fail3;
751 : }
752 0 : memcpy (type1_subset->data,
753 0 : _cairo_array_index (&font->contents, 0), length);
754 :
755 0 : len = snprintf(type1_subset->data + font->bbox_position,
756 0 : font->bbox_max_chars,
757 : "%d %d %d %d",
758 0 : (int)type1_subset->x_min,
759 0 : (int)type1_subset->y_min,
760 0 : (int)type1_subset->x_max,
761 0 : (int)type1_subset->y_max);
762 0 : type1_subset->data[font->bbox_position + len] = ' ';
763 :
764 0 : type1_subset->header_length = font->header_size;
765 0 : type1_subset->data_length = font->data_size;
766 0 : type1_subset->trailer_length = font->trailer_size;
767 :
768 0 : return cairo_type1_font_destroy (font);
769 :
770 : fail3:
771 0 : free (type1_subset->widths);
772 : fail2:
773 0 : free (type1_subset->base_font);
774 : fail1:
775 : /* status is already set, ignore further errors */
776 0 : cairo_type1_font_destroy (font);
777 :
778 0 : return status;
779 : }
780 :
781 : cairo_status_t
782 0 : _cairo_type1_fallback_init_binary (cairo_type1_subset_t *type1_subset,
783 : const char *name,
784 : cairo_scaled_font_subset_t *scaled_font_subset)
785 : {
786 0 : return _cairo_type1_fallback_init_internal (type1_subset,
787 : name,
788 : scaled_font_subset, FALSE);
789 : }
790 :
791 : cairo_status_t
792 0 : _cairo_type1_fallback_init_hex (cairo_type1_subset_t *type1_subset,
793 : const char *name,
794 : cairo_scaled_font_subset_t *scaled_font_subset)
795 : {
796 0 : return _cairo_type1_fallback_init_internal (type1_subset,
797 : name,
798 : scaled_font_subset, TRUE);
799 : }
800 :
801 : void
802 0 : _cairo_type1_fallback_fini (cairo_type1_subset_t *subset)
803 : {
804 0 : free (subset->base_font);
805 0 : free (subset->widths);
806 0 : free (subset->data);
807 0 : }
808 :
809 : cairo_status_t
810 0 : _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
811 : cairo_scaled_font_subset_t *scaled_font_subset)
812 : {
813 : cairo_type1_font_t *font;
814 : cairo_status_t status;
815 : unsigned int i;
816 : cairo_array_t charstring;
817 :
818 0 : status = cairo_type1_font_create (scaled_font_subset, &font, FALSE);
819 0 : if (unlikely (status))
820 0 : return status;
821 :
822 0 : _cairo_array_init (&type2_subset->charstrings, sizeof (cairo_array_t));
823 :
824 0 : type2_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
825 0 : if (unlikely (type2_subset->widths == NULL)) {
826 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
827 0 : goto fail1;
828 : }
829 :
830 0 : _cairo_scaled_font_freeze_cache (font->type1_scaled_font);
831 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
832 0 : _cairo_array_init (&charstring, sizeof (unsigned char));
833 0 : status = _cairo_array_grow_by (&charstring, 32);
834 0 : if (unlikely (status))
835 0 : goto fail2;
836 :
837 0 : status = cairo_type1_font_create_charstring (font, i,
838 0 : font->scaled_font_subset->glyphs[i],
839 : CAIRO_CHARSTRING_TYPE2,
840 : &charstring);
841 0 : if (unlikely (status))
842 0 : goto fail2;
843 :
844 0 : status = _cairo_array_append (&type2_subset->charstrings, &charstring);
845 0 : if (unlikely (status))
846 0 : goto fail2;
847 : }
848 0 : _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
849 :
850 0 : for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
851 0 : type2_subset->widths[i] = font->widths[i];
852 :
853 0 : type2_subset->x_min = (int) font->x_min;
854 0 : type2_subset->y_min = (int) font->y_min;
855 0 : type2_subset->x_max = (int) font->x_max;
856 0 : type2_subset->y_max = (int) font->y_max;
857 0 : type2_subset->ascent = (int) font->y_max;
858 0 : type2_subset->descent = (int) font->y_min;
859 :
860 0 : return cairo_type1_font_destroy (font);
861 :
862 : fail2:
863 0 : _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
864 0 : _cairo_array_fini (&charstring);
865 0 : _cairo_type2_charstrings_fini (type2_subset);
866 : fail1:
867 0 : cairo_type1_font_destroy (font);
868 0 : return status;
869 : }
870 :
871 : void
872 0 : _cairo_type2_charstrings_fini (cairo_type2_charstrings_t *type2_subset)
873 : {
874 : unsigned int i, num_charstrings;
875 : cairo_array_t *charstring;
876 :
877 0 : num_charstrings = _cairo_array_num_elements (&type2_subset->charstrings);
878 0 : for (i = 0; i < num_charstrings; i++) {
879 0 : charstring = _cairo_array_index (&type2_subset->charstrings, i);
880 0 : _cairo_array_fini (charstring);
881 : }
882 0 : _cairo_array_fini (&type2_subset->charstrings);
883 :
884 0 : free (type2_subset->widths);
885 0 : }
886 :
887 : #endif /* CAIRO_HAS_FONT_SUBSET */
|