1
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2006 Red Hat, Inc
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it either under the terms of the GNU Lesser General Public
8
 * License version 2.1 as published by the Free Software Foundation
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
11
 * notice, a recipient may use your version of this file under either
12
 * the MPL or the LGPL.
13
 *
14
 * You should have received a copy of the LGPL along with this library
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17
 * You should have received a copy of the MPL along with this library
18
 * in the file COPYING-MPL-1.1
19
 *
20
 * The contents of this file are subject to the Mozilla Public License
21
 * Version 1.1 (the "License"); you may not use this file except in
22
 * compliance with the License. You may obtain a copy of the License at
23
 * http://www.mozilla.org/MPL/
24
 *
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27
 * the specific language governing rights and limitations.
28
 *
29
 * The Original Code is the cairo graphics library.
30
 *
31
 * The Initial Developer of the Original Code is Red Hat, Inc.
32
 *
33
 * Contributor(s):
34
 *	Kristian Høgsberg <krh@redhat.com>
35
 */
36

            
37
/*
38
 * Useful links:
39
 * http://partners.adobe.com/public/developer/en/font/T1_SPEC.PDF
40
 */
41

            
42

            
43
#define _DEFAULT_SOURCE /* for snprintf(), strdup() */
44
#include "cairoint.h"
45

            
46
#include "cairo-array-private.h"
47
#include "cairo-error-private.h"
48

            
49
#if CAIRO_HAS_FONT_SUBSET
50

            
51
#include "cairo-type1-private.h"
52
#include "cairo-scaled-font-subsets-private.h"
53
#include "cairo-output-stream-private.h"
54

            
55
#include <ctype.h>
56

            
57
#define TYPE1_STACKSIZE 24 /* Defined in Type 1 Font Format */
58

            
59

            
60
typedef struct {
61
    int subset_index;
62
    double width;
63
    const char *encrypted_charstring;
64
    int encrypted_charstring_length;
65
} glyph_data_t;
66

            
67
typedef struct _cairo_type1_font_subset {
68
    cairo_scaled_font_subset_t *scaled_font_subset;
69

            
70
    struct {
71
	unsigned int font_id;
72
	char *base_font;
73
	unsigned int num_glyphs; /* Num /CharStrings in font */
74
	double x_min, y_min, x_max, y_max;
75
	double ascent, descent;
76
	double units_per_em;
77

            
78
	const char    *data;
79
	unsigned long  header_size;
80
	unsigned long  data_size;
81
	unsigned long  trailer_size;
82
    } base;
83

            
84
    /* Num glyphs in subset. May be greater than
85
     * scaled_font_subset->num_glyphs due to glyphs required by the
86
     * SEAC operator. */
87
    int num_glyphs;
88

            
89
    /* The glyphs and glyph_names arrays are indexed by the order of
90
     * the Charstrings in the font. This is not necessarily the same
91
     * order as the glyph index. The index_to_glyph_name() font backend
92
     * function is used to map the glyph index to the glyph order in
93
     * the Charstrings. */
94

            
95
    cairo_array_t glyphs_array;
96
    glyph_data_t *glyphs; /* pointer to first element of above array */
97
    cairo_array_t glyph_names_array;
98
    char **glyph_names; /* pointer to first element of above array */
99

            
100
    int num_subrs; /* Num /Subrs routines in the font */
101
    cairo_bool_t subset_subrs;
102
    struct {
103
	const char *subr_string;
104
	int subr_length;
105
	const char *np;
106
	int np_length;
107
	cairo_bool_t used;
108
    } *subrs; /* array with num_subrs elements */
109

            
110
    /* Maps scaled_font_subset index to glyphs_array.
111
     * Array size = scaled_font_subset->num_glyphs. */
112
    int *scaled_subset_index_to_glyphs;
113

            
114
    /* Keeps track of the glyphs that will be emitted in the subset.
115
     * Allocated size = base.num_glyphs. Number of entries = num_glyphs.
116
     * Array values are glyph_array indexes.
117
     */
118
    int *type1_subset_index_to_glyphs;
119

            
120
    cairo_output_stream_t *output;
121
    cairo_array_t contents;
122

            
123
    const char *rd, *nd, *np;
124

            
125
    int lenIV;
126

            
127
    char *type1_data;
128
    unsigned int type1_length;
129
    char *type1_end;
130

            
131
    char *header_segment;
132
    unsigned int header_segment_size;
133
    char *eexec_segment;
134
    unsigned int eexec_segment_size;
135
    cairo_bool_t eexec_segment_is_ascii;
136

            
137
    char *cleartext;
138
    char *cleartext_end;
139

            
140
    unsigned int header_size;
141

            
142
    unsigned short eexec_key;
143
    cairo_bool_t hex_encode;
144
    int hex_column;
145

            
146
    struct {
147
	double stack[TYPE1_STACKSIZE];
148
	int sp;
149
    } build_stack;
150

            
151
    struct {
152
	int stack[TYPE1_STACKSIZE];
153
	int sp;
154
    } ps_stack;
155

            
156

            
157
} cairo_type1_font_subset_t;
158

            
159

            
160
static cairo_status_t
161
_cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
162
			       cairo_scaled_font_subset_t *scaled_font_subset,
163
			       cairo_bool_t                hex_encode)
164
{
165
    memset (font, 0, sizeof (*font));
166
    font->scaled_font_subset = scaled_font_subset;
167

            
168
    _cairo_array_init (&font->glyphs_array, sizeof (glyph_data_t));
169
    _cairo_array_init (&font->glyph_names_array, sizeof (char *));
170
    font->scaled_subset_index_to_glyphs = _cairo_calloc_ab (scaled_font_subset->num_glyphs,
171
							    sizeof font->scaled_subset_index_to_glyphs[0]);
172
    if (unlikely (font->scaled_subset_index_to_glyphs == NULL))
173
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
174

            
175

            
176
    font->type1_subset_index_to_glyphs = NULL;
177
    font->base.num_glyphs = 0;
178
    font->num_subrs = 0;
179
    font->subset_subrs = TRUE;
180
    font->subrs = NULL;
181

            
182
    font->hex_encode = hex_encode;
183
    font->num_glyphs = 0;
184

            
185
    _cairo_array_init (&font->contents, sizeof (char));
186

            
187
    return CAIRO_STATUS_SUCCESS;
188
}
189

            
190
static void
191
cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph)
192
{
193
    if (font->glyphs[glyph].subset_index >= 0)
194
	return;
195

            
196
    font->glyphs[glyph].subset_index = font->num_glyphs;
197
    font->type1_subset_index_to_glyphs[font->num_glyphs] = glyph;
198
    font->num_glyphs++;
199
}
200

            
201
static cairo_bool_t
202
is_ps_delimiter(int c)
203
{
204
    static const char delimiters[] = "()[]{}<>/% \t\r\n";
205

            
206
    return strchr (delimiters, c) != NULL;
207
}
208

            
209
static const char *
210
find_token (const char *buffer, const char *end, const char *token)
211
{
212
    int i, length;
213
    /* FIXME: find substring really must be find_token */
214

            
215
    if (buffer == NULL)
216
	return NULL;
217

            
218
    length = strlen (token);
219
    for (i = 0; buffer + i < end - length + 1; i++)
220
	if (memcmp (buffer + i, token, length) == 0)
221
	    if ((i == 0 || token[0] == '/' || is_ps_delimiter(buffer[i - 1])) &&
222
		(buffer + i == end - length || is_ps_delimiter(buffer[i + length])))
223
		return buffer + i;
224

            
225
    return NULL;
226
}
227

            
228
static cairo_status_t
229
cairo_type1_font_subset_find_segments (cairo_type1_font_subset_t *font)
230
{
231
    unsigned char *p;
232
    const char *eexec_token;
233
    unsigned int size, i;
234

            
235
    p = (unsigned char *) font->type1_data;
236
    font->type1_end = font->type1_data + font->type1_length;
237
    if (font->type1_length >= 2 && p[0] == 0x80 && p[1] == 0x01) {
238
	if (font->type1_end < (char *)(p + 6))
239
	    return CAIRO_INT_STATUS_UNSUPPORTED;
240
	font->header_segment_size =
241
	    p[2] | (p[3] << 8) | (p[4] << 16) | ((unsigned int) p[5] << 24);
242
	font->header_segment = (char *) p + 6;
243

            
244
	p += 6 + font->header_segment_size;
245
	if (font->type1_end < (char *)(p + 6))
246
	    return CAIRO_INT_STATUS_UNSUPPORTED;
247
	font->eexec_segment_size =
248
	    p[2] | (p[3] << 8) | (p[4] << 16) | ((unsigned int) p[5] << 24);
249
	font->eexec_segment = (char *) p + 6;
250
	font->eexec_segment_is_ascii = (p[1] == 1);
251

            
252
        p += 6 + font->eexec_segment_size;
253
	while (font->type1_end >= (char *)(p + 6) && p[1] != 0x03) {
254
	    size = p[2] | (p[3] << 8) | (p[4] << 16) | ((unsigned int) p[5] << 24);
255
	    if (font->type1_end < (char *)(p + 6 + size))
256
		return CAIRO_INT_STATUS_UNSUPPORTED;
257
	    p += 6 + size;
258
        }
259
        font->type1_end = (char *) p;
260
    } else {
261
	eexec_token = find_token ((char *) p, font->type1_end, "eexec");
262
	if (eexec_token == NULL)
263
	    return CAIRO_INT_STATUS_UNSUPPORTED;
264

            
265
	font->header_segment_size = eexec_token - (char *) p + strlen ("eexec\n");
266
	font->header_segment = (char *) p;
267
	font->eexec_segment_size = font->type1_length - font->header_segment_size;
268
	font->eexec_segment = (char *) p + font->header_segment_size;
269
	font->eexec_segment_is_ascii = TRUE;
270
	for (i = 0; i < 4; i++) {
271
	    if (!_cairo_isxdigit (font->eexec_segment[i]))
272
		font->eexec_segment_is_ascii = FALSE;
273
	}
274
    }
275

            
276
    return CAIRO_STATUS_SUCCESS;
277
}
278

            
279
/* Search for the definition of key and erase it by overwriting with spaces.
280
 * This function is looks for definitions of the form:
281
 *
282
 * /key1 1234 def
283
 * /key2 [12 34 56] def
284
 *
285
 * ie a key defined as an integer or array of integers.
286
 *
287
 */
