Subversion Repositories Kolibri OS

Rev

Rev 1897 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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