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