288
static void
289
cairo_type1_font_erase_dict_key (cairo_type1_font_subset_t *font,
290
				 const char *key)
291
{
292
    const char *start, *p, *segment_end;
293

            
294
    segment_end = font->header_segment + font->header_segment_size;
295

            
296
    start = font->header_segment;
297
    do {
298
	start = find_token (start, segment_end, key);
299
	if (start) {
300
	    p = start + strlen(key);
301
	    /* skip integers or array of integers */
302
	    while (p < segment_end &&
303
		   (_cairo_isspace(*p) ||
304
		    _cairo_isdigit(*p) ||
305
		    *p == '[' ||
306
		    *p == ']'))
307
	    {
308
		p++;
309
	    }
310

            
311
	    if (p + 3 < segment_end && memcmp(p, "def", 3) == 0) {
312
		/* erase definition of the key */
313
		memset((char *) start, ' ', p + 3 - start);
314
	    }
315
	    start += strlen(key);
316
	}
317
    } while (start);
318
}
319

            
320
static cairo_status_t
321
cairo_type1_font_subset_get_matrix (cairo_type1_font_subset_t *font,
322
				    const char                *name,
323
				    double                    *a,
324
				    double                    *b,
325
				    double                    *c,
326
				    double                    *d)
327
{
328
    const char *start, *end, *segment_end;
329
    int ret, s_max, i, j;
330
    char *s;
331
    const char *decimal_point;
332
    int decimal_point_len;
333

            
334
    decimal_point = _cairo_get_locale_decimal_point ();
335
    decimal_point_len = strlen (decimal_point);
336

            
337
    assert (decimal_point_len != 0);
338

            
339
    segment_end = font->header_segment + font->header_segment_size;
340
    start = find_token (font->header_segment, segment_end, name);
341
    if (start == NULL)
342
	return CAIRO_INT_STATUS_UNSUPPORTED;
343

            
344
    end = find_token (start, segment_end, "def");
345
    if (end == NULL)
346
	return CAIRO_INT_STATUS_UNSUPPORTED;
347

            
348
    s_max = end - start + 5*decimal_point_len + 1;
349
    s = _cairo_malloc (s_max);
350
    if (unlikely (s == NULL))
351
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
352

            
353
    i = 0;
354
    j = 0;
355
    while (i < end - start && j < s_max - decimal_point_len) {
356
	if (start[i] == '.') {
357
	    strncpy(s + j, decimal_point, decimal_point_len + 1);
358
	    i++;
359
	    j += decimal_point_len;
360
	} else {
361
	    s[j++] = start[i++];
362
	}
363
    }
364
    s[j] = 0;
365

            
366
    start = strpbrk (s, "{[");
367
    if (!start) {
368
	free (s);
369
	return CAIRO_INT_STATUS_UNSUPPORTED;
370
    }
371

            
372
    start++;
373
    ret = 0;
374
    if (*start)
375
	ret = sscanf(start, "%lf %lf %lf %lf", a, b, c, d);
376

            
377
    free (s);
378

            
379
    if (ret != 4)
380
	return CAIRO_INT_STATUS_UNSUPPORTED;
381

            
382
    return CAIRO_STATUS_SUCCESS;
383
}
384

            
385
static cairo_status_t
386
cairo_type1_font_subset_get_bbox (cairo_type1_font_subset_t *font)
387
{
388
    cairo_status_t status;
389
    double x_min, y_min, x_max, y_max;
390
    double xx, yx, xy, yy;
391

            
392
    status = cairo_type1_font_subset_get_matrix (font, "/FontBBox",
393
						 &x_min,
394
						 &y_min,
395
						 &x_max,
396
						 &y_max);
397
    if (unlikely (status))
398
	return status;
399

            
400
    status = cairo_type1_font_subset_get_matrix (font, "/FontMatrix",
401
						 &xx, &yx, &xy, &yy);
402
    if (unlikely (status))
403
	return status;
404

            
405
    if (yy == 0.0)
406
	return CAIRO_INT_STATUS_UNSUPPORTED;
407

            
408
    /* FreeType uses 1/yy to get units per EM */
409
    font->base.units_per_em = 1.0/yy;
410

            
411
    /* If the FontMatrix is not a uniform scale the metrics we extract
412
     * from the font won't match what FreeType returns */
413
    if (xx != yy || yx != 0.0 || xy != 0.0)
414
	return CAIRO_INT_STATUS_UNSUPPORTED;
415

            
416
    font->base.x_min = x_min / font->base.units_per_em;
417
    font->base.y_min = y_min / font->base.units_per_em;
418
    font->base.x_max = x_max / font->base.units_per_em;
419
    font->base.y_max = y_max / font->base.units_per_em;
420
    font->base.ascent = font->base.y_max;
421
    font->base.descent = font->base.y_min;
422

            
423
    return CAIRO_STATUS_SUCCESS;
424
}
425

            
426
static cairo_status_t
427
cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font)
428
{
429
    const char *start, *end, *segment_end;
430
    char *s;
431
    int i;
432
    cairo_status_t status;
433

            
434
    segment_end = font->header_segment + font->header_segment_size;
435
    start = find_token (font->header_segment, segment_end, "/FontName");
436
    if (start == NULL)
437
	return CAIRO_INT_STATUS_UNSUPPORTED;
438

            
439
    start += strlen ("/FontName");
440

            
441
    end = find_token (start, segment_end, "def");
442
    if (end == NULL)
443
	return CAIRO_INT_STATUS_UNSUPPORTED;
444

            
445
    while (end > start && _cairo_isspace(end[-1]))
446
	end--;
447

            
448
    s = _cairo_malloc (end - start + 1);
449
    if (unlikely (s == NULL))
450
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
451

            
452
    strncpy (s, start, end - start);
453
    s[end - start] = 0;
454

            
455
    start = strchr (s, '/');
456
    if (!start++ || !start) {
457
	free (s);
458
	return CAIRO_INT_STATUS_UNSUPPORTED;
459
    }
460

            
461
    /* If font name is prefixed with a subset tag, strip it off. */
462
    if (strlen(start) > 7 && start[6] == '+') {
463
	for (i = 0; i < 6; i++) {
464
	    if (start[i] < 'A' || start[i] > 'Z')
465
		break;
466
	}
467
	if (i == 6)
468
	    start += 7;
469
    }
470

            
471
    font->base.base_font = strdup (start);
472
    free (s);
473
    if (unlikely (font->base.base_font == NULL))
474
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
475

            
476
    status = _cairo_escape_ps_name (&font->base.base_font);
477

            
478
    return status;
479
}
480

            
481
static cairo_status_t
482
cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
483
					 const char *name)
