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
cairo_type1_font_create(cairo_scaled_font_subset_t * scaled_font_subset,cairo_type1_font_t ** subset_return,cairo_bool_t hex_encode)77 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     font = calloc (1, sizeof (cairo_type1_font_t));
89     if (unlikely (font == NULL))
90 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
91 
92     font->widths = calloc (scaled_font_subset->num_glyphs, sizeof (int));
93     if (unlikely (font->widths == NULL)) {
94 	free (font);
95 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
96     }
97 
98     font->scaled_font_subset = scaled_font_subset;
99     font->hex_encode = hex_encode;
100 
101     font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
102 
103     cairo_matrix_init_scale (&font_matrix, 1000, -1000);
104     cairo_matrix_init_identity (&ctm);
105 
106     _cairo_font_options_init_default (&font_options);
107     cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
108     cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);
109 
110     font->type1_scaled_font = cairo_scaled_font_create (font_face,
111 							&font_matrix,
112 							&ctm,
113 							&font_options);
114     status = font->type1_scaled_font->status;
115     if (unlikely (status))
116         goto fail;
117 
118     _cairo_array_init (&font->contents, sizeof (unsigned char));
119     font->output = NULL;
120 
121     *subset_return = font;
122 
123     return CAIRO_STATUS_SUCCESS;
124 
125 fail:
126     free (font->widths);
127     free (font);
128 
129     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
charstring_encode_command(cairo_array_t * data,int command)146 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     unsigned char *p = buf;
152 
153     if (command & 0xff00)
154         *p++ = command >> 8;
155     *p++ = command & 0x00ff;
156 
157     /* Ensure the array doesn't grow, which allows this function to
158      * have no possibility of failure. */
159     orig_size = _cairo_array_size (data);
160     status = _cairo_array_append_multiple (data, buf, p - buf);
161 
162     assert (status == CAIRO_STATUS_SUCCESS);
163     assert (_cairo_array_size (data) == orig_size);
164 }
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
charstring_encode_integer(cairo_array_t * data,int i,cairo_charstring_type_t type)171 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     unsigned char *p = buf;
179 
180     if (i >= -107 && i <= 107) {
181         *p++ = i + 139;
182     } else if (i >= 108 && i <= 1131) {
183         i -= 108;
184         *p++ = (i >> 8)+ 247;
185         *p++ = i & 0xff;
186     } else if (i >= -1131 && i <= -108) {
187         i = -i - 108;
188         *p++ = (i >> 8)+ 251;
189         *p++ = i & 0xff;
190     } else {
191         if (type == CAIRO_CHARSTRING_TYPE1) {
192             *p++ = 0xff;
193             *p++ = i >> 24;
194             *p++ = (i >> 16) & 0xff;
195             *p++ = (i >> 8)  & 0xff;
196             *p++ = i & 0xff;
197         } else {
198             *p++ = 0xff;
199             *p++ = (i >> 8)  & 0xff;
200             *p++ = i & 0xff;
201             *p++ = 0;
202             *p++ = 0;
203         }
204     }
205 
206     /* Ensure the array doesn't grow, which allows this function to
207      * have no possibility of failure. */
208     orig_size = _cairo_array_size (data);
209     status = _cairo_array_append_multiple (data, buf, p - buf);
210 
211     assert (status == CAIRO_STATUS_SUCCESS);
212     assert (_cairo_array_size (data) == orig_size);
213 }
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
_charstring_move_to(void * closure,const cairo_point_t * point)222 _charstring_move_to (void		    *closure,
223                      const cairo_point_t    *point)
224 {
225     t1_path_info_t *path_info = (t1_path_info_t *) closure;
226     int dx, dy;
227     cairo_status_t status;
228 
229     status = _cairo_array_grow_by (path_info->data, 12);
230     if (unlikely (status))
231         return status;
232 
233     dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
234     dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
235     charstring_encode_integer (path_info->data, dx, path_info->type);
236     charstring_encode_integer (path_info->data, dy, path_info->type);
237     path_info->current_x += dx;
238     path_info->current_y += dy;
239 
240     charstring_encode_command (path_info->data, CHARSTRING_rmoveto);
241 
242     return CAIRO_STATUS_SUCCESS;
243 }
244 
245 static cairo_status_t
_charstring_line_to(void * closure,const cairo_point_t * point)246 _charstring_line_to (void		    *closure,
247                      const cairo_point_t    *point)
248 {
249     t1_path_info_t *path_info = (t1_path_info_t *) closure;
250     int dx, dy;
251     cairo_status_t status;
252 
253     status = _cairo_array_grow_by (path_info->data, 12);
254     if (unlikely (status))
255         return status;
256 
257     dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
258     dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
259     charstring_encode_integer (path_info->data, dx, path_info->type);
260     charstring_encode_integer (path_info->data, dy, path_info->type);
261     path_info->current_x += dx;
262     path_info->current_y += dy;
263 
264     charstring_encode_command (path_info->data, CHARSTRING_rlineto);
265 
266     return CAIRO_STATUS_SUCCESS;
267 }
268 
269 static cairo_status_t
_charstring_curve_to(void * closure,const cairo_point_t * point1,const cairo_point_t * point2,const cairo_point_t * point3)270 _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     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     status = _cairo_array_grow_by (path_info->data, 32);
280     if (unlikely (status))
281         return status;
282 
283     dx1 = _cairo_fixed_integer_part (point1->x) - path_info->current_x;
284     dy1 = _cairo_fixed_integer_part (point1->y) - path_info->current_y;
285     dx2 = _cairo_fixed_integer_part (point2->x) - path_info->current_x - dx1;
286     dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1;
287     dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2;
288     dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2;
289     charstring_encode_integer (path_info->data, dx1, path_info->type);
290     charstring_encode_integer (path_info->data, dy1, path_info->type);
291     charstring_encode_integer (path_info->data, dx2, path_info->type);
292     charstring_encode_integer (path_info->data, dy2, path_info->type);
293     charstring_encode_integer (path_info->data, dx3, path_info->type);
294     charstring_encode_integer (path_info->data, dy3, path_info->type);
295     path_info->current_x += dx1 + dx2 + dx3;
296     path_info->current_y += dy1 + dy2 + dy3;
297     charstring_encode_command (path_info->data, CHARSTRING_rcurveto);
298 
299     return CAIRO_STATUS_SUCCESS;
300 }
301 
302 static cairo_status_t
_charstring_close_path(void * closure)303 _charstring_close_path (void *closure)
304 {
305     cairo_status_t status;
306     t1_path_info_t *path_info = (t1_path_info_t *) closure;
307 
308     if (path_info->type == CAIRO_CHARSTRING_TYPE2)
309         return CAIRO_STATUS_SUCCESS;
310 
311     status = _cairo_array_grow_by (path_info->data, 2);
312     if (unlikely (status))
313 	return status;
314 
315     charstring_encode_command (path_info->data, CHARSTRING_closepath);
316 
317     return CAIRO_STATUS_SUCCESS;
318 }
319 
320 static void
charstring_encrypt(cairo_array_t * data)321 charstring_encrypt (cairo_array_t *data)
322 {
323     unsigned char *d, *end;
324     uint16_t c, p, r;
325 
326     r = CAIRO_TYPE1_CHARSTRING_KEY;
327     d = (unsigned char *) _cairo_array_index (data, 0);
328     end = d + _cairo_array_num_elements (data);
329     while (d < end) {
330 	p = *d;
331 	c = p ^ (r >> 8);
332 	r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
333         *d++ = c;
334     }
335 }
336 
337 static cairo_int_status_t
cairo_type1_font_create_charstring(cairo_type1_font_t * font,int subset_index,int glyph_index,cairo_charstring_type_t type,cairo_array_t * data)338 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     cairo_bool_t emit_path = TRUE;
349 
350     /* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */
351     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     if (glyph_index == 0 && status == CAIRO_INT_STATUS_UNSUPPORTED) {
360 	emit_path = FALSE;
361 	status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
362 					     glyph_index,
363 					     CAIRO_SCALED_GLYPH_INFO_METRICS,
364 					     &scaled_glyph);
365     }
366     if (unlikely (status))
367         return status;
368 
369     metrics = &scaled_glyph->metrics;
370     if (subset_index == 0) {
371         font->x_min = metrics->x_bearing;
372         font->y_min = metrics->y_bearing;
373         font->x_max = metrics->x_bearing + metrics->width;
374         font->y_max = metrics->y_bearing + metrics->height;
375     } else {
376         if (metrics->x_bearing < font->x_min)
377             font->x_min = metrics->x_bearing;
378         if (metrics->y_bearing < font->y_min)
379             font->y_min = metrics->y_bearing;
380         if (metrics->x_bearing + metrics->width > font->x_max)
381             font->x_max = metrics->x_bearing + metrics->width;
382         if (metrics->y_bearing + metrics->height > font->y_max)
383             font->y_max = metrics->y_bearing + metrics->height;
384     }
385     font->widths[subset_index] = metrics->x_advance;
386 
387     status = _cairo_array_grow_by (data, 30);
388     if (unlikely (status))
389         return status;
390 
391     if (type == CAIRO_CHARSTRING_TYPE1) {
392         charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing, type);
393         charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing, type);
394         charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type);
395         charstring_encode_integer (data, (int) scaled_glyph->metrics.y_advance, type);
396         charstring_encode_command (data, CHARSTRING_sbw);
397 
398         path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
399         path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
400     } else {
401         charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type);
402 
403         path_info.current_x = 0;
404         path_info.current_y = 0;
405     }
406     path_info.data = data;
407     path_info.type = type;
408     if (emit_path) {
409 	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 	if (unlikely (status))
417 	    return status;
418     }
419 
420     status = _cairo_array_grow_by (data, 1);
421     if (unlikely (status))
422         return status;
423     charstring_encode_command (path_info.data, CHARSTRING_endchar);
424 
425     return CAIRO_STATUS_SUCCESS;
426 }
427 
428 static cairo_int_status_t
cairo_type1_font_write_charstrings(cairo_type1_font_t * font,cairo_output_stream_t * encrypted_output)429 cairo_type1_font_write_charstrings (cairo_type1_font_t    *font,
430                                     cairo_output_stream_t *encrypted_output)
431 {
432     cairo_status_t status;
433     unsigned char zeros[] = { 0, 0, 0, 0 };
434     cairo_array_t data;
435     unsigned int i;
436     int length;
437 
438     _cairo_array_init (&data, sizeof (unsigned char));
439     status = _cairo_array_grow_by (&data, 1024);
440     if (unlikely (status))
441         goto fail;
442 
443     _cairo_output_stream_printf (encrypted_output,
444                                  "2 index /CharStrings %d dict dup begin\n",
445                                  font->scaled_font_subset->num_glyphs + 1);
446 
447     _cairo_scaled_font_freeze_cache (font->type1_scaled_font);
448     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
449         _cairo_array_truncate (&data, 0);
450         /* four "random" bytes required by encryption algorithm */
451         status = _cairo_array_append_multiple (&data, zeros, 4);
452         if (unlikely (status))
453 	    break;
454 
455         status = cairo_type1_font_create_charstring (font, i,
456 						     font->scaled_font_subset->glyphs[i],
457                                                      CAIRO_CHARSTRING_TYPE1,
458 						     &data);
459         if (unlikely (status))
460 	    break;
461 
462         charstring_encrypt (&data);
463         length = _cairo_array_num_elements (&data);
464 	if (font->scaled_font_subset->glyph_names != NULL) {
465 	    _cairo_output_stream_printf (encrypted_output, "/%s %d RD ",
466 					 font->scaled_font_subset->glyph_names[i],
467 					 length);
468 	} else if (i == 0) {
469 	    _cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
470 	} else {
471 	    _cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length);
472 	}
473         _cairo_output_stream_write (encrypted_output,
474                                     _cairo_array_index (&data, 0),
475                                     length);
476         _cairo_output_stream_printf (encrypted_output, " ND\n");
477     }
478     _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
479 
480 fail:
481     _cairo_array_fini (&data);
482     return status;
483 }
484 
485 static void
cairo_type1_font_write_header(cairo_type1_font_t * font,const char * name)486 cairo_type1_font_write_header (cairo_type1_font_t *font,
487                                const char         *name)
488 {
489     unsigned int i;
490     const char spaces[50] = "                                                  ";
491 
492     _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     font->bbox_max_chars = 50;
508 
509     _cairo_output_stream_printf (font->output, "/FontBBox {");
510     font->bbox_position = _cairo_output_stream_get_position (font->output);
511     _cairo_output_stream_write (font->output, spaces, font->bbox_max_chars);
512 
513     _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     for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
518 	if (font->scaled_font_subset->glyph_names != NULL) {
519 	    _cairo_output_stream_printf (font->output, "dup %d /%s put\n",
520 					 i, font->scaled_font_subset->glyph_names[i]);
521 	} else {
522 	    _cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, i);
523 	}
524     }
525     _cairo_output_stream_printf (font->output,
526                                  "readonly def\n"
527                                  "currentdict end\n"
528                                  "currentfile eexec\n");
529 }
530 
531 static cairo_status_t
cairo_type1_write_stream_encrypted(void * closure,const unsigned char * data,unsigned int length)532 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     cairo_type1_font_t *font = closure;
541 
542     in = (const unsigned char *) data;
543     end = (const unsigned char *) data + length;
544     while (in < end) {
545 	p = *in++;
546 	c = p ^ (font->eexec_key >> 8);
547 	font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
548 
549 	if (font->hex_encode) {
550 	    digits[0] = hex_digits[c >> 4];
551 	    digits[1] = hex_digits[c & 0x0f];
552 	    digits[2] = '\n';
553 	    font->hex_column += 2;
554 
555 	    if (font->hex_column == 78) {
556 		_cairo_output_stream_write (font->output, digits, 3);
557 		font->hex_column = 0;
558 	    } else {
559 		_cairo_output_stream_write (font->output, digits, 2);
560 	    }
561 	} else {
562 	    digits[0] = c;
563 	    _cairo_output_stream_write (font->output, digits, 1);
564 	}
565     }
566 
567     return CAIRO_STATUS_SUCCESS;
568 }
569 
570 static cairo_int_status_t
cairo_type1_font_write_private_dict(cairo_type1_font_t * font,const char * name)571 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     font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
579     font->hex_column = 0;
580     encrypted_output = _cairo_output_stream_create (
581         cairo_type1_write_stream_encrypted,
582         NULL,
583         font);
584     if (_cairo_output_stream_get_status (encrypted_output))
585 	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     _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     status = cairo_type1_font_write_charstrings (font, encrypted_output);
602     if (unlikely (status))
603 	goto fail;
604 
605     _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     status2 = _cairo_output_stream_destroy (encrypted_output);
615     if (status == CAIRO_STATUS_SUCCESS)
616 	status = status2;
617 
618     return status;
619 }
620 
621 static void
cairo_type1_font_write_trailer(cairo_type1_font_t * font)622 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     for (i = 0; i < 8; i++)
629 	_cairo_output_stream_write (font->output, zeros, sizeof zeros);
630 
631     _cairo_output_stream_printf (font->output, "cleartomark\n");
632 }
633 
634 static cairo_status_t
cairo_type1_write_stream(void * closure,const unsigned char * data,unsigned int length)635 cairo_type1_write_stream (void *closure,
636                          const unsigned char *data,
637                          unsigned int length)
638 {
639     cairo_type1_font_t *font = closure;
640 
641     return _cairo_array_append_multiple (&font->contents, data, length);
642 }
643 
644 static cairo_int_status_t
cairo_type1_font_write(cairo_type1_font_t * font,const char * name)645 cairo_type1_font_write (cairo_type1_font_t *font,
646                         const char *name)
647 {
648     cairo_int_status_t status;
649 
650     cairo_type1_font_write_header (font, name);
651     font->header_size = _cairo_output_stream_get_position (font->output);
652 
653     status = cairo_type1_font_write_private_dict (font, name);
654     if (unlikely (status))
655 	return status;
656 
657     font->data_size = _cairo_output_stream_get_position (font->output) -
658 	font->header_size;
659 
660     cairo_type1_font_write_trailer (font);
661     font->trailer_size =
662 	_cairo_output_stream_get_position (font->output) -
663 	font->header_size - font->data_size;
664 
665     return CAIRO_STATUS_SUCCESS;
666 }
667 
668 static cairo_int_status_t
cairo_type1_font_generate(cairo_type1_font_t * font,const char * name)669 cairo_type1_font_generate (cairo_type1_font_t *font, const char *name)
670 {
671     cairo_int_status_t status;
672 
673     status = _cairo_array_grow_by (&font->contents, 4096);
674     if (unlikely (status))
675 	return status;
676 
677     font->output = _cairo_output_stream_create (cairo_type1_write_stream, NULL, font);
678     if (_cairo_output_stream_get_status (font->output))
679 	return _cairo_output_stream_destroy (font->output);
680 
681     status = cairo_type1_font_write (font, name);
682     if (unlikely (status))
683 	return status;
684 
685     font->data = _cairo_array_index (&font->contents, 0);
686 
687     return CAIRO_STATUS_SUCCESS;
688 }
689 
690 static cairo_status_t
cairo_type1_font_destroy(cairo_type1_font_t * font)691 cairo_type1_font_destroy (cairo_type1_font_t *font)
692 {
693     cairo_status_t status = CAIRO_STATUS_SUCCESS;
694 
695     free (font->widths);
696     cairo_scaled_font_destroy (font->type1_scaled_font);
697     _cairo_array_fini (&font->contents);
698     if (font->output)
699 	status = _cairo_output_stream_destroy (font->output);
700     free (font);
701 
702     return status;
703 }
704 
705 static cairo_status_t
_cairo_type1_fallback_init_internal(cairo_type1_subset_t * type1_subset,const char * name,cairo_scaled_font_subset_t * scaled_font_subset,cairo_bool_t hex_encode)706 _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     status = cairo_type1_font_create (scaled_font_subset, &font, hex_encode);
717     if (unlikely (status))
718 	return status;
719 
720     status = cairo_type1_font_generate (font, name);
721     if (unlikely (status))
722 	goto fail1;
723 
724     type1_subset->base_font = strdup (name);
725     if (unlikely (type1_subset->base_font == NULL)) {
726         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
727         goto fail1;
728     }
729 
730     type1_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
731     if (unlikely (type1_subset->widths == NULL)) {
732         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
733         goto fail2;
734     }
735     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
736 	type1_subset->widths[i] = (double)font->widths[i]/1000;
737 
738     type1_subset->x_min   = (double)font->x_min/1000;
739     type1_subset->y_min   = (double)font->y_min/1000;
740     type1_subset->x_max   = (double)font->x_max/1000;
741     type1_subset->y_max   = (double)font->y_max/1000;
742     type1_subset->ascent  = (double)font->y_max/1000;
743     type1_subset->descent = (double)font->y_min/1000;
744 
745     length = font->header_size + font->data_size +
746 	font->trailer_size;
747     type1_subset->data = malloc (length);
748     if (unlikely (type1_subset->data == NULL)) {
749         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
750 	goto fail3;
751     }
752     memcpy (type1_subset->data,
753 	    _cairo_array_index (&font->contents, 0), length);
754 
755     len = snprintf(type1_subset->data + font->bbox_position,
756                    font->bbox_max_chars,
757                    "%d %d %d %d",
758                    (int)type1_subset->x_min,
759                    (int)type1_subset->y_min,
760                    (int)type1_subset->x_max,
761                    (int)type1_subset->y_max);
762     type1_subset->data[font->bbox_position + len] = ' ';
763 
764     type1_subset->header_length = font->header_size;
765     type1_subset->data_length = font->data_size;
766     type1_subset->trailer_length = font->trailer_size;
767 
768     return cairo_type1_font_destroy (font);
769 
770  fail3:
771     free (type1_subset->widths);
772  fail2:
773     free (type1_subset->base_font);
774  fail1:
775     /* status is already set, ignore further errors */
776     cairo_type1_font_destroy (font);
777 
778     return status;
779 }
780 
781 cairo_status_t
_cairo_type1_fallback_init_binary(cairo_type1_subset_t * type1_subset,const char * name,cairo_scaled_font_subset_t * scaled_font_subset)782 _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     return _cairo_type1_fallback_init_internal (type1_subset,
787                                                 name,
788                                                 scaled_font_subset, FALSE);
789 }
790 
791 cairo_status_t
_cairo_type1_fallback_init_hex(cairo_type1_subset_t * type1_subset,const char * name,cairo_scaled_font_subset_t * scaled_font_subset)792 _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     return _cairo_type1_fallback_init_internal (type1_subset,
797                                                 name,
798                                                 scaled_font_subset, TRUE);
799 }
800 
801 void
_cairo_type1_fallback_fini(cairo_type1_subset_t * subset)802 _cairo_type1_fallback_fini (cairo_type1_subset_t *subset)
803 {
804     free (subset->base_font);
805     free (subset->widths);
806     free (subset->data);
807 }
808 
809 cairo_status_t
_cairo_type2_charstrings_init(cairo_type2_charstrings_t * type2_subset,cairo_scaled_font_subset_t * scaled_font_subset)810 _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     status = cairo_type1_font_create (scaled_font_subset, &font, FALSE);
819     if (unlikely (status))
820 	return status;
821 
822     _cairo_array_init (&type2_subset->charstrings, sizeof (cairo_array_t));
823 
824     type2_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
825     if (unlikely (type2_subset->widths == NULL)) {
826         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
827         goto fail1;
828     }
829 
830     _cairo_scaled_font_freeze_cache (font->type1_scaled_font);
831     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
832         _cairo_array_init (&charstring, sizeof (unsigned char));
833         status = _cairo_array_grow_by (&charstring, 32);
834         if (unlikely (status))
835             goto fail2;
836 
837 	status = cairo_type1_font_create_charstring (font, i,
838 						     font->scaled_font_subset->glyphs[i],
839 						     CAIRO_CHARSTRING_TYPE2,
840 						     &charstring);
841         if (unlikely (status))
842             goto fail2;
843 
844         status = _cairo_array_append (&type2_subset->charstrings, &charstring);
845         if (unlikely (status))
846             goto fail2;
847     }
848     _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
849 
850     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
851 	type2_subset->widths[i] = font->widths[i];
852 
853     type2_subset->x_min   = (int) font->x_min;
854     type2_subset->y_min   = (int) font->y_min;
855     type2_subset->x_max   = (int) font->x_max;
856     type2_subset->y_max   = (int) font->y_max;
857     type2_subset->ascent  = (int) font->y_max;
858     type2_subset->descent = (int) font->y_min;
859 
860     return cairo_type1_font_destroy (font);
861 
862 fail2:
863     _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
864     _cairo_array_fini (&charstring);
865     _cairo_type2_charstrings_fini (type2_subset);
866 fail1:
867     cairo_type1_font_destroy (font);
868     return status;
869 }
870 
871 void
_cairo_type2_charstrings_fini(cairo_type2_charstrings_t * type2_subset)872 _cairo_type2_charstrings_fini (cairo_type2_charstrings_t *type2_subset)
873 {
874     unsigned int i, num_charstrings;
875     cairo_array_t *charstring;
876 
877     num_charstrings = _cairo_array_num_elements (&type2_subset->charstrings);
878     for (i = 0; i < num_charstrings; i++) {
879         charstring = _cairo_array_index (&type2_subset->charstrings, i);
880         _cairo_array_fini (charstring);
881     }
882     _cairo_array_fini (&type2_subset->charstrings);
883 
884     free (type2_subset->widths);
885 }
886 
887 #endif /* CAIRO_HAS_FONT_SUBSET */
888