484
{
485
    const char *start, *end, *segment_end;
486
    unsigned int i;
487
    int glyph;
488

            
489
    /* FIXME:
490
     * This function assumes that /FontName always appears
491
     * before /Encoding. This appears to always be the case with Type1
492
     * fonts.
493
     *
494
     * The more recently added code for removing the UniqueID and XUID
495
     * keys can not make any assumptions about the position of the
496
     * keys in the dictionary so it is implemented by overwriting the
497
     * key definition with spaces before we start copying the font to
498
     * the output.
499
     *
500
     * This code should be rewritten to not make any assumptions about
501
     * the order of dictionary keys. This will allow UniqueID to be
502
     * stripped out instead of leaving a bunch of spaces in the
503
     * output.
504
     */
505
    cairo_type1_font_erase_dict_key (font, "/UniqueID");
506
    cairo_type1_font_erase_dict_key (font, "/XUID");
507

            
508
    segment_end = font->header_segment + font->header_segment_size;
509

            
510
    /* Type 1 fonts created by Fontforge have some PostScript code at
511
     * the start of the font that skips the font if the printer has a
512
     * cached copy of the font with the same unique id. This breaks
513
     * our subsetted font so we disable it by searching for the
514
     * PostScript operator "known" when used to check for the
515
     * "/UniqueID" dictionary key. We append " pop false " after it to
516
     * pop the result of this check off the stack and replace it with
517
     * "false" to make the PostScript code think "/UniqueID" does not
518
     * exist.
519
     */
520
    end = font->header_segment;
521
    start = find_token (font->header_segment, segment_end, "/UniqueID");
522
    if (start) {
523
	start += 9;
524
	while (start < segment_end && _cairo_isspace (*start))
525
	    start++;
526
	if (start + 5 < segment_end && memcmp(start, "known", 5) == 0) {
527
	    _cairo_output_stream_write (font->output, font->header_segment,
528
					start + 5 - font->header_segment);
529
	    _cairo_output_stream_printf (font->output, " pop false ");
530
	    end = start + 5;
531
	}
532
    }
533

            
534
    start = find_token (end, segment_end, "/FontName");
535
    if (start == NULL)
536
	return CAIRO_INT_STATUS_UNSUPPORTED;
537

            
538
    _cairo_output_stream_write (font->output, end,
539
				start - end);
540

            
541
    _cairo_output_stream_printf (font->output, "/FontName /%s def", name);
542

            
543
    end = find_token (start, segment_end, "def");
544
    if (end == NULL)
545
	return CAIRO_INT_STATUS_UNSUPPORTED;
546
    end += 3;
547

            
548
    start = find_token (end, segment_end, "/Encoding");
549
    if (start == NULL)
550
	return CAIRO_INT_STATUS_UNSUPPORTED;
551
    _cairo_output_stream_write (font->output, end, start - end);
552

            
553
    _cairo_output_stream_printf (font->output,
554
				 "/Encoding 256 array\n"
555
				 "0 1 255 {1 index exch /.notdef put} for\n");
556
    if (font->scaled_font_subset->is_latin) {
557
	for (i = 1; i < 256; i++) {
558
	    int subset_glyph = font->scaled_font_subset->latin_to_subset_glyph_index[i];
559

            
560
	    if (subset_glyph > 0) {
561
		_cairo_output_stream_printf (font->output,
562
					     "dup %d /%s put\n",
563
					     i,
564
					     _cairo_winansi_to_glyphname (i));
565
	    }
566
	}
567
    } else {
568
	for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
569
	    glyph = font->scaled_subset_index_to_glyphs[i];
570
	    _cairo_output_stream_printf (font->output,
571
					 "dup %d /%s put\n",
572
					 i,
573
					 font->glyph_names[glyph]);
574
	}
575
    }
576
    _cairo_output_stream_printf (font->output, "readonly def");
577

            
578
    end = find_token (start, segment_end, "def");
579
    if (end == NULL)
580
	return CAIRO_INT_STATUS_UNSUPPORTED;
581
    end += 3;
582

            
583
    /* There are some buggy fonts that contain more than one /Encoding */
584
    if (find_token (end, segment_end, "/Encoding"))
585
	return CAIRO_INT_STATUS_UNSUPPORTED;
586

            
587
    _cairo_output_stream_write (font->output, end, segment_end - end);
588

            
589
    return font->output->status;
590
}
591

            
592
static int
593
hex_to_int (int ch)
594
{
595
    if (ch <= '9')
596
	return ch - '0';
597
    else if (ch <= 'F')
598
	return ch - 'A' + 10;
599
    else
600
	return ch - 'a' + 10;
601
}
602

            
603
static cairo_status_t
604
cairo_type1_font_subset_write_encrypted (cairo_type1_font_subset_t *font,
605
					 const char *data, unsigned int length)
606
{
607
    const unsigned char *in, *end;
608
    int c, p;
609
    static const char hex_digits[16] = "0123456789abcdef";
610
    char digits[3];
611

            
612
    in = (const unsigned char *) data;
613
    end = (const unsigned char *) data + length;
614
    while (in < end) {
615
	p = *in++;
616
	c = p ^ (font->eexec_key >> 8);
617
	font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
618

            
619
	if (font->hex_encode) {
620
	    digits[0] = hex_digits[c >> 4];
621
	    digits[1] = hex_digits[c & 0x0f];
622
	    digits[2] = '\n';
623
	    font->hex_column += 2;
624

            
625
	    if (font->hex_column == 78) {
626
		_cairo_output_stream_write (font->output, digits, 3);
627
		font->hex_column = 0;
628
	    } else {
629
		_cairo_output_stream_write (font->output, digits, 2);
630
	    }
631
	} else {
632
	    digits[0] = c;
633
	    _cairo_output_stream_write (font->output, digits, 1);
634
	}
635
    }
636

            
637
    return font->output->status;
638
}
639

            
640
static cairo_status_t
641
cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font)
642
{
643
    unsigned short r = CAIRO_TYPE1_PRIVATE_DICT_KEY;
644
    unsigned char *in, *end;
645
    char *out;
646
    int c, p;
647
    unsigned int i;
648

            
649
    in = (unsigned char *) font->eexec_segment;
650
    end = (unsigned char *) in + font->eexec_segment_size;
651

            
652
    font->cleartext = _cairo_malloc (font->eexec_segment_size + 1);
653
    if (unlikely (font->cleartext == NULL))
654
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
655

            
656
    out = font->cleartext;
657
    while (in < end) {
658
	if (font->eexec_segment_is_ascii) {
659
	    c = *in++;
660
	    if (_cairo_isspace (c))
661
		continue;
662
	    c = (hex_to_int (c) << 4) | hex_to_int (*in++);
663
	} else {
664
	    c = *in++;
665
	}
666
	p = c ^ (r >> 8);
667
	r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
668

            
669
	*out++ = p;
670
    }
671
    font->cleartext_end = out;
672

            
673
    /* Overwrite random bytes with spaces.
674
     *
675
     * The first 4 bytes of the cleartext are the random bytes
676
     * required by the encryption algorithm. When encrypting the
677
     * cleartext, the first ciphertext byte must not be a white space
678
     * character and the first 4 bytes must not be an ASCII Hex
679
     * character. Some fonts do not check that their randomly chosen
680
     * bytes results in ciphertext that complies with this
681
     * restriction. This may cause problems for some PDF consumers. By
682
     * replacing the random bytes with spaces, the first four bytes of
683
     * ciphertext will always be 0xf9, 0x83, 0xef, 0x00 which complies
684
     * with this restriction. Using spaces also means we don't have to
685
     * skip over the random bytes when parsing the cleartext.
686
     */
687
    for (i = 0; i < 4 && i < font->eexec_segment_size; i++)
688
	font->cleartext[i] = ' ';
689

            
690
    /* Ensure strtol() can not scan past the end of the cleartext */
691
    font->cleartext[font->eexec_segment_size] = 0;
692

            
693
    return CAIRO_STATUS_SUCCESS;
694
}
695

            
696
static const char *
697
skip_token (const char *p, const char *end)
698
{
699
    while (p < end && _cairo_isspace(*p))
700
	p++;
701

            
702
    while (p < end && !_cairo_isspace(*p))
703
	p++;
704

            
705
    if (p == end)
706
	return NULL;
707

            
708
    return p;
709
}
710

            
711
static void
712
cairo_type1_font_subset_decrypt_charstring (const unsigned char *in, int size, unsigned char *out)
713
{
714
    unsigned short r = CAIRO_TYPE1_CHARSTRING_KEY;
715
    int c, p, i;
716

            
717
    for (i = 0; i < size; i++) {
718
        c = *in++;
719
	p = c ^ (r >> 8);
720
	r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
721
	*out++ = p;
722
    }
723
}
724

            
725
static const unsigned char *
726
cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer)
727
{
728
    if (*p <= 246) {
729
        *integer = *p++ - 139;
730
    } else if (*p <= 250) {
731
        *integer = (p[0] - 247) * 256 + p[1] + 108;
732
        p += 2;
733
    } else if (*p <= 254) {
734
        *integer = -(p[0] - 251) * 256 - p[1] - 108;
735
        p += 2;
736
    } else {
737
        *integer = ((uint32_t)p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
738
        p += 5;
739
    }
740

            
741
    return p;
742
}
743

            
744
static cairo_status_t
745
use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
746
{
747
    const char *glyph_name;
748
    unsigned int i;
749

            
750
    if (index < 0 || index > 255)
751
	return CAIRO_STATUS_SUCCESS;
752

            
753
    glyph_name = _cairo_ps_standard_encoding_to_glyphname (index);
754
    if (glyph_name == NULL)
755
	return CAIRO_STATUS_SUCCESS;
756

            
757
    for (i = 0; i < font->base.num_glyphs; i++) {
758
	if (font->glyph_names[i] &&  strcmp (font->glyph_names[i], glyph_name) == 0) {
759
	    cairo_type1_font_subset_use_glyph (font, i);
760

            
761
	    return CAIRO_STATUS_SUCCESS;
762
	}
763
    }
764

            
765
    return CAIRO_INT_STATUS_UNSUPPORTED;
766
}
767

            
768

            
769
#define TYPE1_CHARSTRING_COMMAND_HSTEM		 0x01
770
#define TYPE1_CHARSTRING_COMMAND_VSTEM		 0x03
771
#define TYPE1_CHARSTRING_COMMAND_VMOVETO	 0x04
772
#define TYPE1_CHARSTRING_COMMAND_RLINETO	 0x05
773
#define TYPE1_CHARSTRING_COMMAND_HLINETO	 0x06
774
#define TYPE1_CHARSTRING_COMMAND_VLINETO	 0x07
775
#define TYPE1_CHARSTRING_COMMAND_RRCURVETO	 0x08
776
#define TYPE1_CHARSTRING_COMMAND_CLOSEPATH	 0x09
777
#define TYPE1_CHARSTRING_COMMAND_CALLSUBR	 0x0a
778
#define TYPE1_CHARSTRING_COMMAND_RETURN		 0x0b
779
#define TYPE1_CHARSTRING_COMMAND_ESCAPE		 0x0c
780
#define TYPE1_CHARSTRING_COMMAND_HSBW		 0x0d
781
#define TYPE1_CHARSTRING_COMMAND_ENDCHAR	 0x0e
782
#define TYPE1_CHARSTRING_COMMAND_RMOVETO	 0x15
783
#define TYPE1_CHARSTRING_COMMAND_HMOVETO	 0x16
784
#define TYPE1_CHARSTRING_COMMAND_VHCURVETO	 0x1e
785
#define TYPE1_CHARSTRING_COMMAND_HVCURVETO	 0x1f
786
#define TYPE1_CHARSTRING_COMMAND_DOTSECTION	 0x0c00
787
#define TYPE1_CHARSTRING_COMMAND_VSTEM3		 0x0c01
788
#define TYPE1_CHARSTRING_COMMAND_HSTEM3		 0x0c02
789
#define TYPE1_CHARSTRING_COMMAND_SEAC		 0x0c06
790
#define TYPE1_CHARSTRING_COMMAND_SBW		 0x0c07
791
#define TYPE1_CHARSTRING_COMMAND_DIV		 0x0c0c
792
#define TYPE1_CHARSTRING_COMMAND_CALLOTHERSUBR   0x0c10
793
#define TYPE1_CHARSTRING_COMMAND_POP	         0x0c11
794
#define TYPE1_CHARSTRING_COMMAND_SETCURRENTPOINT 0x0c21
795

            
796
/* Parse the charstring, including recursing into subroutines. Find
797
 * the glyph width, subroutines called, and glyphs required by the
798
 * SEAC operator. */
799
static cairo_status_t
800
cairo_type1_font_subset_parse_charstring (cairo_type1_font_subset_t *font,
801
					  int                        glyph,
802
					  const char                *encrypted_charstring,
803
					  int                        encrypted_charstring_length)
804
{
805
    cairo_status_t status;
806
    unsigned char *charstring;
807
    const unsigned char *end;
808
    const unsigned char *p;
809
    int command;
810

            
811
    charstring = _cairo_malloc (encrypted_charstring_length);
812
    if (unlikely (charstring == NULL))
813
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
814

            
815
    cairo_type1_font_subset_decrypt_charstring ((const unsigned char *)
816
						encrypted_charstring,
817
						encrypted_charstring_length,
818
						charstring);
819
    end = charstring + encrypted_charstring_length;
820
    p = charstring + font->lenIV;
821
    status = CAIRO_STATUS_SUCCESS;
822
    while (p < end) {
823
        if (*p < 32) {
824
	    command = *p++;
825
	    switch (command) {
826
	    case TYPE1_CHARSTRING_COMMAND_HSTEM:
827
	    case TYPE1_CHARSTRING_COMMAND_VSTEM:
828
	    case TYPE1_CHARSTRING_COMMAND_VMOVETO:
829
	    case TYPE1_CHARSTRING_COMMAND_RLINETO:
830
	    case TYPE1_CHARSTRING_COMMAND_HLINETO:
831
	    case TYPE1_CHARSTRING_COMMAND_VLINETO:
832
	    case TYPE1_CHARSTRING_COMMAND_RRCURVETO:
833
	    case TYPE1_CHARSTRING_COMMAND_CLOSEPATH:
834
	    case TYPE1_CHARSTRING_COMMAND_RMOVETO:
835
	    case TYPE1_CHARSTRING_COMMAND_HMOVETO:
836
	    case TYPE1_CHARSTRING_COMMAND_VHCURVETO:
837
	    case TYPE1_CHARSTRING_COMMAND_HVCURVETO:
838
	    case TYPE1_CHARSTRING_COMMAND_RETURN:
839
	    case TYPE1_CHARSTRING_COMMAND_ENDCHAR:
840
	    default:
841
		/* stack clearing operator */
842
		font->build_stack.sp = 0;
843
		break;
844

            
845
	    case TYPE1_CHARSTRING_COMMAND_CALLSUBR:
846
		if (font->subset_subrs && font->build_stack.sp > 0) {
847
		    double int_val;
848
		    if (modf(font->build_stack.stack[--font->build_stack.sp], &int_val) == 0.0) {
849
			int subr_num = int_val;
850
			if (subr_num >= 0 && subr_num < font->num_subrs) {
851
			    font->subrs[subr_num].used = TRUE;
852
			    status = cairo_type1_font_subset_parse_charstring (
853
				font,
854
				glyph,
855
				font->subrs[subr_num].subr_string,
856
				font->subrs[subr_num].subr_length);
857
			    break;
858
			}
859
		    }
860
		}
861
		font->subset_subrs = FALSE;
862
		break;
863

            
864
	    case TYPE1_CHARSTRING_COMMAND_HSBW:
865
		if (font->build_stack.sp < 2) {
866
		    status = CAIRO_INT_STATUS_UNSUPPORTED;
867
		    goto cleanup;
868
		}
869

            
870
		font->glyphs[glyph].width = font->build_stack.stack[1]/font->base.units_per_em;
871
		font->build_stack.sp = 0;
872
		break;
873

            
874
	    case TYPE1_CHARSTRING_COMMAND_ESCAPE:
875
		command = command << 8 | *p++;
876
		switch (command) {
877
		case TYPE1_CHARSTRING_COMMAND_DOTSECTION:
878
		case TYPE1_CHARSTRING_COMMAND_VSTEM3:
879
		case TYPE1_CHARSTRING_COMMAND_HSTEM3:
880
		case TYPE1_CHARSTRING_COMMAND_SETCURRENTPOINT:
881
		default:
882
		    /* stack clearing operator */
883
		    font->build_stack.sp = 0;
884
		    break;
885

            
886
		case TYPE1_CHARSTRING_COMMAND_SEAC:
887
		    /* The seac command takes five integer arguments.  The
888
		     * last two are glyph indices into the PS standard
889
		     * encoding give the names of the glyphs that this
890
		     * glyph is composed from.  All we need to do is to
891
		     * make sure those glyphs are present in the subset
892
		     * under their standard names. */
893
		    if (font->build_stack.sp < 5) {
894
			status = CAIRO_INT_STATUS_UNSUPPORTED;
895
			goto cleanup;
896
		    }
897

            
898
		    status = use_standard_encoding_glyph (font, font->build_stack.stack[3]);
899
		    if (unlikely (status))
900
			goto cleanup;
901

            
902
		    status = use_standard_encoding_glyph (font, font->build_stack.stack[4]);
903
		    if (unlikely (status))
904
			goto cleanup;
905

            
906
		    font->build_stack.sp = 0;
907
		    break;
908

            
909
		case TYPE1_CHARSTRING_COMMAND_SBW:
910
		    if (font->build_stack.sp < 4) {
911
			status = CAIRO_INT_STATUS_UNSUPPORTED;
912
			goto cleanup;
913
		    }
914

            
915
		    font->glyphs[glyph].width = font->build_stack.stack[2]/font->base.units_per_em;
916
		    font->build_stack.sp = 0;
917
		    break;
918

            
919
		case TYPE1_CHARSTRING_COMMAND_DIV:
920
		    if (font->build_stack.sp < 2) {
921
			status = CAIRO_INT_STATUS_UNSUPPORTED;
922
			goto cleanup;
923
		    } else {
924
			double num1 = font->build_stack.stack[font->build_stack.sp - 2];
925
			double num2 = font->build_stack.stack[font->build_stack.sp - 1];
926
			font->build_stack.sp--;
927
			if (num2 == 0.0) {
928
			    status = CAIRO_INT_STATUS_UNSUPPORTED;
929
			    goto cleanup;
930
			}
931
			font->build_stack.stack[font->build_stack.sp - 1] = num1/num2;
932
		    }
933
		    break;
934

            
935
		case TYPE1_CHARSTRING_COMMAND_CALLOTHERSUBR:
936
		    if (font->build_stack.sp < 1) {
937
			status = CAIRO_INT_STATUS_UNSUPPORTED;
938
			goto cleanup;
939
		    }
940

            
941
		    font->build_stack.sp--;
942
		    font->ps_stack.sp = 0;
943
		    while (font->build_stack.sp)
944
			font->ps_stack.stack[font->ps_stack.sp++] = font->build_stack.stack[--font->build_stack.sp];
945

            
946
                    break;
947

            
948
		case TYPE1_CHARSTRING_COMMAND_POP:
949
		    if (font->ps_stack.sp < 1) {
950
			status = CAIRO_INT_STATUS_UNSUPPORTED;
951
			goto cleanup;
952
		    }
953

            
954
		    /* T1 spec states that if the interpreter does not
955
		     * support executing the callothersub, the results
956
		     * must be taken from the callothersub arguments. */
957
		    font->build_stack.stack[font->build_stack.sp++] = font->ps_stack.stack[--font->ps_stack.sp];
958
		    break;
959
		}
960
		break;
961
	    }
962
	} else {
963
            /* integer argument */
964
	    if (font->build_stack.sp < TYPE1_STACKSIZE) {
965
		int val;
966
		p = cairo_type1_font_subset_decode_integer (p, &val);
967
		font->build_stack.stack[font->build_stack.sp++] = val;
968
	    } else {
969
		status = CAIRO_INT_STATUS_UNSUPPORTED;
970
		goto cleanup;
971
	    }
972
	}
973
    }
974

            
975
cleanup:
976
    free (charstring);
977

            
978
    return status;
979
}
980

            
981
static cairo_status_t
982
cairo_type1_font_subset_build_subr_list (cairo_type1_font_subset_t *font,
983
					 int subr_number,
984
					 const char *encrypted_charstring, int encrypted_charstring_length,
985
					 const char *np, int np_length)
986
{
987

            
988
    font->subrs[subr_number].subr_string = encrypted_charstring;
989
    font->subrs[subr_number].subr_length = encrypted_charstring_length;
990
    font->subrs[subr_number].np = np;
991
    font->subrs[subr_number].np_length = np_length;
992

            
993
    return CAIRO_STATUS_SUCCESS;
994
}
995

            
996
static cairo_status_t
997
write_used_subrs (cairo_type1_font_subset_t *font,
998
		  int subr_number,
999
		  const char *subr_string, int subr_string_length,
		  const char *np, int np_length)
{
    cairo_status_t status;
    char buffer[256];
    int length;
    if (!font->subrs[subr_number].used)
	return CAIRO_STATUS_SUCCESS;
    length = snprintf (buffer, sizeof buffer,
		       "dup %d %d %s ",
		       subr_number, subr_string_length, font->rd);
    status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
    if (unlikely (status))
	return status;
    status = cairo_type1_font_subset_write_encrypted (font,
					              subr_string,
						      subr_string_length);
    if (unlikely (status))
	return status;
    if (np) {
	status = cairo_type1_font_subset_write_encrypted (font, np, np_length);
    } else {
	length = snprintf (buffer, sizeof buffer, "%s\n", font->np);
	status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
    }
    if (unlikely (status))
	return status;
    return CAIRO_STATUS_SUCCESS;
}
typedef cairo_status_t (*subr_func_t) (cairo_type1_font_subset_t *font,
				       int subr_number,
				       const char *subr_string, int subr_string_length,
				       const char *np, int np_length);
static cairo_status_t
cairo_type1_font_for_each_subr (cairo_type1_font_subset_t  *font,
				const char                 *array_start,
				const char                 *cleartext_end,
				subr_func_t                 func,
				const char                **array_end)
{
    const char *p, *subr_string;
    char *end;
    int subr_num, subr_length;
    const char *np;
    int np_length;
    cairo_status_t status;
    /* We're looking at "dup" at the start of the first subroutine. The subroutines
     * definitions are on the form:
     *
     *   dup 5 23 RD <23 binary bytes> NP
     *
     * or alternatively using -| and |- instead of RD and ND.
     * The first number is the subroutine number.
     */
    p = array_start;
    while (p + 3 < cleartext_end && strncmp (p, "dup", 3) == 0) {
	p = skip_token (p, cleartext_end);
	/* get subr number */
	subr_num = strtol (p, &end, 10);
	if (p == end)
	    return CAIRO_INT_STATUS_UNSUPPORTED;
	if (subr_num < 0 || subr_num >= font->num_subrs)
	    return CAIRO_INT_STATUS_UNSUPPORTED;
	/* get subr length */
	p = end;
	subr_length = strtol (p, &end, 10);
	if (p == end)
	    return CAIRO_INT_STATUS_UNSUPPORTED;
	/* Skip past -| or RD to binary data.  There is exactly one space
	 * between the -| or RD token and the encrypted data, thus '+ 1'. */
	subr_string = skip_token (end, cleartext_end) + 1;
	np = NULL;
	np_length = 0;
	/* Skip binary data and | or NP token. */
	p = skip_token (subr_string + subr_length, cleartext_end);
        if (p == NULL)
            return CAIRO_INT_STATUS_UNSUPPORTED;
	while (p < cleartext_end && _cairo_isspace(*p))
	    p++;
	/* Some fonts have "noaccess put" instead of "NP" */
	if (p + 3 < cleartext_end && strncmp (p, "put", 3) == 0) {
	    p = skip_token (p, cleartext_end);
	    while (p < cleartext_end && _cairo_isspace(*p))
		p++;
	    np = subr_string + subr_length;
	    np_length = p - np;
	}
	status = func (font, subr_num,
		       subr_string, subr_length, np, np_length);
	if (unlikely (status))
	    return status;
    }
    *array_end = (char *) p;
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_type1_font_subset_build_glyph_list (cairo_type1_font_subset_t *font,
					  int glyph_number,
					  const char *name, int name_length,
					  const char *encrypted_charstring, int encrypted_charstring_length)
{
    char *s;
    glyph_data_t glyph;
    cairo_status_t status;
    s = _cairo_malloc (name_length + 1);
    if (unlikely (s == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    strncpy (s, name, name_length);
    s[name_length] = 0;
    status = _cairo_array_append (&font->glyph_names_array, &s);
    if (unlikely (status))
	return status;
    glyph.subset_index = -1;
    glyph.width = 0;
    glyph.encrypted_charstring = encrypted_charstring;
    glyph.encrypted_charstring_length = encrypted_charstring_length;
    status = _cairo_array_append (&font->glyphs_array, &glyph);
    return status;
}
static cairo_status_t
write_used_glyphs (cairo_type1_font_subset_t *font,
		   int glyph_number,
		   const char *name, int name_length,
		   const char *charstring, int charstring_length)
{
    cairo_status_t status;
    char buffer[256];
    int length;
    unsigned int subset_id;
    int ch;
    const char *wa_name;
    if (font->glyphs[glyph_number].subset_index < 0)
	return CAIRO_STATUS_SUCCESS;
    if (font->scaled_font_subset->is_latin) {
	/* When using the WinAnsi encoding in PDF, the /Encoding array
	 * is ignored and instead glyphs are keyed by glyph names. To
	 * ensure correct rendering we replace the glyph name in the
	 * font with the standard name.
         **/
	subset_id = font->glyphs[glyph_number].subset_index;
	/* Any additional glyph included for use by the seac operator
	 * will either have subset_id >= font->scaled_font_subset->num_glyphs
	 * or will not map to a winansi name (wa_name = NULL).  In this
	 * case the original name is used.
	 */
	if (subset_id > 0 && subset_id < font->scaled_font_subset->num_glyphs) {
	    ch = font->scaled_font_subset->to_latin_char[subset_id];
	    wa_name = _cairo_winansi_to_glyphname (ch);
	    if (wa_name) {
		name = wa_name;
		name_length = strlen(name);
	    }
	}
    }
    length = snprintf (buffer, sizeof buffer,
		       "/%.*s %d %s ",
		       name_length, name, charstring_length, font->rd);
    status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
    if (unlikely (status))
	return status;
    status = cairo_type1_font_subset_write_encrypted (font,
					              charstring,
						      charstring_length);
    if (unlikely (status))
	return status;
    length = snprintf (buffer, sizeof buffer, "%s\n", font->nd);
    status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
    if (unlikely (status))
	return status;
    return CAIRO_STATUS_SUCCESS;
}
typedef cairo_status_t (*glyph_func_t) (cairo_type1_font_subset_t *font,
					int glyph_number,
			                const char *name, int name_length,
			                const char *charstring, int charstring_length);
static cairo_status_t
cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font,
					const char *dict_start,
					const char *dict_end,
					glyph_func_t func,
					const char **dict_out)
{
    int charstring_length, name_length;
    const char *p, *charstring, *name;
    char *end;
    cairo_status_t status;
    int glyph_count;
    /* We're looking at '/' in the name of the first glyph.  The glyph
     * definitions are on the form:
     *
     *   /name 23 RD <23 binary bytes> ND
     *
     * or alternatively using -| and |- instead of RD and ND.
     *
     * We parse the glyph name and see if it is in the subset.  If it
     * is, we call the specified callback with the glyph name and
     * glyph data, otherwise we just skip it.  We need to parse
     * through a glyph definition; we can't just find the next '/',
     * since the binary data could contain a '/'.
     */
    p = dict_start;
    glyph_count = 0;
    while (*p == '/') {
	name = p + 1;
	p = skip_token (p, dict_end);
	name_length = p - name;
	charstring_length = strtol (p, &end, 10);
	if (p == end)
	    return CAIRO_INT_STATUS_UNSUPPORTED;
	/* Skip past -| or RD to binary data.  There is exactly one space
	 * between the -| or RD token and the encrypted data, thus '+ 1'. */
	charstring = skip_token (end, dict_end) + 1;
	/* Skip binary data and |- or ND token. */
	p = skip_token (charstring + charstring_length, dict_end);
        if (p == NULL)
            return CAIRO_INT_STATUS_UNSUPPORTED;
	while (p < dict_end && _cairo_isspace(*p))
	    p++;
	/* In case any of the skip_token() calls above reached EOF, p will
	 * be equal to dict_end. */
	if (p == dict_end)
	    return CAIRO_INT_STATUS_UNSUPPORTED;
	status = func (font, glyph_count++,
		       name, name_length,
		       charstring, charstring_length);
	if (unlikely (status))
	    return status;
    }
    *dict_out = p;
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
					    const char                *name)
{
    cairo_status_t status;
    const char *p, *subrs, *charstrings, *array_start, *array_end, *dict_start, *dict_end;
    const char *lenIV_start, *lenIV_end, *closefile_token;
    char buffer[32], *lenIV_str, *subr_count_end, *glyph_count_end;
    int ret, lenIV, length;
    const cairo_scaled_font_backend_t *backend;
    unsigned int i;
    int glyph, j;
    /* The private dict holds hint information, common subroutines and
     * the actual glyph definitions (charstrings).
     *
     * What we do here is scan directly to the /Subrs token, which
     * marks the beginning of the subroutines. We read in all the
     * subroutines, then move on to the /CharString token, which marks
     * the beginning of the glyph definitions, and read in the charstrings.
     *
     * The charstrings are parsed to extract glyph widths, work out
     * which subroutines are called, and to see if any extra glyphs
     * need to be included due to the use of the seac glyph combining
     * operator.
     *
     * Finally, the private dict is copied to the subset font minus the
     * subroutines and charstrings not required.
     */
    /* Determine lenIV, the number of random characters at the start of
       each encrypted charstring. The default is 4, but this can be
       overridden in the private dict. */
    font->lenIV = 4;
    if ((lenIV_start = find_token (font->cleartext, font->cleartext_end, "/lenIV")) != NULL) {
        lenIV_start += 6;
        lenIV_end = find_token (lenIV_start, font->cleartext_end, "def");
        if (lenIV_end == NULL)
	    return CAIRO_INT_STATUS_UNSUPPORTED;
        lenIV_str = _cairo_malloc (lenIV_end - lenIV_start + 1);
        if (unlikely (lenIV_str == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
        strncpy (lenIV_str, lenIV_start, lenIV_end - lenIV_start);
        lenIV_str[lenIV_end - lenIV_start] = 0;
        ret = sscanf(lenIV_str, "%d", &lenIV);
        free(lenIV_str);
        if (unlikely (ret <= 0))
	    return CAIRO_INT_STATUS_UNSUPPORTED;
        /* Apparently some fonts signal unencrypted charstrings with a negative lenIV,
           though this is not part of the Type 1 Font Format specification.  See, e.g.
           http://lists.gnu.org/archive/html/freetype-devel/2000-06/msg00064.html. */
        if (unlikely (lenIV < 0))
	    return CAIRO_INT_STATUS_UNSUPPORTED;
        font->lenIV = lenIV;
    }
    /* Find start of Subrs */
    subrs = find_token (font->cleartext, font->cleartext_end, "/Subrs");
    if (subrs == NULL) {
	font->subset_subrs = FALSE;
	p = font->cleartext;
	array_start = NULL;
	goto skip_subrs;
    }
    /* Scan past /Subrs and get the array size. */
    p = subrs + strlen ("/Subrs");
    font->num_subrs = strtol (p, &subr_count_end, 10);
    if (subr_count_end == p)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    if (font->num_subrs <= 0)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    font->subrs = _cairo_calloc_ab (font->num_subrs, sizeof (font->subrs[0]));
    if (unlikely (font->subrs == NULL))
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    /* look for "dup" which marks the beginning of the first subr */
    array_start = find_token (subr_count_end, font->cleartext_end, "dup");
    if (array_start == NULL)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    /* Read in the subroutines */
    status = cairo_type1_font_for_each_subr (font,
					     array_start,
					     font->cleartext_end,
					     cairo_type1_font_subset_build_subr_list,
					     &array_end);
    if (unlikely(status))
	return status;
    p = array_end;
skip_subrs:
    /* Find start of CharStrings */
    charstrings = find_token (p, font->cleartext_end, "/CharStrings");
    if (charstrings == NULL)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    /* Scan past /CharStrings and the integer following it. */
    p = charstrings + strlen ("/CharStrings");
    strtol (p, &glyph_count_end, 10);
    if (p == glyph_count_end)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    /* Look for a '/' which marks the beginning of the first glyph
     * definition. */
    for (p = glyph_count_end; p < font->cleartext_end; p++)
	if (*p == '/')
	    break;
    if (p == font->cleartext_end)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    dict_start = p;
    /* Now that we have the private dictionary broken down in
     * sections, do the first pass through the glyph definitions to
     * build a list of glyph names and charstrings. */
    status = cairo_type1_font_subset_for_each_glyph (font,
						     dict_start,
						     font->cleartext_end,
						     cairo_type1_font_subset_build_glyph_list,
						     &dict_end);
    if (unlikely(status))
	return status;
    font->glyphs = _cairo_array_index (&font->glyphs_array, 0);
    font->glyph_names = _cairo_array_index (&font->glyph_names_array, 0);
    font->base.num_glyphs = _cairo_array_num_elements (&font->glyphs_array);
    font->type1_subset_index_to_glyphs = _cairo_calloc_ab (font->base.num_glyphs,
							sizeof font->type1_subset_index_to_glyphs[0]);
    if (unlikely (font->type1_subset_index_to_glyphs == NULL))
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    backend = font->scaled_font_subset->scaled_font->backend;
    if (!backend->index_to_glyph_name)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    /* Find the glyph number corresponding to each glyph in the subset
     * and mark it as in use */
    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
	unsigned long index;
	status = backend->index_to_glyph_name (font->scaled_font_subset->scaled_font,
					       font->glyph_names,
					       font->base.num_glyphs,
					       font->scaled_font_subset->glyphs[i],
					       &index);
	if (unlikely(status))
	    return status;
	cairo_type1_font_subset_use_glyph (font, index);
	font->scaled_subset_index_to_glyphs[i] = index;
    }
    /* Go through the charstring of each glyph in use, get the glyph
     * width and figure out which extra glyphs may be required by the
     * seac operator (which may cause font->num_glyphs to increase
     * while this loop is executing). Also subset the Subrs. */
    for (j = 0; j < font->num_glyphs; j++) {
	glyph = font->type1_subset_index_to_glyphs[j];
	font->build_stack.sp = 0;
	font->ps_stack.sp = 0;
	status = cairo_type1_font_subset_parse_charstring (font,
							   glyph,
							   font->glyphs[glyph].encrypted_charstring,
							   font->glyphs[glyph].encrypted_charstring_length);
	if (unlikely (status))
	    return status;
    }
    /* Always include the first five subroutines in case the Flex/hint mechanism is
     * being used. */
    for (j = 0; j < MIN (font->num_subrs, 5); j++) {
	font->subrs[j].used = TRUE;
    }
    closefile_token = find_token (dict_end, font->cleartext_end, "closefile");
    if (closefile_token == NULL)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    /* We're ready to start outputting. First write the header,
     * i.e. the public part of the font dict.*/
    status = cairo_type1_font_subset_write_header (font, name);
    if (unlikely (status))
	return status;
    font->base.header_size = _cairo_output_stream_get_position (font->output);
    /* Start outputting the private dict */
    if (font->subset_subrs) {
	/* First output everything up to the start of the Subrs array. */
	status = cairo_type1_font_subset_write_encrypted (font, font->cleartext,
							  array_start - font->cleartext);
	if (unlikely (status))
	    return status;
	/* Write out the subr definitions for each of the glyphs in
	 * the subset. */
	status = cairo_type1_font_for_each_subr (font,
						 array_start,
						 font->cleartext_end,
						 write_used_subrs,
						 &p);
	if (unlikely (status))
	    return status;
    } else {
	p = font->cleartext;
    }
    /* If subr subsetting, output everything from end of subrs to
     * start of /CharStrings token.  If not subr subsetting, output
     * everything start of private dict to start of /CharStrings
     * token. */
    status = cairo_type1_font_subset_write_encrypted (font, p, charstrings - p);
    if (unlikely (status))
	return status;
    /* Write out new charstring count */
    length = snprintf (buffer, sizeof buffer,
		       "/CharStrings %d", font->num_glyphs);
    status = cairo_type1_font_subset_write_encrypted (font, buffer, length);
    if (unlikely (status))
	return status;
    /* Write out text between the charstring count and the first
     * charstring definition */
    status = cairo_type1_font_subset_write_encrypted (font, glyph_count_end,
	                                          dict_start - glyph_count_end);
    if (unlikely (status))
	return status;
    /* Write out the charstring definitions for each of the glyphs in
     * the subset. */
    status = cairo_type1_font_subset_for_each_glyph (font,
						     dict_start,
						     font->cleartext_end,
						     write_used_glyphs,
						     &p);
    if (unlikely (status))
	return status;
    /* Output what's left between the end of the glyph definitions and
     * the end of the private dict to the output. */
    status = cairo_type1_font_subset_write_encrypted (font, p,
	                        closefile_token - p + strlen ("closefile") + 1);
    if (unlikely (status))
	return status;
    if (font->hex_encode)
	_cairo_output_stream_write (font->output, "\n", 1);
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_type1_font_subset_write_trailer(cairo_type1_font_subset_t *font)
{
    const char *cleartomark_token;
    int i;
    static const char zeros[65] =
	"0000000000000000000000000000000000000000000000000000000000000000\n";
    for (i = 0; i < 8; i++)
	_cairo_output_stream_write (font->output, zeros, sizeof zeros);
    cleartomark_token = find_token (font->type1_data, font->type1_end, "cleartomark");
    if (cleartomark_token) {
	/* Some fonts have conditional save/restore around the entire
	 * font dict, so we need to retain whatever postscript code
	 * that may come after 'cleartomark'. */
	_cairo_output_stream_write (font->output, cleartomark_token,
				    font->type1_end - cleartomark_token);
	if (*(font->type1_end - 1) != '\n')
	    _cairo_output_stream_printf (font->output, "\n");
    } else if (!font->eexec_segment_is_ascii) {
	/* Fonts embedded in PDF may omit the fixed-content portion
	 * that includes the 'cleartomark' operator. Type 1 in PDF is
	 * always binary. */
	_cairo_output_stream_printf (font->output, "cleartomark\n");
    } else {
	return CAIRO_INT_STATUS_UNSUPPORTED;
    }
    /* some fonts do not have a newline at the end of the last line */
    _cairo_output_stream_printf (font->output, "\n");
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
type1_font_write (void *closure, const unsigned char *data, unsigned int length)
{
    cairo_type1_font_subset_t *font = closure;
    return _cairo_array_append_multiple (&font->contents, data, length);
}
static cairo_status_t
cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
			       const char *name)
{
    cairo_status_t status;
    status = cairo_type1_font_subset_find_segments (font);
    if (unlikely (status))
	return status;
    status = cairo_type1_font_subset_decrypt_eexec_segment (font);
    if (unlikely (status))
	return status;
    /* Determine which glyph definition delimiters to use. */
    if (find_token (font->cleartext, font->cleartext_end, "/-|") != NULL) {
	font->rd = "-|";
	font->nd = "|-";
	font->np = "|";
    } else if (find_token (font->cleartext, font->cleartext_end, "/RD") != NULL) {
	font->rd = "RD";
	font->nd = "ND";
	font->np = "NP";
    } else {
	/* Don't know *what* kind of font this is... */
	return CAIRO_INT_STATUS_UNSUPPORTED;
    }
    font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
    font->hex_column = 0;
    status = cairo_type1_font_subset_get_bbox (font);
    if (unlikely (status))
	return status;
    status = cairo_type1_font_subset_get_fontname (font);
    if (unlikely (status))
	return status;
    status = cairo_type1_font_subset_write_private_dict (font, name);
    if (unlikely (status))
	return status;
    font->base.data_size = _cairo_output_stream_get_position (font->output) -
	font->base.header_size;
    status = cairo_type1_font_subset_write_trailer (font);
    if (unlikely (status))
	return status;
    font->base.trailer_size =
	_cairo_output_stream_get_position (font->output) -
	font->base.header_size - font->base.data_size;
    return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
check_fontdata_is_type1 (const unsigned char *data, long length)
{
    /* Test for  Type 1 Binary (PFB) */
    if (length > 2 && data[0] == 0x80 && data[1] == 0x01)
	return TRUE;
    /* Test for Type 1 1 ASCII (PFA) */
    if (length > 2 && data[0] == '%' && data[1] == '!')
	return TRUE;
    return FALSE;
}
static cairo_status_t
cairo_type1_font_subset_generate (void       *abstract_font,
				  const char *name)
{
    cairo_type1_font_subset_t *font = abstract_font;
    cairo_scaled_font_t *scaled_font;
    cairo_status_t status;
    unsigned long data_length;
    scaled_font = font->scaled_font_subset->scaled_font;
    if (!scaled_font->backend->load_type1_data)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    status = scaled_font->backend->load_type1_data (scaled_font, 0, NULL, &data_length);
    if (status)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    font->type1_length = data_length;
    font->type1_data = _cairo_malloc (font->type1_length);
    if (unlikely (font->type1_data == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    status = scaled_font->backend->load_type1_data (scaled_font, 0,
						    (unsigned char *) font->type1_data,
						    &data_length);
    if (unlikely (status))
        return status;
    if (!check_fontdata_is_type1 ((unsigned char *)font->type1_data, data_length))
	return CAIRO_INT_STATUS_UNSUPPORTED;
    status = _cairo_array_grow_by (&font->contents, 4096);
    if (unlikely (status))
	return status;
    font->output = _cairo_output_stream_create (type1_font_write, NULL, font);
    if (unlikely ((status = font->output->status)))
	return status;
    status = cairo_type1_font_subset_write (font, name);
    if (unlikely (status))
	return status;
    font->base.data = _cairo_array_index (&font->contents, 0);
    return status;
}
static cairo_status_t
_cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
{
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
    unsigned int i;
    /* If the subset generation failed, some of the pointers below may
     * be NULL depending on at which point the error occurred. */
    _cairo_array_fini (&font->contents);
    free (font->type1_data);
    for (i = 0; i < _cairo_array_num_elements (&font->glyph_names_array); i++) {
	char **s;
	s = _cairo_array_index (&font->glyph_names_array, i);
	free (*s);
    }
    _cairo_array_fini (&font->glyph_names_array);
    _cairo_array_fini (&font->glyphs_array);
    free (font->subrs);
    if (font->output != NULL)
	status = _cairo_output_stream_destroy (font->output);
    free (font->base.base_font);
    free (font->scaled_subset_index_to_glyphs);
    free (font->type1_subset_index_to_glyphs);
    free (font->cleartext);
    return status;
}
cairo_status_t
_cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
			  const char			*name,
			  cairo_scaled_font_subset_t	*scaled_font_subset,
                          cairo_bool_t                   hex_encode)
{
    cairo_type1_font_subset_t font;
    cairo_status_t status;
    cairo_bool_t is_synthetic;
    unsigned long length;
    unsigned int i;
    char buf[30];
    int glyph;
    /* We need to use a fallback font if this font differs from the type1 outlines. */
    if (scaled_font_subset->scaled_font->backend->is_synthetic) {
	status = scaled_font_subset->scaled_font->backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic);
	if (unlikely (status))
	    return status;
	if (is_synthetic)
	    return CAIRO_INT_STATUS_UNSUPPORTED;
    }
    status = _cairo_type1_font_subset_init (&font, scaled_font_subset, hex_encode);
    if (unlikely (status))
	return status;
    status = cairo_type1_font_subset_generate (&font, name);
    if (unlikely (status))
	goto fail1;
    if (font.base.base_font) {
	type1_subset->base_font = strdup (font.base.base_font);
    } else {
        snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
                 scaled_font_subset->font_id, scaled_font_subset->subset_id);
	type1_subset->base_font = strdup (buf);
    }
    if (unlikely (type1_subset->base_font == NULL))
	goto fail1;
    type1_subset->widths = _cairo_calloc_ab (scaled_font_subset->num_glyphs, sizeof (double));
    if (unlikely (type1_subset->widths == NULL))
	goto fail2;
    for (i = 0; i < font.scaled_font_subset->num_glyphs; i++) {
	glyph = font.scaled_subset_index_to_glyphs[i];
	type1_subset->widths[i] = font.glyphs[glyph].width;
    }
    type1_subset->x_min = font.base.x_min;
    type1_subset->y_min = font.base.y_min;
    type1_subset->x_max = font.base.x_max;
    type1_subset->y_max = font.base.y_max;
    type1_subset->ascent = font.base.ascent;
    type1_subset->descent = font.base.descent;
    length = font.base.header_size +
	     font.base.data_size +
	     font.base.trailer_size;
    type1_subset->data = _cairo_malloc (length);
    if (unlikely (type1_subset->data == NULL))
	goto fail3;
    memcpy (type1_subset->data,
	    _cairo_array_index (&font.contents, 0), length);
    type1_subset->header_length = font.base.header_size;
    type1_subset->data_length = font.base.data_size;
    type1_subset->trailer_length = font.base.trailer_size;
    return _cairo_type1_font_subset_fini (&font);
 fail3:
    free (type1_subset->widths);
 fail2:
    free (type1_subset->base_font);
 fail1:
    _cairo_type1_font_subset_fini (&font);
    return status;
}
void
_cairo_type1_subset_fini (cairo_type1_subset_t *subset)
{
    free (subset->base_font);
    free (subset->widths);
    free (subset->data);
}
cairo_bool_t
_cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
{
    cairo_status_t status;
    unsigned long length;
    unsigned char buf[64];
    if (!scaled_font->backend->load_type1_data)
	return FALSE;
    status = scaled_font->backend->load_type1_data (scaled_font, 0, NULL, &length);
    if (status)
	return FALSE;
    /* We only need a few bytes to test for Type 1 */
    if (length > sizeof (buf))
	length = sizeof (buf);
    status = scaled_font->backend->load_type1_data (scaled_font, 0, buf, &length);
    if (status)
	return FALSE;
    return check_fontdata_is_type1 (buf, length);
}
#endif /* CAIRO_HAS_FONT_SUBSET */