1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2006 Adrian Johnson
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 Adrian Johnson.
32
 *
33
 * Contributor(s):
34
 *	Adrian Johnson <ajohnson@redneon.com>
35
 *      Eugeniy Meshcheryakov <eugen@debian.org>
36
 */
37

            
38
/*
39
 * Useful links:
40
 * http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5176.CFF.pdf
41
 * http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5177.Type2.pdf
42
 */
43

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

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

            
50
#if CAIRO_HAS_FONT_SUBSET
51

            
52
#include "cairo-scaled-font-subsets-private.h"
53
#include "cairo-truetype-subset-private.h"
54
#include <string.h>
55
#include <locale.h>
56

            
57
/* CFF Dict Operators. If the high byte is 0 the command is encoded
58
 * with a single byte. */
59
#define BASEFONTNAME_OP     0x0c16
60
#define CIDCOUNT_OP         0x0c22
61
#define CHARSET_OP          0x000f
62
#define CHARSTRINGS_OP      0x0011
63
#define COPYRIGHT_OP        0x0c00
64
#define DEFAULTWIDTH_OP     0x0014
65
#define ENCODING_OP         0x0010
66
#define FAMILYNAME_OP       0x0003
67
#define FDARRAY_OP          0x0c24
68
#define FDSELECT_OP         0x0c25
69
#define FONTBBOX_OP         0x0005
70
#define FONTMATRIX_OP       0x0c07
71
#define FONTNAME_OP         0x0c26
72
#define FULLNAME_OP         0x0002
73
#define LOCAL_SUB_OP        0x0013
74
#define NOMINALWIDTH_OP     0x0015
75
#define NOTICE_OP           0x0001
76
#define POSTSCRIPT_OP       0x0c15
77
#define PRIVATE_OP          0x0012
78
#define ROS_OP              0x0c1e
79
#define UNIQUEID_OP         0x000d
80
#define VERSION_OP          0x0000
81
#define WEIGHT_OP           0x0004
82
#define XUID_OP             0x000e
83
#define BLUEVALUES_OP       0x0006
84
#define OTHERBLUES_OP       0x0007
85
#define FAMILYBLUES_OP      0x0008
86
#define FAMILYOTHERBLUES_OP 0x0009
87
#define STEMSNAPH_OP        0x0c0c
88
#define STEMSNAPV_OP        0x0c0d
89

            
90
#define NUM_STD_STRINGS 391
91

            
92
/* Type 2 Charstring operators */
93
#define TYPE2_hstem     0x0001
94
#define TYPE2_vstem     0x0003
95
#define TYPE2_callsubr  0x000a
96

            
97
#define TYPE2_return    0x000b
98
#define TYPE2_endchar   0x000e
99

            
100
#define TYPE2_hstemhm   0x0012
101
#define TYPE2_hintmask  0x0013
102
#define TYPE2_cntrmask  0x0014
103
#define TYPE2_vstemhm   0x0017
104
#define TYPE2_callgsubr 0x001d
105

            
106
#define TYPE2_rmoveto   0x0015
107
#define TYPE2_hmoveto   0x0016
108
#define TYPE2_vmoveto   0x0004
109

            
110

            
111
#define MAX_SUBROUTINE_NESTING 10 /* From Type2 Charstring spec */
112

            
113

            
114
typedef struct _cff_header {
115
    uint8_t major;
116
    uint8_t minor;
117
    uint8_t header_size;
118
    uint8_t offset_size;
119
} cff_header_t;
120

            
121
typedef struct _cff_index_element {
122
    cairo_bool_t   is_copy;
123
    unsigned char *data;
124
    int            length;
125
} cff_index_element_t;
126

            
127
typedef struct _cff_dict_operator {
128
    cairo_hash_entry_t base;
129

            
130
    unsigned short operator;
131
    unsigned char *operand;
132
    int            operand_length;
133
    int            operand_offset;
134
} cff_dict_operator_t;
135

            
136
typedef struct _cairo_cff_font {
137

            
138
    cairo_scaled_font_subset_t *scaled_font_subset;
139
    const cairo_scaled_font_backend_t *backend;
140

            
141
    /* Font Data */
142
    unsigned char       *data;
143
    unsigned long        data_length;
144
    unsigned char       *current_ptr;
145
    unsigned char       *data_end;
146
    cff_header_t        *header;
147
    char                *font_name;
148
    char                *ps_name;
149
    cairo_hash_table_t  *top_dict;
150
    cairo_hash_table_t  *private_dict;
151
    cairo_array_t        strings_index;
152
    cairo_array_t        charstrings_index;
153
    cairo_array_t        global_sub_index;
154
    cairo_array_t        local_sub_index;
155
    unsigned char       *charset;
156
    int                  num_glyphs;
157
    cairo_bool_t         is_cid;
158
    cairo_bool_t         is_opentype;
159
    int  		 units_per_em;
160
    int 		 global_sub_bias;
161
    int			 local_sub_bias;
162
    double               default_width;
163
    double               nominal_width;
164

            
165
    /* CID Font Data */
166
    int                 *fdselect;
167
    unsigned int         num_fontdicts;
168
    cairo_hash_table_t **fd_dict;
169
    cairo_hash_table_t **fd_private_dict;
170
    cairo_array_t       *fd_local_sub_index;
171
    int			*fd_local_sub_bias;
172
    double              *fd_default_width;
173
    double              *fd_nominal_width;
174

            
175
    /* Subsetted Font Data */
176
    char                *subset_font_name;
177
    cairo_array_t        charstrings_subset_index;
178
    cairo_array_t        strings_subset_index;
179
    int			 euro_sid;
180
    int                 *fdselect_subset;
181
    unsigned int         num_subset_fontdicts;
182
    int                 *fd_subset_map;
183
    int                 *private_dict_offset;
184
    cairo_bool_t         subset_subroutines;
185
    cairo_bool_t	*global_subs_used;
186
    cairo_bool_t	*local_subs_used;
187
    cairo_bool_t       **fd_local_subs_used;
188
    cairo_array_t        output;
189

            
190
    /* Subset Metrics */
191
    int                 *widths;
192
    int                  x_min, y_min, x_max, y_max;
193
    int                  ascent, descent;
194

            
195
    /* Type 2 charstring data */
196
    int 	 	 type2_stack_size;
197
    int 		 type2_stack_top_value;
198
    cairo_bool_t 	 type2_stack_top_is_int;
199
    int 		 type2_num_hints;
200
    int 		 type2_hintmask_bytes;
201
    int                  type2_nesting_level;
202
    cairo_bool_t         type2_seen_first_int;
203
    cairo_bool_t         type2_find_width;
204
    cairo_bool_t         type2_found_width;
205
    int                  type2_width;
206
    cairo_bool_t         type2_has_path;
207

            
208
} cairo_cff_font_t;
209

            
210
/* Encoded integer using maximum sized encoding. This is required for
211
 * operands that are later modified after encoding. */
212
static unsigned char *
213
encode_integer_max (unsigned char *p, int i)
214
{
215
    *p++ = 29;
216
    *p++ = i >> 24;
217
    *p++ = (i >> 16) & 0xff;
218
    *p++ = (i >> 8)  & 0xff;
219
    *p++ = i & 0xff;
220
    return p;
221
}
222

            
223
static unsigned char *
224
encode_integer (unsigned char *p, int i)
225
{
226
    if (i >= -107 && i <= 107) {
227
        *p++ = i + 139;
228
    } else if (i >= 108 && i <= 1131) {
229
        i -= 108;
230
        *p++ = (i >> 8)+ 247;
231
        *p++ = i & 0xff;
232
    } else if (i >= -1131 && i <= -108) {
233
        i = -i - 108;
234
        *p++ = (i >> 8)+ 251;
235
        *p++ = i & 0xff;
236
    } else if (i >= -32768 && i <= 32767) {
237
        *p++ = 28;
238
        *p++ = (i >> 8)  & 0xff;
239
        *p++ = i & 0xff;
240
    } else {
241
        p = encode_integer_max (p, i);
242
    }
243
    return p;
244
}
245

            
246
static unsigned char *
247
decode_integer (unsigned char *p, int *integer)
248
{
249
    if (*p == 28) {
250
        *integer = (int16_t)(p[1]<<8 | p[2]);
251
        p += 3;
252
    } else if (*p == 29) {
253
        *integer = (int32_t)(((uint32_t)p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]);
254
        p += 5;
255
    } else if (*p >= 32 && *p <= 246) {
256
        *integer = *p++ - 139;
257
    } else if (*p <= 250) {
258
        *integer = (p[0] - 247) * 256 + p[1] + 108;
259
        p += 2;
260
    } else if (*p <= 254) {
261
        *integer = -(p[0] - 251) * 256 - p[1] - 108;
262
        p += 2;
263
    } else {
264
        *integer = 0;
265
        p += 1;
266
    }
267
    return p;
268
}
269

            
270
static char *
271
decode_nibble (int n, char *buf)
272
{
273
    switch (n)
274
    {
275
    case 0xa:
276
	*buf++ = '.';
277
	break;
278
    case 0xb:
279
	*buf++ = 'E';
280
	break;
281
    case 0xc:
282
	*buf++ = 'E';
283
	*buf++ = '-';
284
	break;
285
    case 0xd:
286
	*buf++ = '-';
287
	break;
288
    case 0xe:
289
	*buf++ = '-';
290
	break;
291
    case 0xf:
292
	break;
293
    default:
294
	*buf++ = '0' + n;
295
	break;
296
    }
297

            
298
    return buf;
299
}
300

            
301
static unsigned char *
302
decode_real (unsigned char *p, double *real)
303
{
304
    char buffer[100];
305
    char *buf = buffer;
306
    char *buf_end = buffer + sizeof (buffer);
307
    char *end;
308
    int n;
309

            
310
    p++;
311
    while (buf + 2 < buf_end) {
312
	n = *p >> 4;
313
	buf = decode_nibble (n, buf);
314
	n = *p & 0x0f;
315
	buf = decode_nibble (n, buf);
316
        if ((*p & 0x0f) == 0x0f) {
317
	    p++;
318
            break;
319
	}
320
	p++;
321
    };
322
    *buf = 0;
323

            
324
    *real = _cairo_strtod (buffer, &end);
325

            
326
    return p;
327
}
328

            
329
static unsigned char *
330
decode_number (unsigned char *p, double *number)
331
{
332
    if (*p == 30) {
333
        p = decode_real (p, number);
334
    } else {
335
        int i;
336
        p = decode_integer (p, &i);
337
        *number = i;
338
    }
339
    return p;
340
}
341

            
342
static unsigned char *
343
decode_operator (unsigned char *p, unsigned short *operator)
344
{
345
    unsigned short op = 0;
346

            
347
    op = *p++;
348
    if (op == 12) {
349
        op <<= 8;
350
        op |= *p++;
351
    }
352
    *operator = op;
353
    return p;
354
}
355

            
356
/* return 0 if not an operand */
357
static int
358
operand_length (unsigned char *p)
359
{
360
    unsigned char *begin = p;
361

            
362
    if (*p == 28)
363
        return 3;
364

            
365
    if (*p == 29)
366
        return 5;
367

            
368
    if (*p >= 32 && *p <= 246)
369
        return 1;
370

            
371
    if (*p >= 247 && *p <= 254)
372
        return 2;
373

            
374
    if (*p == 30) {
375
        while ((*p & 0x0f) != 0x0f)
376
            p++;
377
        return p - begin + 1;
378
    }
379

            
380
    return 0;
381
}
382

            
383
static unsigned char *
384
encode_index_offset (unsigned char *p, int offset_size, unsigned long offset)
385
{
386
    while (--offset_size >= 0) {
387
        p[offset_size] = (unsigned char) (offset & 0xff);
388
        offset >>= 8;
389
    }
390
    return p + offset_size;
391
}
392

            
393
static size_t
394
decode_index_offset(unsigned char *p, int off_size)
395
{
396
    unsigned long offset = 0;
397

            
398
    while (off_size-- > 0)
399
        offset = offset*256 + *p++;
400
    return offset;
401
}
402

            
403
static void
404
cff_index_init (cairo_array_t *index)
405
{
406
    _cairo_array_init (index, sizeof (cff_index_element_t));
407
}
408

            
409
static cairo_int_status_t
410
cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_ptr)
411
{
412
    cff_index_element_t element;
413
    unsigned char *data, *p;
414
    cairo_status_t status;
415
    int offset_size, count, i;
416
    size_t start, end = 0;
417

            
418
    p = *ptr;
419
    if (p + 2 > end_ptr)
420
        return CAIRO_INT_STATUS_UNSUPPORTED;
421
    count = get_unaligned_be16 (p);
422
    p += 2;
423
    if (count > 0) {
424
        offset_size = *p++;
425
        if (p + (count + 1)*offset_size > end_ptr || offset_size > 4)
426
            return CAIRO_INT_STATUS_UNSUPPORTED;
427
        data = p + offset_size*(count + 1) - 1;
428
        start = decode_index_offset (p, offset_size);
429
        p += offset_size;
430
        for (i = 0; i < count; i++) {
431
            end = decode_index_offset (p, offset_size);
432
            p += offset_size;
433
            if (p > end_ptr || end < start || data + end > end_ptr)
434
                return CAIRO_INT_STATUS_UNSUPPORTED;
435
            element.length = end - start;
436
            element.is_copy = FALSE;
437
            element.data = data + start;
438
            status = _cairo_array_append (index, &element);
439
            if (unlikely (status))
440
                return status;
441
            start = end;
442
        }
443
        p = data + end;
444
    }
445
    *ptr = p;
446

            
447
    return CAIRO_STATUS_SUCCESS;
448
}
449

            
450
static cairo_status_t
451
cff_index_write (cairo_array_t *index, cairo_array_t *output)
452
{
453
    int offset_size;
454
    int offset;
455
    int num_elem;
456
    int i;
457
    cff_index_element_t *element;
458
    uint16_t count;
459
    unsigned char buf[5];
460
    cairo_status_t status;
461

            
462
    num_elem = _cairo_array_num_elements (index);
463
    count = cpu_to_be16 ((uint16_t) num_elem);
464
    status = _cairo_array_append_multiple (output, &count, 2);
465
    if (unlikely (status))
466
        return status;
467

            
468
    if (num_elem == 0)
469
        return CAIRO_STATUS_SUCCESS;
470

            
471
    /* Find maximum offset to determine offset size */
472
    offset = 1;
473
    for (i = 0; i < num_elem; i++) {
474
        element = _cairo_array_index (index, i);
475
        offset += element->length;
476
    }
477
    if (offset < 0x100)
478
        offset_size = 1;
479
    else if (offset < 0x10000)
480
        offset_size = 2;
481
    else if (offset < 0x1000000)
482
        offset_size = 3;
483
    else
484
        offset_size = 4;
485

            
486
    buf[0] = (unsigned char) offset_size;
487
    status = _cairo_array_append (output, buf);
488
    if (unlikely (status))
489
        return status;
490

            
491
    offset = 1;
492
    encode_index_offset (buf, offset_size, offset);
493
    status = _cairo_array_append_multiple (output, buf, offset_size);
494
    if (unlikely (status))
495
        return status;
496

            
497
    for (i = 0; i < num_elem; i++) {
498
        element = _cairo_array_index (index, i);
499
        offset += element->length;
500
        encode_index_offset (buf, offset_size, offset);
501
        status = _cairo_array_append_multiple (output, buf, offset_size);
502
        if (unlikely (status))
503
            return status;
504
    }
505

            
506
    for (i = 0; i < num_elem; i++) {
507
        element = _cairo_array_index (index, i);
508
        if (element->length > 0) {
509
            status = _cairo_array_append_multiple (output,
510
                                                   element->data,
511
                                                   element->length);
512
        }
513
        if (unlikely (status))
514
            return status;
515
    }
516
    return CAIRO_STATUS_SUCCESS;
517
}
518

            
519
static void
520
cff_index_set_object (cairo_array_t *index, int obj_index,
521
                      unsigned char *object , int length)
522
{
523
    cff_index_element_t *element;
524

            
525
    element = _cairo_array_index (index, obj_index);
526
    if (element->is_copy)
527
        free (element->data);
528

            
529
    element->data = object;
530
    element->length = length;
531
    element->is_copy = FALSE;
532
}
533

            
534
static cairo_status_t
535
cff_index_append (cairo_array_t *index, unsigned char *object , int length)
536
{
537
    cff_index_element_t element;
538

            
539
    element.length = length;
540
    element.is_copy = FALSE;
541
    element.data = object;
542

            
543
    return _cairo_array_append (index, &element);
544
}
545

            
546
static cairo_status_t
547
cff_index_append_copy (cairo_array_t *index,
548
                       const unsigned char *object,
549
                       unsigned int length)
550
{
551
    cff_index_element_t element;
552
    cairo_status_t status;
553

            
554
    element.length = length;
555
    element.is_copy = TRUE;
556
    element.data = _cairo_malloc (element.length);
557
    if (unlikely (element.data == NULL && length != 0))
558
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
559

            
560
    memcpy (element.data, object, element.length);
561

            
562
    status = _cairo_array_append (index, &element);
563
    if (unlikely (status)) {
564
	free (element.data);
565
	return status;
566
    }
567

            
568
    return CAIRO_STATUS_SUCCESS;
569
}
570

            
571
static void
572
cff_index_fini (cairo_array_t *index)
573
{
574
    cff_index_element_t *element;
575
    unsigned int i;
576

            
577
    for (i = 0; i < _cairo_array_num_elements (index); i++) {
578
        element = _cairo_array_index (index, i);
579
        if (element->is_copy && element->data)
580
            free (element->data);
581
    }
582
    _cairo_array_fini (index);
583
}
584

            
585
static cairo_bool_t
586
_cairo_cff_dict_equal (const void *key_a, const void *key_b)
587
{
588
    const cff_dict_operator_t *op_a = key_a;
589
    const cff_dict_operator_t *op_b = key_b;
590

            
591
    return op_a->operator == op_b->operator;
592
}
593

            
594
static cairo_status_t
595
cff_dict_init (cairo_hash_table_t **dict)
596
{
597
    *dict = _cairo_hash_table_create (_cairo_cff_dict_equal);
598
    if (unlikely (*dict == NULL))
599
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
600

            
601
    return CAIRO_STATUS_SUCCESS;
602
}
603

            
604
static void
605
_cairo_dict_init_key (cff_dict_operator_t *key, int operator)
606
{
607
    key->base.hash = (unsigned long) operator;
608
    key->operator = operator;
609
}
610

            
611
static cairo_status_t
612
cff_dict_create_operator (int            operator,
613
                          unsigned char *operand,
614
                          int            size,
615
			  cff_dict_operator_t **out)
616
{
617
    cff_dict_operator_t *op;
618

            
619
    op = _cairo_calloc (sizeof (cff_dict_operator_t));
620
    if (unlikely (op == NULL))
621
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
622

            
623
    _cairo_dict_init_key (op, operator);
624
    if (size != 0) {
625
	op->operand = _cairo_malloc (size);
626
	if (unlikely (op->operand == NULL)) {
627
	    free (op);
628
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
629
	}
630
	memcpy (op->operand, operand, size);
631
    } else {
632
	op->operand = NULL;
633
	/* Delta-encoded arrays can be empty. */
634
	if (operator != BLUEVALUES_OP &&
635
	    operator != OTHERBLUES_OP &&
636
	    operator != FAMILYBLUES_OP &&
637
	    operator != FAMILYOTHERBLUES_OP &&
638
	    operator != STEMSNAPH_OP &&
639
	    operator != STEMSNAPV_OP) {
640
	    free (op);
641
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
642
	}
643
    }
644

            
645
    op->operand_length = size;
646
    op->operand_offset = -1;
647

            
648
    *out = op;
649
    return CAIRO_STATUS_SUCCESS;
650
}
651

            
652
static cairo_status_t
653
cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size)
654
{
655
    unsigned char *end;
656
    cairo_array_t operands;
657
    cff_dict_operator_t *op;
658
    unsigned short operator;
659
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
660
    int size;
661

            
662
    end = p + dict_size;
663
    _cairo_array_init (&operands, 1);
664
    while (p < end) {
665
        size = operand_length (p);
666
        if (size != 0) {
667
            status = _cairo_array_append_multiple (&operands, p, size);
668
            if (unlikely (status))
669
                goto fail;
670

            
671
            p += size;
672
        } else {
673
            p = decode_operator (p, &operator);
674
            status = cff_dict_create_operator (operator,
675
                                          _cairo_array_index (&operands, 0),
676
                                          _cairo_array_num_elements (&operands),
677
					  &op);
678
            if (unlikely (status))
679
                goto fail;
680

            
681
            status = _cairo_hash_table_insert (dict, &op->base);
682
            if (unlikely (status))
683
                goto fail;
684

            
685
            _cairo_array_truncate (&operands, 0);
686
        }
687
    }
688

            
689
fail:
690
    _cairo_array_fini (&operands);
691

            
692
    return status;
693
}
694

            
695
static void
696
cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
697
{
698
    cff_dict_operator_t key, *op;
699

            
700
    _cairo_dict_init_key (&key, operator);
701
    op = _cairo_hash_table_lookup (dict, &key.base);
702
    if (op != NULL) {
703
        free (op->operand);
704
        _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
705
        free (op);
706
    }
707
}
708

            
709
static unsigned char *
710
cff_dict_get_operands (cairo_hash_table_t *dict,
711
                       unsigned short      operator,
712
                       int                *size)
713
{
714
    cff_dict_operator_t key, *op;
715

            
716
    _cairo_dict_init_key (&key, operator);
717
    op = _cairo_hash_table_lookup (dict, &key.base);
718
    if (op != NULL) {
719
        *size = op->operand_length;
720
        return op->operand;
721
    }
722

            
723
    return NULL;
724
}
725

            
726
static cairo_status_t
727
cff_dict_set_operands (cairo_hash_table_t *dict,
728
                       unsigned short      operator,
729
                       unsigned char      *operand,
730
                       int                 size)
731
{
732
    cff_dict_operator_t key, *op;
733
    cairo_status_t status;
734

            
735
    _cairo_dict_init_key (&key, operator);
736
    op = _cairo_hash_table_lookup (dict, &key.base);
737
    if (op != NULL) {
738
        free (op->operand);
739
        op->operand = _cairo_malloc (size);
740
	if (unlikely (op->operand == NULL))
741
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
742

            
743
        memcpy (op->operand, operand, size);
744
        op->operand_length = size;
745
    }
746
    else
747
    {
748
        status = cff_dict_create_operator (operator, operand, size, &op);
749
        if (unlikely (status))
750
	    return status;
751

            
752
	status = _cairo_hash_table_insert (dict, &op->base);
753
	if (unlikely (status))
754
	    return status;
755
    }
756

            
757
    return CAIRO_STATUS_SUCCESS;
758
}
759

            
760
static int
761
cff_dict_get_location (cairo_hash_table_t *dict,
762
                       unsigned short      operator,
763
                       int                *size)
764
{
765
    cff_dict_operator_t key, *op;
766

            
767
    _cairo_dict_init_key (&key, operator);
768
    op = _cairo_hash_table_lookup (dict, &key.base);
769
    if (op != NULL) {
770
        *size = op->operand_length;
771
        return op->operand_offset;
772
    }
773

            
774
    return -1;
775
}
776

            
777
typedef struct _dict_write_info {
778
    cairo_array_t *output;
779
    cairo_status_t status;
780
} dict_write_info_t;
781

            
782
static void
783
cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info)
784
{
785
    unsigned char data;
786

            
787
    op->operand_offset = _cairo_array_num_elements (write_info->output);
788
    write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length);
789
    if (write_info->status)
790
        return;
791

            
792
    if (op->operator & 0xff00) {
793
        data = op->operator >> 8;
794
        write_info->status = _cairo_array_append (write_info->output, &data);
795
        if (write_info->status)
796
            return;
797
    }
798
    data = op->operator & 0xff;
799
    write_info->status = _cairo_array_append (write_info->output, &data);
800
}
801

            
802
static void
803
_cairo_dict_collect (void *entry, void *closure)
804
{
805
    dict_write_info_t   *write_info = closure;
806
    cff_dict_operator_t *op = entry;
807

            
808
    if (write_info->status)
809
        return;
810

            
811
    /* The ROS operator is handled separately in cff_dict_write() */
812
    if (op->operator != ROS_OP)
813
        cairo_dict_write_operator (op, write_info);
814
}
815

            
816
static cairo_status_t
817
cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output)
818
{
819
    dict_write_info_t write_info;
820
    cff_dict_operator_t key, *op;
821

            
822
    write_info.output = output;
823
    write_info.status = CAIRO_STATUS_SUCCESS;
824

            
825
    /* The CFF specification requires that the Top Dict of CID fonts
826
     * begin with the ROS operator. */
827
    _cairo_dict_init_key (&key, ROS_OP);
828
    op = _cairo_hash_table_lookup (dict, &key.base);
829
    if (op != NULL)
830
        cairo_dict_write_operator (op, &write_info);
831

            
832
    _cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info);
833

            
834
    return write_info.status;
835
}
836

            
837
static void
838
_cff_dict_entry_pluck (void *_entry, void *dict)
839
{
840
    cff_dict_operator_t *entry = _entry;
841

            
842
    _cairo_hash_table_remove (dict, &entry->base);
843
    free (entry->operand);
844
    free (entry);
845
}
846

            
847
static void
848
cff_dict_fini (cairo_hash_table_t *dict)
849
{
850
    _cairo_hash_table_foreach (dict, _cff_dict_entry_pluck, dict);
851
    _cairo_hash_table_destroy (dict);
852
}
853

            
854
static cairo_int_status_t
855
cairo_cff_font_read_header (cairo_cff_font_t *font)
856
{
857
    if (font->data_length < sizeof (cff_header_t))
858
        return CAIRO_INT_STATUS_UNSUPPORTED;
859

            
860

            
861
    font->header = (cff_header_t *) font->data;
862
    font->current_ptr = font->data + font->header->header_size;
863

            
864
    return CAIRO_STATUS_SUCCESS;
865
}
866

            
867
static cairo_int_status_t
868
cairo_cff_font_read_name (cairo_cff_font_t *font)
869
{
870
    cairo_array_t index;
871
    cairo_int_status_t status;
872
    cff_index_element_t *element;
873
    unsigned char *p;
874
    int i, len;
875

            
876
    cff_index_init (&index);
877
    status = cff_index_read (&index, &font->current_ptr, font->data_end);
878
    if (status == CAIRO_INT_STATUS_SUCCESS && !font->is_opentype) {
879
        element = _cairo_array_index (&index, 0);
880
	p = element->data;
881
	len = element->length;
882

            
883
	/* If font name is prefixed with a subset tag, strip it off. */
884
	if (len > 7 && p[6] == '+') {
885
	    for (i = 0; i < 6; i++)
886
		if (p[i] < 'A' || p[i] > 'Z')
887
		    break;
888
	    if (i == 6) {
889
		p += 7;
890
		len -= 7;
891
	    }
892
	}
893

            
894
	font->ps_name = _cairo_strndup ((char*)p, len);
895
	if (unlikely (font->ps_name == NULL))
896
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
897

            
898
        status = _cairo_escape_ps_name (&font->ps_name);
899
    }
900
    cff_index_fini (&index);
901

            
902
    return status;
903
}
904

            
905
static cairo_int_status_t
906
cairo_cff_font_read_private_dict (cairo_cff_font_t   *font,
907
                                  cairo_hash_table_t *private_dict,
908
                                  cairo_array_t      *local_sub_index,
909
                                  int                *local_sub_bias,
910
                                  cairo_bool_t      **local_subs_used,
911
                                  double             *default_width,
912
                                  double             *nominal_width,
913
                                  unsigned char      *ptr,
914
                                  int                 size)
915
{
916
    cairo_int_status_t status;
917
    unsigned char buf[10];
918
    unsigned char *end_buf;
919
    int offset;
920
    int i;
921
    unsigned char *operand;
922
    unsigned char *p;
923
    int num_subs;
924

            
925
    status = cff_dict_read (private_dict, ptr, size);
926
    if (unlikely (status))
927
	return status;
928

            
929
    operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
930
    if (operand) {
931
        decode_integer (operand, &offset);
932
        p = ptr + offset;
933
        status = cff_index_read (local_sub_index, &p, font->data_end);
934
	if (unlikely (status))
935
	    return status;
936

            
937
	/* Use maximum sized encoding to reserve space for later modification. */
938
	end_buf = encode_integer_max (buf, 0);
939
	status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
940
	if (unlikely (status))
941
	    return status;
942
    }
943

            
944
    *default_width = 0;
945
    operand = cff_dict_get_operands (private_dict, DEFAULTWIDTH_OP, &i);
946
    if (operand)
947
        decode_number (operand, default_width);
948

            
949
    *nominal_width = 0;
950
    operand = cff_dict_get_operands (private_dict, NOMINALWIDTH_OP, &i);
951
    if (operand)
952
	 decode_number (operand, nominal_width);
953

            
954
    num_subs = _cairo_array_num_elements (local_sub_index);
955
    if (num_subs > 0) {
956
	*local_subs_used = _cairo_calloc_ab (num_subs, sizeof (cairo_bool_t));
957
	if (unlikely (*local_subs_used == NULL))
958
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
959
    } else {
960
	*local_subs_used = NULL;
961
    }
962

            
963
    if (num_subs < 1240)
964
	*local_sub_bias = 107;
965
    else if (num_subs < 33900)
966
	*local_sub_bias = 1131;
967
    else
968
	*local_sub_bias = 32768;
969

            
970
    return CAIRO_STATUS_SUCCESS;
971
}
972

            
973
static cairo_int_status_t
974
cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p)
975
{
976
    int type, num_ranges, first, last, fd, i, j;
977

            
978
    font->fdselect = _cairo_calloc_ab (font->num_glyphs, sizeof (int));
979
    if (unlikely (font->fdselect == NULL))
980
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
981

            
982
    type = *p++;
983
    if (type == 0)
984
    {
985
        for (i = 0; i < font->num_glyphs; i++)
986
            font->fdselect[i] = *p++;
987
    } else if (type == 3) {
988
        num_ranges = get_unaligned_be16 (p);
989
        p += 2;
990
        for  (i = 0; i < num_ranges; i++)
991
        {
992
            first = get_unaligned_be16 (p);
993
            p += 2;
994
            fd = *p++;
995
            last = get_unaligned_be16 (p);
996
            if (last > font->num_glyphs)
997
                return CAIRO_INT_STATUS_UNSUPPORTED;
998
            for (j = first; j < last; j++)
999
                font->fdselect[j] = fd;
        }
    } else {
        return CAIRO_INT_STATUS_UNSUPPORTED;
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
{
    cairo_array_t index;
    cff_index_element_t *element;
    unsigned int i;
    int size;
    unsigned char *operand;
    int offset;
    cairo_int_status_t status;
    unsigned char buf[100];
    unsigned char *end_buf;
    cff_index_init (&index);
    status = cff_index_read (&index, &ptr, font->data_end);
    if (unlikely (status))
        goto fail;
    font->num_fontdicts = _cairo_array_num_elements (&index);
    font->fd_dict = _cairo_calloc_ab (font->num_fontdicts, sizeof (cairo_hash_table_t *));
    if (unlikely (font->fd_dict == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        goto fail;
    }
    font->fd_private_dict = _cairo_calloc_ab (font->num_fontdicts, sizeof (cairo_hash_table_t *));
    if (unlikely (font->fd_private_dict == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        goto fail;
    }
    font->fd_local_sub_index = _cairo_calloc_ab (font->num_fontdicts, sizeof (cairo_array_t));
    if (unlikely (font->fd_local_sub_index == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        goto fail;
    }
    font->fd_local_sub_bias = _cairo_calloc_ab (font->num_fontdicts, sizeof (int));
    if (unlikely (font->fd_local_sub_bias == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        goto fail;
    }
    font->fd_local_subs_used = _cairo_calloc_ab (font->num_fontdicts, sizeof (cairo_bool_t *));
    if (unlikely (font->fd_local_subs_used == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        goto fail;
    }
    font->fd_default_width = _cairo_calloc_ab (font->num_fontdicts, sizeof (double));
    if (unlikely (font->fd_default_width == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        goto fail;
    }
    font->fd_nominal_width = _cairo_calloc_ab (font->num_fontdicts, sizeof (double));
    if (unlikely (font->fd_nominal_width == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        goto fail;
    }
    for (i = 0; i < font->num_fontdicts; i++) {
        status = cff_dict_init (&font->fd_dict[i]);
        if (unlikely (status))
            goto fail;
        element = _cairo_array_index (&index, i);
        status = cff_dict_read (font->fd_dict[i], element->data, element->length);
        if (unlikely (status))
            goto fail;
        operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size);
        if (operand == NULL) {
            status = CAIRO_INT_STATUS_UNSUPPORTED;
            goto fail;
        }
        operand = decode_integer (operand, &size);
        decode_integer (operand, &offset);
        status = cff_dict_init (&font->fd_private_dict[i]);
	if (unlikely (status))
            goto fail;
        cff_index_init (&font->fd_local_sub_index[i]);
        status = cairo_cff_font_read_private_dict (font,
                                                   font->fd_private_dict[i],
                                                   &font->fd_local_sub_index[i],
                                                   &font->fd_local_sub_bias[i],
                                                   &font->fd_local_subs_used[i],
                                                   &font->fd_default_width[i],
                                                   &font->fd_nominal_width[i],
                                                   font->data + offset,
                                                   size);
        if (unlikely (status))
            goto fail;
	/* Set integer operand to max value to use max size encoding to reserve
         * space for any value later */
        end_buf = encode_integer_max (buf, 0);
        end_buf = encode_integer_max (end_buf, 0);
        status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf);
        if (unlikely (status))
            goto fail;
    }
    status = CAIRO_STATUS_SUCCESS;
fail:
    cff_index_fini (&index);
    return status;
}
static void
cairo_cff_font_read_font_metrics (cairo_cff_font_t *font, cairo_hash_table_t  *top_dict)
{
    unsigned char *p;
    unsigned char *end;
    int size;
    double x_min, y_min, x_max, y_max;
    double xx, yx, xy, yy;
    x_min = 0.0;
    y_min = 0.0;
    x_max = 0.0;
    y_max = 0.0;
    p = cff_dict_get_operands (font->top_dict, FONTBBOX_OP, &size);
    if (p) {
        end = p + size;
        if (p < end)
            p = decode_number (p, &x_min);
        if (p < end)
            p = decode_number (p, &y_min);
        if (p < end)
            p = decode_number (p, &x_max);
        if (p < end)
            p = decode_number (p, &y_max);
    }
    font->x_min = floor (x_min);
    font->y_min = floor (y_min);
    font->x_max = floor (x_max);
    font->y_max = floor (y_max);
    font->ascent = font->y_max;
    font->descent = font->y_min;
    xx = 0.001;
    yx = 0.0;
    xy = 0.0;
    yy = 0.001;
    p = cff_dict_get_operands (font->top_dict, FONTMATRIX_OP, &size);
    if (p) {
        end = p + size;
        if (p < end)
            p = decode_number (p, &xx);
        if (p < end)
            p = decode_number (p, &yx);
        if (p < end)
            p = decode_number (p, &xy);
        if (p < end)
            p = decode_number (p, &yy);
    }
    /* FreeType uses 1/abs(yy) to get units per EM */
    font->units_per_em = _cairo_round(1.0/fabs(yy));
}
static cairo_int_status_t
cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
{
    cairo_array_t index;
    cff_index_element_t *element;
    unsigned char buf[20];
    unsigned char *end_buf;
    unsigned char *operand;
    cairo_int_status_t status;
    unsigned char *p;
    int size;
    int offset;
    cff_index_init (&index);
    status = cff_index_read (&index, &font->current_ptr, font->data_end);
    if (unlikely (status))
        goto fail;
    element = _cairo_array_index (&index, 0);
    if (element == NULL)
        return CAIRO_STATUS_NO_MEMORY;
    status = cff_dict_read (font->top_dict, element->data, element->length);
    if (unlikely (status))
        goto fail;
    if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL)
        font->is_cid = TRUE;
    else
        font->is_cid = FALSE;
    operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size);
    decode_integer (operand, &offset);
    p = font->data + offset;
    status = cff_index_read (&font->charstrings_index, &p, font->data_end);
    if (unlikely (status))
        goto fail;
    font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index);
    if (font->is_cid) {
	 operand = cff_dict_get_operands (font->top_dict, CHARSET_OP, &size);
	 if (!operand)
	      return CAIRO_INT_STATUS_UNSUPPORTED;
	 decode_integer (operand, &offset);
	 font->charset = font->data + offset;
	 if (font->charset >= font->data_end)
	      return CAIRO_INT_STATUS_UNSUPPORTED;
    }
    if (!font->is_opentype)
        cairo_cff_font_read_font_metrics (font, font->top_dict);
    if (font->is_cid) {
        operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
        decode_integer (operand, &offset);
        status = cairo_cff_font_read_fdselect (font, font->data + offset);
	if (unlikely (status))
	    goto fail;
        operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
        decode_integer (operand, &offset);
        status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
	if (unlikely (status))
	    goto fail;
    } else {
        operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
        operand = decode_integer (operand, &size);
        decode_integer (operand, &offset);
	status = cairo_cff_font_read_private_dict (font,
                                                   font->private_dict,
						   &font->local_sub_index,
						   &font->local_sub_bias,
						   &font->local_subs_used,
                                                   &font->default_width,
                                                   &font->nominal_width,
						   font->data + offset,
						   size);
	if (unlikely (status))
	    goto fail;
    }
    /* Use maximum sized encoding to reserve space for later modification. */
    end_buf = encode_integer_max (buf, 0);
    status = cff_dict_set_operands (font->top_dict,
	                            CHARSTRINGS_OP, buf, end_buf - buf);
    if (unlikely (status))
	goto fail;
    status = cff_dict_set_operands (font->top_dict,
	                            CHARSET_OP, buf, end_buf - buf);
    if (unlikely (status))
	goto fail;
    if (font->scaled_font_subset->is_latin) {
        status = cff_dict_set_operands (font->top_dict,
                                        ENCODING_OP, buf, end_buf - buf);
        if (unlikely (status))
            goto fail;
	/* Private has two operands - size and offset */
	end_buf = encode_integer_max (end_buf, 0);
	cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf - buf);
        if (unlikely (status))
            goto fail;
    } else {
        status = cff_dict_set_operands (font->top_dict,
                                        FDSELECT_OP, buf, end_buf - buf);
        if (unlikely (status))
            goto fail;
        status = cff_dict_set_operands (font->top_dict,
                                        FDARRAY_OP, buf, end_buf - buf);
        if (unlikely (status))
            goto fail;
        cff_dict_remove (font->top_dict, ENCODING_OP);
        cff_dict_remove (font->top_dict, PRIVATE_OP);
    }
    /* Remove the unique identifier operators as the subsetted font is
     * not the same is the original font. */
    cff_dict_remove (font->top_dict, UNIQUEID_OP);
    cff_dict_remove (font->top_dict, XUID_OP);
fail:
    cff_index_fini (&index);
    return status;
}
static cairo_int_status_t
cairo_cff_font_read_strings (cairo_cff_font_t *font)
{
    return cff_index_read (&font->strings_index, &font->current_ptr, font->data_end);
}
static cairo_int_status_t
cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font)
{
    cairo_int_status_t status;
    int num_subs;
    status = cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end);
    if (unlikely (status))
	return status;
    num_subs = _cairo_array_num_elements (&font->global_sub_index);
    if (num_subs > 0) {
	font->global_subs_used = _cairo_calloc_ab (num_subs, sizeof(cairo_bool_t));
	if (unlikely (font->global_subs_used == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    } else {
	font->global_subs_used = NULL;
    }
    if (num_subs < 1240)
        font->global_sub_bias = 107;
    else if (num_subs < 33900)
        font->global_sub_bias = 1131;
    else
        font->global_sub_bias = 32768;
    return CAIRO_STATUS_SUCCESS;
}
typedef cairo_int_status_t
(*font_read_t) (cairo_cff_font_t *font);
static const font_read_t font_read_funcs[] = {
    cairo_cff_font_read_header,
    cairo_cff_font_read_name,
    cairo_cff_font_read_top_dict,
    cairo_cff_font_read_strings,
    cairo_cff_font_read_global_subroutines,
};
static cairo_int_status_t
cairo_cff_font_read_font (cairo_cff_font_t *font)
{
    cairo_int_status_t status;
    unsigned int i;
    for (i = 0; i < ARRAY_LENGTH (font_read_funcs); i++) {
        status = font_read_funcs[i] (font);
        if (unlikely (status))
            return status;
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
{
    cairo_status_t status;
    unsigned char buf[30];
    unsigned char *p;
    int sid1, sid2;
    const char *registry = "Adobe";
    const char *ordering = "Identity";
    sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
    status = cff_index_append_copy (&font->strings_subset_index,
                                    (unsigned char *)registry,
                                    strlen(registry));
    if (unlikely (status))
	return status;
    sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
    status = cff_index_append_copy (&font->strings_subset_index,
                                    (unsigned char *)ordering,
				    strlen(ordering));
    if (unlikely (status))
	return status;
    p = encode_integer (buf, sid1);
    p = encode_integer (p, sid2);
    p = encode_integer (p, 0);
    status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
    if (unlikely (status))
	return status;
    p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
    status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
    if (unlikely (status))
	return status;
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_subset_dict_string(cairo_cff_font_t   *font,
                                  cairo_hash_table_t *dict,
                                  int                 operator)
{
    int size;
    unsigned char *p;
    int sid;
    unsigned char buf[100];
    cff_index_element_t *element;
    cairo_status_t status;
    p = cff_dict_get_operands (dict, operator, &size);
    if (!p)
        return CAIRO_STATUS_SUCCESS;
    decode_integer (p, &sid);
    if (sid < NUM_STD_STRINGS)
        return CAIRO_STATUS_SUCCESS;
    element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS);
    sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
    status = cff_index_append (&font->strings_subset_index, element->data, element->length);
    if (unlikely (status))
        return status;
    p = encode_integer (buf, sid);
    status = cff_dict_set_operands (dict, operator, buf, p - buf);
    if (unlikely (status))
	return status;
    return CAIRO_STATUS_SUCCESS;
}
static const int dict_strings[] = {
    VERSION_OP,
    NOTICE_OP,
    COPYRIGHT_OP,
    FULLNAME_OP,
    FAMILYNAME_OP,
    WEIGHT_OP,
    POSTSCRIPT_OP,
    BASEFONTNAME_OP,
    FONTNAME_OP,
};
static cairo_status_t
cairo_cff_font_subset_dict_strings (cairo_cff_font_t   *font,
                                    cairo_hash_table_t *dict)
{
    cairo_status_t status;
    unsigned int i;
    for (i = 0; i < ARRAY_LENGTH (dict_strings); i++) {
        status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]);
        if (unlikely (status))
            return status;
    }
    return CAIRO_STATUS_SUCCESS;
}
static unsigned char *
type2_decode_integer (unsigned char *p, int *integer)
{
    if (*p == 28) {
	*integer = p[1] << 8 | p[2];
	p += 3;
    } else if (*p <= 246) {
        *integer = *p++ - 139;
    } else if (*p <= 250) {
        *integer = (p[0] - 247) * 256 + p[1] + 108;
        p += 2;
    } else if (*p <= 254) {
        *integer = -(p[0] - 251) * 256 - p[1] - 108;
        p += 2;
    } else { /* *p == 255 */
	 /* 16.16 fixed-point number. The fraction is ignored. */
	 *integer = (int16_t)((p[1] << 8) | p[2]);
        p += 5;
    }
    return p;
}
/* Type 2 charstring parser for finding calls to local or global
 * subroutines. For non Opentype CFF fonts it also gets the glyph
 * widths.
 *
 * When we find a subroutine operator, the subroutine is marked as in
 * use and recursively followed. The subroutine number is the value on
 * the top of the stack when the subroutine operator is executed. In
 * most fonts the subroutine number is encoded in an integer
 * immediately preceding the subroutine operator. However it is
 * possible for the subroutine number on the stack to be the result of
 * a computation (in which case there will be an operator preceding
 * the subroutine operator). If this occurs, subroutine subsetting is
 * disabled since we can't easily determine which subroutines are
 * used.
 *
 * The width, if present, is the first integer in the charstring. The
 * only way to confirm if the integer at the start of the charstring is
 * the width is when the first stack clearing operator is parsed,
 * check if there is an extra integer left over on the stack.
 *
 * When the first stack clearing operator is encountered
 * type2_find_width is set to FALSE and type2_found_width is set to
 * TRUE if an extra argument is found, otherwise FALSE.
 */
static cairo_status_t
cairo_cff_parse_charstring (cairo_cff_font_t *font,
                            unsigned char *charstring, int length,
                            int glyph_id,
			    cairo_bool_t need_width)
{
    unsigned char *p = charstring;
    unsigned char *end = charstring + length;
    int integer;
    int hint_bytes;
    int sub_num;
    cff_index_element_t *element;
    int fd;
    while (p < end) {
        if (*p == 28 || *p >= 32) {
            /* Integer value */
            p = type2_decode_integer (p, &integer);
            font->type2_stack_size++;
            font->type2_stack_top_value = integer;
            font->type2_stack_top_is_int = TRUE;
	    if (!font->type2_seen_first_int) {
		font->type2_width = integer;
		font->type2_seen_first_int = TRUE;
	    }
	} else if (*p == TYPE2_hstem || *p == TYPE2_vstem ||
		   *p == TYPE2_hstemhm || *p == TYPE2_vstemhm) {
            /* Hint operator. The number of hints declared by the
             * operator depends on the size of the stack. */
	    font->type2_stack_top_is_int = FALSE;
	    font->type2_num_hints += font->type2_stack_size/2;
	    if (font->type2_find_width && font->type2_stack_size % 2)
		font->type2_found_width = TRUE;
	    font->type2_stack_size = 0;
	    font->type2_find_width = FALSE;
	    p++;
	} else if (*p == TYPE2_hintmask || *p == TYPE2_cntrmask) {
	    /* Hintmask operator. These operators are followed by a
	     * variable length mask where the length depends on the
	     * number of hints declared. The first time this is called
	     * it is also an implicit vstem if there are arguments on
	     * the stack. */
	    if (font->type2_hintmask_bytes == 0) {
		font->type2_stack_top_is_int = FALSE;
		font->type2_num_hints += font->type2_stack_size/2;
		if (font->type2_find_width && font->type2_stack_size % 2)
		    font->type2_found_width = TRUE;
		font->type2_stack_size = 0;
		font->type2_find_width = FALSE;
		font->type2_hintmask_bytes = (font->type2_num_hints+7)/8;
	    }
	    hint_bytes = font->type2_hintmask_bytes;
	    p++;
	    p += hint_bytes;
	} else if (*p == TYPE2_rmoveto) {
	    if (font->type2_find_width && font->type2_stack_size > 2)
		font->type2_found_width = TRUE;
	    font->type2_stack_size = 0;
	    font->type2_find_width = FALSE;
	    font->type2_has_path = TRUE;
	    p++;
	} else if (*p == TYPE2_hmoveto || *p == TYPE2_vmoveto) {
	    if (font->type2_find_width && font->type2_stack_size > 1)
		font->type2_found_width = TRUE;
	    font->type2_stack_size = 0;
	    font->type2_find_width = FALSE;
	    font->type2_has_path = TRUE;
	    p++;
	} else if (*p == TYPE2_endchar) {
	    if (!font->type2_has_path && font->type2_stack_size > 3)
		return CAIRO_INT_STATUS_UNSUPPORTED; /* seac (Ref Appendix C of Type 2 Charstring Format */
	    if (font->type2_find_width && font->type2_stack_size > 0)
		font->type2_found_width = TRUE;
	    return CAIRO_STATUS_SUCCESS;
        } else if (*p == TYPE2_callsubr) {
            /* call to local subroutine */
	    if (! font->type2_stack_top_is_int)
		return CAIRO_INT_STATUS_UNSUPPORTED;
            if (++font->type2_nesting_level > MAX_SUBROUTINE_NESTING)
		return CAIRO_INT_STATUS_UNSUPPORTED;
            p++;
	    font->type2_stack_top_is_int = FALSE;
            font->type2_stack_size--;
	    if (font->type2_find_width && font->type2_stack_size == 0)
		font->type2_seen_first_int = FALSE;
            if (font->is_cid) {
                fd = font->fdselect[glyph_id];
		sub_num = font->type2_stack_top_value + font->fd_local_sub_bias[fd];
		if (sub_num >= (int)_cairo_array_num_elements(&font->fd_local_sub_index[fd]))
		    return CAIRO_INT_STATUS_UNSUPPORTED;
                element = _cairo_array_index (&font->fd_local_sub_index[fd], sub_num);
                if (! font->fd_local_subs_used[fd][sub_num]) {
		    font->fd_local_subs_used[fd][sub_num] = TRUE;
		    cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width);
		}
            } else {
		sub_num = font->type2_stack_top_value + font->local_sub_bias;
		if (sub_num >= (int)_cairo_array_num_elements(&font->local_sub_index))
		    return CAIRO_INT_STATUS_UNSUPPORTED;
                element = _cairo_array_index (&font->local_sub_index, sub_num);
                if (! font->local_subs_used[sub_num] ||
		    (need_width && !font->type2_found_width))
		{
		    font->local_subs_used[sub_num] = TRUE;
		    cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width);
		}
            }
            font->type2_nesting_level--;
        } else if (*p == TYPE2_callgsubr) {
            /* call to global subroutine */
	    if (! font->type2_stack_top_is_int)
		return CAIRO_INT_STATUS_UNSUPPORTED;
            if (++font->type2_nesting_level > MAX_SUBROUTINE_NESTING)
		return CAIRO_INT_STATUS_UNSUPPORTED;
            p++;
            font->type2_stack_size--;
	    font->type2_stack_top_is_int = FALSE;
	    if (font->type2_find_width && font->type2_stack_size == 0)
		font->type2_seen_first_int = FALSE;
	    sub_num = font->type2_stack_top_value + font->global_sub_bias;
	    if (sub_num >= (int)_cairo_array_num_elements(&font->global_sub_index))
		return CAIRO_INT_STATUS_UNSUPPORTED;
	    element = _cairo_array_index (&font->global_sub_index, sub_num);
            if (! font->global_subs_used[sub_num] ||
		(need_width && !font->type2_found_width))
	    {
                font->global_subs_used[sub_num] = TRUE;
                cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width);
            }
            font->type2_nesting_level--;
        } else if (*p == 12) {
            /* 2 byte instruction */
	    /* All the 2 byte operators are either not valid before a
	     * stack clearing operator or they are one of the
	     * arithmetic, storage, or conditional operators. */
	    if (need_width && font->type2_find_width)
		return CAIRO_INT_STATUS_UNSUPPORTED;
            p += 2;
	    font->type2_stack_top_is_int = FALSE;
	} else {
            /* 1 byte instruction */
            p++;
	    font->type2_stack_top_is_int = FALSE;
        }
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_find_width_and_subroutines_used (cairo_cff_font_t  *font,
					   unsigned char *charstring, int length,
					   int glyph_id, int subset_id)
{
    cairo_status_t status;
    int width;
    int fd;
    font->type2_stack_size = 0;
    font->type2_stack_top_value = 0;;
    font->type2_stack_top_is_int = FALSE;
    font->type2_num_hints = 0;
    font->type2_hintmask_bytes = 0;
    font->type2_nesting_level = 0;
    font->type2_seen_first_int = FALSE;
    font->type2_find_width = TRUE;
    font->type2_found_width = FALSE;
    font->type2_width = 0;
    font->type2_has_path = FALSE;
    status = cairo_cff_parse_charstring (font, charstring, length, glyph_id, TRUE);
    if (status)
	return status;
    if (!font->is_opentype) {
        if (font->is_cid) {
            fd = font->fdselect[glyph_id];
            if (font->type2_found_width)
                width = font->fd_nominal_width[fd] + font->type2_width;
            else
                width = font->fd_default_width[fd];
        } else {
            if (font->type2_found_width)
                width = font->nominal_width + font->type2_width;
            else
                width = font->default_width;
        }
        font->widths[subset_id] = width;
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
cairo_cff_font_get_gid_for_cid (cairo_cff_font_t  *font, unsigned long cid, unsigned long *gid)
{
    unsigned char *p;
    unsigned long first_gid;
    unsigned long first_cid;
    int num_left;
    unsigned long c, g;
    if (cid == 0) {
	*gid = 0;
	return CAIRO_STATUS_SUCCESS;
    }
    switch (font->charset[0]) {
	/* Format 0 */
	case 0:
	    p = font->charset + 1;
	    g = 1;
	    while (g <= (unsigned)font->num_glyphs && p < font->data_end) {
		c = get_unaligned_be16 (p);
		if (c == cid) {
		    *gid = g;
		    return CAIRO_STATUS_SUCCESS;
		}
		g++;
		p += 2;
	    }
	    break;
	/* Format 1 */
	case 1:
	    first_gid = 1;
	    p = font->charset + 1;
	    while (first_gid <= (unsigned)font->num_glyphs && p + 2 < font->data_end) {
		first_cid = get_unaligned_be16 (p);
		num_left = p[2];
		if (cid >= first_cid && cid <= first_cid + num_left) {
		    *gid = first_gid + cid - first_cid;
		    return CAIRO_STATUS_SUCCESS;
		}
		first_gid += num_left + 1;
		p += 3;
	    }
	    break;
	/* Format 2 */
	case 2:
	    first_gid = 1;
	    p = font->charset + 1;
	    while (first_gid <= (unsigned)font->num_glyphs && p + 3 < font->data_end) {
		first_cid = get_unaligned_be16 (p);
		num_left = get_unaligned_be16 (p+2);
		if (cid >= first_cid && cid <= first_cid + num_left) {
		    *gid = first_gid + cid - first_cid;
		    return CAIRO_STATUS_SUCCESS;
		}
		first_gid += num_left + 1;
		p += 4;
	    }
	    break;
	default:
	    break;
    }
    return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_int_status_t
cairo_cff_font_subset_charstrings_and_subroutines (cairo_cff_font_t  *font)
{
    cff_index_element_t *element;
    unsigned int i;
    cairo_int_status_t status;
    unsigned long glyph, cid;
    font->subset_subroutines = TRUE;
    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
	if (font->is_cid && !font->is_opentype) {
	    cid = font->scaled_font_subset->glyphs[i];
	    status = cairo_cff_font_get_gid_for_cid (font, cid, &glyph);
	    if (unlikely (status))
		return status;
	} else {
	    glyph = font->scaled_font_subset->glyphs[i];
	}
        element = _cairo_array_index (&font->charstrings_index, glyph);
        status = cff_index_append (&font->charstrings_subset_index,
                                   element->data,
                                   element->length);
        if (unlikely (status))
            return status;
	if (font->subset_subroutines) {
	    status = cairo_cff_find_width_and_subroutines_used (font,
								element->data, element->length,
								glyph, i);
	    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
		/* If parsing the charstrings fails we embed all the
		 * subroutines. But if the font is not opentype we
		 * need to successfully parse all charstrings to get
		 * the widths. */
		font->subset_subroutines = FALSE;
		if (!font->is_opentype)
		    return status;
	    } else if (unlikely (status)) {
                return status;
	    }
        }
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_subset_fontdict (cairo_cff_font_t  *font)
{
    unsigned int i;
    int fd;
    int *reverse_map;
    unsigned long cid, gid;
    cairo_int_status_t status;
    font->fdselect_subset = _cairo_calloc_ab (font->scaled_font_subset->num_glyphs,
                                     sizeof (int));
    if (unlikely (font->fdselect_subset == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    font->fd_subset_map = _cairo_calloc_ab (font->num_fontdicts, sizeof (int));
    if (unlikely (font->fd_subset_map == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    font->private_dict_offset = _cairo_calloc_ab (font->num_fontdicts, sizeof (int));
    if (unlikely (font->private_dict_offset == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    reverse_map = _cairo_calloc_ab (font->num_fontdicts, sizeof (int));
    if (unlikely (reverse_map == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    for (i = 0; i < font->num_fontdicts; i++)
        reverse_map[i] = -1;
    font->num_subset_fontdicts = 0;
    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
	if (font->is_opentype) {
	    gid = font->scaled_font_subset->glyphs[i];
	} else {
	    cid = font->scaled_font_subset->glyphs[i];
	    status = cairo_cff_font_get_gid_for_cid (font, cid, &gid);
	    if (unlikely (status)) {
		free (reverse_map);
		return status;
	    }
	}
        fd = font->fdselect[gid];
        if (reverse_map[fd] < 0) {
            font->fd_subset_map[font->num_subset_fontdicts] = fd;
            reverse_map[fd] = font->num_subset_fontdicts++;
        }
        font->fdselect_subset[i] = reverse_map[fd];
    }
    free (reverse_map);
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
{
    unsigned char buf[100];
    unsigned char *end_buf;
    cairo_status_t status;
    font->num_fontdicts = 1;
    font->fd_dict = _cairo_malloc (sizeof (cairo_hash_table_t *));
    if (unlikely (font->fd_dict == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    if (cff_dict_init (&font->fd_dict[0])) {
	free (font->fd_dict);
	font->fd_dict = NULL;
	font->num_fontdicts = 0;
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }
    font->fd_subset_map = _cairo_malloc (sizeof (int));
    if (unlikely (font->fd_subset_map == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    font->private_dict_offset = _cairo_malloc (sizeof (int));
    if (unlikely (font->private_dict_offset == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    font->fd_subset_map[0] = 0;
    font->num_subset_fontdicts = 1;
    /* Set integer operand to max value to use max size encoding to reserve
     * space for any value later */
    end_buf = encode_integer_max (buf, 0);
    end_buf = encode_integer_max (end_buf, 0);
    status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
    if (unlikely (status))
	return status;
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_subset_strings (cairo_cff_font_t *font)
{
    cairo_status_t status;
    unsigned int i;
    status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
    if (unlikely (status))
        return status;
    if (font->is_cid) {
        for (i = 0; i < font->num_subset_fontdicts; i++) {
            status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
            if (unlikely (status))
                return status;
            status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]);
            if (unlikely (status))
                return status;
        }
    } else {
        status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
    }
    return status;
}
/* The Euro is the only the only character in the winansi encoding
 * with a glyph name that is not a CFF standard string. As the strings
 * are written before the charset, we need to check during the
 * subsetting phase if the Euro glyph is required and add the
 * glyphname to the list of strings to write out.
 */
static cairo_status_t
cairo_cff_font_add_euro_charset_string (cairo_cff_font_t *font)
{
    cairo_status_t status;
    unsigned int i;
    int ch;
    const char *euro = "Euro";
    for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
	ch = font->scaled_font_subset->to_latin_char[i];
	if (ch == 128) {
	    font->euro_sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
	    status = cff_index_append_copy (&font->strings_subset_index,
					    (unsigned char *)euro, strlen(euro));
	    return status;
	}
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_subset_font (cairo_cff_font_t  *font)
{
    cairo_status_t status;
    if (!font->scaled_font_subset->is_latin) {
	status = cairo_cff_font_set_ros_strings (font);
	if (unlikely (status))
	    return status;
    }
    status = cairo_cff_font_subset_charstrings_and_subroutines (font);
    if (unlikely (status))
        return status;
    if (!font->scaled_font_subset->is_latin) {
	if (font->is_cid)
	    status = cairo_cff_font_subset_fontdict (font);
	else
	    status = cairo_cff_font_create_cid_fontdict (font);
	if (unlikely (status))
	    return status;
    }  else {
	font->private_dict_offset = _cairo_malloc (sizeof (int));
	if (unlikely (font->private_dict_offset == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }
    status = cairo_cff_font_subset_strings (font);
    if (unlikely (status))
        return status;
    if (font->scaled_font_subset->is_latin)
	status = cairo_cff_font_add_euro_charset_string (font);
    return status;
}
/* Set the operand of the specified operator in the (already written)
 * top dict to point to the current position in the output
 * array. Operands updated with this function must have previously
 * been encoded with the 5-byte (max) integer encoding. */
static void
cairo_cff_font_set_topdict_operator_to_cur_pos (cairo_cff_font_t  *font,
                                                int                operator)
{
    int cur_pos;
    int offset;
    int size;
    unsigned char buf[10];
    unsigned char *buf_end;
    unsigned char *op_ptr;
    cur_pos = _cairo_array_num_elements (&font->output);
    buf_end = encode_integer_max (buf, cur_pos);
    offset = cff_dict_get_location (font->top_dict, operator, &size);
    assert (offset > 0);
    op_ptr = _cairo_array_index (&font->output, offset);
    memcpy (op_ptr, buf, buf_end - buf);
}
static cairo_status_t
cairo_cff_font_write_header (cairo_cff_font_t *font)
{
    return _cairo_array_append_multiple (&font->output,
                                         font->header,
                                         font->header->header_size);
}
static cairo_status_t
cairo_cff_font_write_name (cairo_cff_font_t *font)
{
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
    cairo_array_t index;
    cff_index_init (&index);
    status = cff_index_append_copy (&index,
                                    (unsigned char *) font->ps_name,
                                    strlen(font->ps_name));
    if (unlikely (status))
	goto FAIL;
    status = cff_index_write (&index, &font->output);
    if (unlikely (status))
        goto FAIL;
FAIL:
    cff_index_fini (&index);
    return status;
}
static cairo_status_t
cairo_cff_font_write_top_dict (cairo_cff_font_t *font)
{
    uint16_t count;
    unsigned char buf[10];
    unsigned char *p;
    int offset_index;
    int dict_start, dict_size;
    int offset_size = 4;
    cairo_status_t status;
    /* Write an index containing the top dict */
    count = cpu_to_be16 (1);
    status = _cairo_array_append_multiple (&font->output, &count, 2);
    if (unlikely (status))
        return status;
    buf[0] = offset_size;
    status = _cairo_array_append (&font->output, buf);
    if (unlikely (status))
        return status;
    encode_index_offset (buf, offset_size, 1);
    status = _cairo_array_append_multiple (&font->output, buf, offset_size);
    if (unlikely (status))
        return status;
    /* Reserve space for last element of offset array and update after
     * dict is written */
    offset_index = _cairo_array_num_elements (&font->output);
    status = _cairo_array_append_multiple (&font->output, buf, offset_size);
    if (unlikely (status))
        return status;
    dict_start = _cairo_array_num_elements (&font->output);
    status = cff_dict_write (font->top_dict, &font->output);
    if (unlikely (status))
        return status;
    dict_size = _cairo_array_num_elements (&font->output) - dict_start;
    encode_index_offset (buf, offset_size, dict_size + 1);
    p = _cairo_array_index (&font->output, offset_index);
    memcpy (p, buf, offset_size);
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_strings (cairo_cff_font_t  *font)
{
    return cff_index_write (&font->strings_subset_index, &font->output);
}
static cairo_status_t
cairo_cff_font_write_global_subrs (cairo_cff_font_t  *font)
{
    unsigned int i;
    unsigned char return_op = TYPE2_return;
    /* poppler and fontforge don't like zero length subroutines so we
     * replace unused subroutines with a 'return' instruction. */
    if (font->subset_subroutines) {
        for (i = 0; i < _cairo_array_num_elements (&font->global_sub_index); i++) {
            if (! font->global_subs_used[i])
                cff_index_set_object (&font->global_sub_index, i, &return_op, 1);
        }
    }
    return cff_index_write (&font->global_sub_index, &font->output);
}
static cairo_status_t
cairo_cff_font_write_encoding (cairo_cff_font_t  *font)
{
    unsigned char buf[2];
    cairo_status_t status;
    unsigned int i;
    cairo_cff_font_set_topdict_operator_to_cur_pos (font, ENCODING_OP);
    buf[0] = 0; /* Format 0 */
    buf[1] = font->scaled_font_subset->num_glyphs - 1;
    status = _cairo_array_append_multiple (&font->output, buf, 2);
    if (unlikely (status))
	return status;
    for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
	unsigned char ch = font->scaled_font_subset->to_latin_char[i];
        status = _cairo_array_append (&font->output, &ch);
        if (unlikely (status))
            return status;
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_fdselect (cairo_cff_font_t  *font)
{
    unsigned char data;
    unsigned int i;
    cairo_int_status_t status;
    cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP);
    if (font->is_cid) {
        data = 0;
        status = _cairo_array_append (&font->output, &data);
        if (unlikely (status))
            return status;
        for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
            data = font->fdselect_subset[i];
            status = _cairo_array_append (&font->output, &data);
            if (unlikely (status))
                return status;
        }
    } else {
        unsigned char byte;
        uint16_t word;
        status = _cairo_array_grow_by (&font->output, 9);
        if (unlikely (status))
            return status;
        byte = 3;
        status = _cairo_array_append (&font->output, &byte);
        assert (status == CAIRO_INT_STATUS_SUCCESS);
        word = cpu_to_be16 (1);
        status = _cairo_array_append_multiple (&font->output, &word, 2);
        assert (status == CAIRO_INT_STATUS_SUCCESS);
        word = cpu_to_be16 (0);
        status = _cairo_array_append_multiple (&font->output, &word, 2);
        assert (status == CAIRO_INT_STATUS_SUCCESS);
        byte = 0;
        status = _cairo_array_append (&font->output, &byte);
        assert (status == CAIRO_INT_STATUS_SUCCESS);
        word = cpu_to_be16 (font->scaled_font_subset->num_glyphs);
        status = _cairo_array_append_multiple (&font->output, &word, 2);
        assert (status == CAIRO_INT_STATUS_SUCCESS);
    }
    return CAIRO_STATUS_SUCCESS;
}
/* Winansi to CFF standard strings mapping for characters 128 to 255 */
static const int winansi_to_cff_std_string[] = {
	/* 128 */
      0,   0, 117, 101, 118, 121, 112, 113,
    126, 122, 192, 107, 142,   0, 199,   0,
	/* 144 */
      0,  65,   8, 105, 119, 116, 111, 137,
    127, 153, 221, 108, 148,   0, 228, 198,
	/* 160 */
      0,  96,  97,  98, 103, 100, 160, 102,
    131, 170, 139, 106, 151,   0, 165, 128,
	/* 176 */
    161, 156, 164, 169, 125, 152, 115, 114,
    133, 150, 143, 120, 158, 155, 163, 123,
	/* 192 */
    174, 171, 172, 176, 173, 175, 138, 177,
    181, 178, 179, 180, 185, 182, 183, 184,
	/* 208 */
    154, 186, 190, 187, 188, 191, 189, 168,
    141, 196, 193, 194, 195, 197, 157, 149,
	/* 224 */
    203, 200, 201, 205, 202, 204, 144, 206,
    210, 207, 208, 209, 214, 211, 212, 213,
	/* 240 */
    167, 215, 219, 216, 217, 220, 218, 159,
    147, 225, 222, 223, 224, 226, 162, 227,
};
static int
cairo_cff_font_get_sid_for_winansi_char (cairo_cff_font_t  *font, int ch)
{
    int sid;
    if (ch == 39) {
	sid = 104;
    } else if (ch == 96) {
	sid = 124;
    } else if (ch >= 32 && ch <= 126) {
	sid = ch - 31;
    } else if (ch == 128) {
	assert (font->euro_sid >= NUM_STD_STRINGS);
	sid = font->euro_sid;
    } else if (ch >= 128 && ch <= 255) {
	sid = winansi_to_cff_std_string[ch - 128];
    } else {
	sid = 0;
    }
    return sid;
}
static cairo_status_t
cairo_cff_font_write_type1_charset (cairo_cff_font_t  *font)
{
    unsigned char format = 0;
    unsigned int i;
    int ch, sid;
    cairo_status_t status;
    uint16_t sid_be16;
    cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
    status = _cairo_array_append (&font->output, &format);
    if (unlikely (status))
	return status;
    for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
	ch = font->scaled_font_subset->to_latin_char[i];
	sid = cairo_cff_font_get_sid_for_winansi_char (font, ch);
        if (unlikely (status))
	    return status;
	sid_be16 = cpu_to_be16(sid);
	status = _cairo_array_append_multiple (&font->output, &sid_be16, sizeof(sid_be16));
        if (unlikely (status))
            return status;
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_cid_charset (cairo_cff_font_t  *font)
{
    unsigned char byte;
    uint16_t word;
    cairo_status_t status;
    cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
    status = _cairo_array_grow_by (&font->output, 5);
    if (unlikely (status))
        return status;
    byte = 2;
    status = _cairo_array_append (&font->output, &byte);
    assert (status == CAIRO_STATUS_SUCCESS);
    word = cpu_to_be16 (1);
    status = _cairo_array_append_multiple (&font->output, &word, 2);
    assert (status == CAIRO_STATUS_SUCCESS);
    word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2);
    status = _cairo_array_append_multiple (&font->output, &word, 2);
    assert (status == CAIRO_STATUS_SUCCESS);
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_charstrings (cairo_cff_font_t  *font)
{
    cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP);
    return cff_index_write (&font->charstrings_subset_index, &font->output);
}
static cairo_status_t
cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
{
    unsigned int i;
    cairo_int_status_t status;
    unsigned int offset_array;
    unsigned char *offset_array_ptr;
    int offset_base;
    uint16_t count;
    uint8_t offset_size = 4;
    cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP);
    count = cpu_to_be16 (font->num_subset_fontdicts);
    status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t));
    if (unlikely (status))
        return status;
    status = _cairo_array_append (&font->output, &offset_size);
    if (unlikely (status))
        return status;
    offset_array = _cairo_array_num_elements (&font->output);
    status = _cairo_array_allocate (&font->output,
                                    (font->num_subset_fontdicts + 1)*offset_size,
                                    (void **) &offset_array_ptr);
    if (unlikely (status))
        return status;
    offset_base = _cairo_array_num_elements (&font->output) - 1;
    put_unaligned_be32(1, offset_array_ptr);
    offset_array += sizeof(uint32_t);
    for (i = 0; i < font->num_subset_fontdicts; i++) {
        status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
                                 &font->output);
        if (unlikely (status))
            return status;
	offset_array_ptr = _cairo_array_index (&font->output, offset_array);
	put_unaligned_be32 (_cairo_array_num_elements (&font->output) - offset_base,
			    offset_array_ptr);
	offset_array += sizeof(uint32_t);
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_private_dict (cairo_cff_font_t   *font,
				   int                 dict_num,
				   cairo_hash_table_t *parent_dict,
				   cairo_hash_table_t *private_dict)
{
    int offset;
    int size;
    unsigned char buf[10];
    unsigned char *buf_end;
    unsigned char *p;
    cairo_status_t status;
    /* Write private dict and update offset and size in top dict */
    font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output);
    status = cff_dict_write (private_dict, &font->output);
    if (unlikely (status))
        return status;
    size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
    /* private entry has two operands - size and offset */
    buf_end = encode_integer_max (buf, size);
    buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]);
    offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size);
    assert (offset > 0);
    p = _cairo_array_index (&font->output, offset);
    memcpy (p, buf, buf_end - buf);
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_local_sub (cairo_cff_font_t   *font,
                                int                 dict_num,
                                cairo_hash_table_t *private_dict,
                                cairo_array_t      *local_sub_index,
                                cairo_bool_t       *local_subs_used)
{
    int offset;
    int size;
    unsigned char buf[10];
    unsigned char *buf_end;
    unsigned char *p;
    cairo_status_t status;
    unsigned int i;
    unsigned char return_op = TYPE2_return;
    if (_cairo_array_num_elements (local_sub_index) > 0) {
        /* Write local subroutines and update offset in private
         * dict. Local subroutines offset is relative to start of
         * private dict */
        offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
        buf_end = encode_integer_max (buf, offset);
        offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size);
        assert (offset > 0);
        p = _cairo_array_index (&font->output, offset);
        memcpy (p, buf, buf_end - buf);
	/* poppler and fontforge don't like zero length subroutines so
	 * we replace unused subroutines with a 'return' instruction.
	 */
        if (font->subset_subroutines) {
            for (i = 0; i < _cairo_array_num_elements (local_sub_index); i++) {
                if (! local_subs_used[i])
                    cff_index_set_object (local_sub_index, i, &return_op, 1);
            }
        }
        status = cff_index_write (local_sub_index, &font->output);
        if (unlikely (status))
            return status;
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t  *font)
{
    unsigned int i;
    cairo_int_status_t status;
    if (font->is_cid) {
        for (i = 0; i < font->num_subset_fontdicts; i++) {
            status = cairo_cff_font_write_private_dict (
                            font,
                            i,
                            font->fd_dict[font->fd_subset_map[i]],
                            font->fd_private_dict[font->fd_subset_map[i]]);
            if (unlikely (status))
                return status;
        }
        for (i = 0; i < font->num_subset_fontdicts; i++) {
            status = cairo_cff_font_write_local_sub (
                            font,
                            i,
                            font->fd_private_dict[font->fd_subset_map[i]],
                            &font->fd_local_sub_index[font->fd_subset_map[i]],
                            font->fd_local_subs_used[font->fd_subset_map[i]]);
            if (unlikely (status))
                return status;
        }
    } else {
        status = cairo_cff_font_write_private_dict (font,
                                                    0,
                                                    font->fd_dict[0],
                                                    font->private_dict);
	if (unlikely (status))
	    return status;
        status = cairo_cff_font_write_local_sub (font,
                                                 0,
                                                 font->private_dict,
                                                 &font->local_sub_index,
                                                 font->local_subs_used);
	if (unlikely (status))
	    return status;
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_type1_private_dict_and_local_sub (cairo_cff_font_t  *font)
{
    cairo_int_status_t status;
    status = cairo_cff_font_write_private_dict (font,
						0,
						font->top_dict,
						font->private_dict);
    if (unlikely (status))
	return status;
    status = cairo_cff_font_write_local_sub (font,
					     0,
					     font->private_dict,
					     &font->local_sub_index,
					     font->local_subs_used);
    if (unlikely (status))
	return status;
    return CAIRO_STATUS_SUCCESS;
}
typedef cairo_status_t
(*font_write_t) (cairo_cff_font_t *font);
static const font_write_t font_write_cid_funcs[] = {
    cairo_cff_font_write_header,
    cairo_cff_font_write_name,
    cairo_cff_font_write_top_dict,
    cairo_cff_font_write_strings,
    cairo_cff_font_write_global_subrs,
    cairo_cff_font_write_cid_charset,
    cairo_cff_font_write_fdselect,
    cairo_cff_font_write_charstrings,
    cairo_cff_font_write_cid_fontdict,
    cairo_cff_font_write_cid_private_dict_and_local_sub,
};
static const font_write_t font_write_type1_funcs[] = {
    cairo_cff_font_write_header,
    cairo_cff_font_write_name,
    cairo_cff_font_write_top_dict,
    cairo_cff_font_write_strings,
    cairo_cff_font_write_global_subrs,
    cairo_cff_font_write_encoding,
    cairo_cff_font_write_type1_charset,
    cairo_cff_font_write_charstrings,
    cairo_cff_font_write_type1_private_dict_and_local_sub,
};
static cairo_status_t
cairo_cff_font_write_subset (cairo_cff_font_t *font)
{
    cairo_int_status_t status;
    unsigned int i;
    if (font->scaled_font_subset->is_latin) {
        for (i = 0; i < ARRAY_LENGTH (font_write_type1_funcs); i++) {
            status = font_write_type1_funcs[i] (font);
            if (unlikely (status))
                return status;
        }
    } else {
        for (i = 0; i < ARRAY_LENGTH (font_write_cid_funcs); i++) {
            status = font_write_cid_funcs[i] (font);
            if (unlikely (status))
                return status;
        }
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
cairo_cff_font_generate (cairo_cff_font_t  *font,
                         const char       **data,
                         unsigned long     *length)
{
    cairo_int_status_t status;
    status = cairo_cff_font_read_font (font);
    if (unlikely (status))
        return status;
    /* If the PS name is not found, create a CairoFont-x-y name. */
    if (font->ps_name == NULL) {
        font->ps_name = _cairo_malloc (30);
        if (unlikely (font->ps_name == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
        snprintf(font->ps_name, 30, "CairoFont-%u-%u",
                 font->scaled_font_subset->font_id,
                 font->scaled_font_subset->subset_id);
    }
    status = cairo_cff_font_subset_font (font);
    if (unlikely (status))
        return status;
    status = cairo_cff_font_write_subset (font);
    if (unlikely (status))
        return status;
    *data = _cairo_array_index (&font->output, 0);
    *length = _cairo_array_num_elements (&font->output);
    return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
cairo_cff_font_create_set_widths (cairo_cff_font_t *font)
{
    unsigned long size;
    unsigned long long_entry_size;
    unsigned long short_entry_size;
    unsigned int i;
    tt_hhea_t hhea;
    int num_hmetrics;
    uint16_t short_entry;
    int glyph_index;
    cairo_int_status_t status;
    size = sizeof (tt_hhea_t);
    status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                                 TT_TAG_hhea, 0,
                                                 (unsigned char*) &hhea, &size);
    if (unlikely (status))
        return status;
    num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
        glyph_index = font->scaled_font_subset->glyphs[i];
        long_entry_size = 2 * sizeof (int16_t);
        short_entry_size = sizeof (int16_t);
        if (glyph_index < num_hmetrics) {
            status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                                         TT_TAG_hmtx,
                                                         glyph_index * long_entry_size,
                                                         (unsigned char *) &short_entry,
							 &short_entry_size);
            if (unlikely (status))
                return status;
        }
        else
        {
            status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                                         TT_TAG_hmtx,
                                                         (num_hmetrics - 1) * long_entry_size,
                                                         (unsigned char *) &short_entry,
							 &short_entry_size);
            if (unlikely (status))
                return status;
        }
	font->widths[i] = be16_to_cpu (short_entry);
    }
    return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
check_fontdata_is_cff (const unsigned char *data, long length)
{
    cff_header_t *header;
    if (length < (long)sizeof (cff_header_t))
        return FALSE;
    header = (cff_header_t *) data;
    if (header->major == 1 &&
	header->minor == 0 &&
	header->header_size == 4)
    {
	return TRUE;
    }
    return FALSE;
}
static cairo_int_status_t
_cairo_cff_font_load_opentype_cff (cairo_cff_font_t  *font)
{
    const cairo_scaled_font_backend_t *backend = font->backend;
    cairo_status_t status;
    tt_head_t head;
    tt_hhea_t hhea;
    unsigned long size, data_length;
    if (!backend->load_truetype_table)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    data_length = 0;
    status = backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                           TT_TAG_CFF, 0, NULL, &data_length);
    if (status)
        return status;
    size = sizeof (tt_head_t);
    status = backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                           TT_TAG_head, 0,
                                           (unsigned char *) &head, &size);
    if (unlikely (status))
        return status;
    size = sizeof (tt_hhea_t);
    status = backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                           TT_TAG_hhea, 0,
                                           (unsigned char *) &hhea, &size);
    if (unlikely (status))
        return status;
    size = 0;
    status = backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                           TT_TAG_hmtx, 0, NULL, &size);
    if (unlikely (status))
        return status;
    font->x_min = (int16_t) be16_to_cpu (head.x_min);
    font->y_min = (int16_t) be16_to_cpu (head.y_min);
    font->x_max = (int16_t) be16_to_cpu (head.x_max);
    font->y_max = (int16_t) be16_to_cpu (head.y_max);
    font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
    font->descent = (int16_t) be16_to_cpu (hhea.descender);
    font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
    if (font->units_per_em == 0)
        font->units_per_em = 1000;
    font->font_name = NULL;
    status = _cairo_truetype_read_font_name (font->scaled_font_subset->scaled_font,
					     &font->ps_name,
					     &font->font_name);
    if (_cairo_status_is_error (status))
	return status;
    font->is_opentype = TRUE;
    font->data_length = data_length;
    font->data = _cairo_malloc (data_length);
    if (unlikely (font->data == NULL))
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
						 TT_TAG_CFF, 0, font->data,
						 &font->data_length);
    if (unlikely (status))
        return status;
    if (!check_fontdata_is_cff (font->data, data_length))
	return CAIRO_INT_STATUS_UNSUPPORTED;
    return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_cff_font_load_cff (cairo_cff_font_t  *font)
{
    const cairo_scaled_font_backend_t *backend = font->backend;
    cairo_status_t status;
    unsigned long data_length;
    if (!backend->load_type1_data)
	return CAIRO_INT_STATUS_UNSUPPORTED;
    data_length = 0;
    status = backend->load_type1_data (font->scaled_font_subset->scaled_font,
				      0, NULL, &data_length);
    if (unlikely (status))
        return status;
    font->font_name = NULL;
    font->is_opentype = FALSE;
    font->data_length = data_length;
    font->data = _cairo_malloc (data_length);
    if (unlikely (font->data == NULL))
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    status = font->backend->load_type1_data (font->scaled_font_subset->scaled_font,
					     0, font->data, &font->data_length);
    if (unlikely (status))
        return status;
    if (!check_fontdata_is_cff (font->data, data_length))
	return CAIRO_INT_STATUS_UNSUPPORTED;
    return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_cff_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
                        cairo_cff_font_t           **font_return,
                        const char                  *subset_name)
{
    const cairo_scaled_font_backend_t *backend;
    cairo_int_status_t status;
    cairo_bool_t is_synthetic;
    cairo_cff_font_t *font;
    backend = scaled_font_subset->scaled_font->backend;
    /* We need to use a fallback font if this font differs from the CFF outlines. */
    if (backend->is_synthetic) {
	status = backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic);
	if (unlikely (status))
	    return status;
	if (is_synthetic)
	    return CAIRO_INT_STATUS_UNSUPPORTED;
    }
    font = _cairo_calloc (sizeof (cairo_cff_font_t));
    if (unlikely (font == NULL))
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    font->backend = backend;
    font->scaled_font_subset = scaled_font_subset;
    status = _cairo_cff_font_load_opentype_cff (font);
    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
	status = _cairo_cff_font_load_cff (font);
    if (status)
	goto fail1;
    font->data_end = font->data + font->data_length;
    _cairo_array_init (&font->output, sizeof (char));
    status = _cairo_array_grow_by (&font->output, 4096);
    if (unlikely (status))
	goto fail2;
    font->subset_font_name = strdup (subset_name);
    if (unlikely (font->subset_font_name == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto fail2;
    }
    font->widths = _cairo_calloc_ab (font->scaled_font_subset->num_glyphs, sizeof (int));
    if (unlikely (font->widths == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        goto fail3;
    }
    if (font->is_opentype) {
	status = cairo_cff_font_create_set_widths (font);
	if (unlikely (status))
	    goto fail4;
    }
    status = cff_dict_init (&font->top_dict);
    if (unlikely (status))
	goto fail4;
    status = cff_dict_init (&font->private_dict);
    if (unlikely (status))
	goto fail5;
    cff_index_init (&font->strings_index);
    cff_index_init (&font->charstrings_index);
    cff_index_init (&font->global_sub_index);
    cff_index_init (&font->local_sub_index);
    cff_index_init (&font->charstrings_subset_index);
    cff_index_init (&font->strings_subset_index);
    font->euro_sid = 0;
    font->fdselect = NULL;
    font->fd_dict = NULL;
    font->fd_private_dict = NULL;
    font->fd_local_sub_index = NULL;
    font->fd_local_sub_bias = NULL;
    font->fdselect_subset = NULL;
    font->fd_subset_map = NULL;
    font->private_dict_offset = NULL;
    font->global_subs_used = NULL;
    font->local_subs_used = NULL;
    font->fd_local_subs_used = NULL;
    *font_return = font;
    return CAIRO_STATUS_SUCCESS;
fail5:
    _cairo_hash_table_destroy (font->top_dict);
fail4:
    free (font->widths);
fail3:
    free (font->subset_font_name);
fail2:
    free (font->ps_name);
    _cairo_array_fini (&font->output);
fail1:
    free (font->data);
    free (font->font_name);
    free (font);
    return status;
}
static void
cairo_cff_font_destroy (cairo_cff_font_t *font)
{
    unsigned int i;
    free (font->widths);
    free (font->font_name);
    free (font->ps_name);
    free (font->subset_font_name);
    _cairo_array_fini (&font->output);
    cff_dict_fini (font->top_dict);
    cff_dict_fini (font->private_dict);
    cff_index_fini (&font->strings_index);
    cff_index_fini (&font->charstrings_index);
    cff_index_fini (&font->global_sub_index);
    cff_index_fini (&font->local_sub_index);
    cff_index_fini (&font->charstrings_subset_index);
    cff_index_fini (&font->strings_subset_index);
    /* If we bailed out early as a result of an error some of the
     * following cairo_cff_font_t members may still be NULL */
    if (font->fd_dict) {
        for (i = 0; i < font->num_fontdicts; i++) {
            if (font->fd_dict[i])
                cff_dict_fini (font->fd_dict[i]);
        }
        free (font->fd_dict);
    }
    free (font->global_subs_used);
    free (font->local_subs_used);
    free (font->fd_subset_map);
    free (font->private_dict_offset);
    if (font->is_cid) {
	free (font->fdselect);
	free (font->fdselect_subset);
        if (font->fd_private_dict) {
            for (i = 0; i < font->num_fontdicts; i++) {
                if (font->fd_private_dict[i])
                    cff_dict_fini (font->fd_private_dict[i]);
            }
            free (font->fd_private_dict);
        }
        if (font->fd_local_sub_index) {
            for (i = 0; i < font->num_fontdicts; i++)
                cff_index_fini (&font->fd_local_sub_index[i]);
            free (font->fd_local_sub_index);
        }
	free (font->fd_local_sub_bias);
        if (font->fd_local_subs_used) {
            for (i = 0; i < font->num_fontdicts; i++) {
		free (font->fd_local_subs_used[i]);
            }
            free (font->fd_local_subs_used);
        }
	free (font->fd_default_width);
	free (font->fd_nominal_width);
    }
    free (font->data);
    free (font);
}
cairo_status_t
_cairo_cff_subset_init (cairo_cff_subset_t          *cff_subset,
                        const char		    *subset_name,
                        cairo_scaled_font_subset_t  *font_subset)
{
    cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
    cairo_status_t status;
    const char *data = NULL; /* squelch bogus compiler warning */
    unsigned long length = 0; /* squelch bogus compiler warning */
    unsigned int i;
    status = _cairo_cff_font_create (font_subset, &font, subset_name);
    if (unlikely (status))
	return status;
    status = cairo_cff_font_generate (font, &data, &length);
    if (unlikely (status))
	goto fail1;
    cff_subset->ps_name = strdup (font->ps_name);
    if (unlikely (cff_subset->ps_name == NULL)) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto fail1;
    }
    if (font->font_name) {
	cff_subset->family_name_utf8 = strdup (font->font_name);
	if (cff_subset->family_name_utf8 == NULL) {
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	    goto fail2;
	}
    } else {
	cff_subset->family_name_utf8 = NULL;
    }
    cff_subset->widths = _cairo_calloc_ab (font->scaled_font_subset->num_glyphs,
					   sizeof (double));
    if (unlikely (cff_subset->widths == NULL)) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto fail3;
    }
    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
        cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em;
    cff_subset->x_min = (double)font->x_min/font->units_per_em;
    cff_subset->y_min = (double)font->y_min/font->units_per_em;
    cff_subset->x_max = (double)font->x_max/font->units_per_em;
    cff_subset->y_max = (double)font->y_max/font->units_per_em;
    cff_subset->ascent = (double)font->ascent/font->units_per_em;
    cff_subset->descent = (double)font->descent/font->units_per_em;
    cff_subset->data = _cairo_malloc (length);
    if (unlikely (cff_subset->data == NULL)) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto fail4;
    }
    memcpy (cff_subset->data, data, length);
    cff_subset->data_length = length;
    cairo_cff_font_destroy (font);
    return CAIRO_STATUS_SUCCESS;
 fail4:
    free (cff_subset->widths);
 fail3:
    free (cff_subset->family_name_utf8);
 fail2:
    free (cff_subset->ps_name);
 fail1:
    cairo_cff_font_destroy (font);
    return status;
}
void
_cairo_cff_subset_fini (cairo_cff_subset_t *subset)
{
    free (subset->ps_name);
    free (subset->family_name_utf8);
    free (subset->widths);
    free (subset->data);
}
cairo_bool_t
_cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font)
{
    const cairo_scaled_font_backend_t *backend;
    cairo_int_status_t status;
    unsigned char *data;
    unsigned long data_length;
    unsigned char *current_ptr;
    unsigned char *data_end;
    cff_header_t  *header;
    cff_index_element_t *element;
    cairo_hash_table_t  *top_dict;
    cairo_array_t index;
    int size;
    cairo_bool_t is_cid = FALSE;
    backend = scaled_font->backend;
    data = NULL;
    data_length = 0;
    status = CAIRO_INT_STATUS_UNSUPPORTED;
    /* Try to load an OpenType/CFF font */
    if (backend->load_truetype_table &&
	(status = backend->load_truetype_table (scaled_font, TT_TAG_CFF,
						0, NULL, &data_length)) == CAIRO_INT_STATUS_SUCCESS)
    {
	data = _cairo_malloc (data_length);
	if (unlikely (data == NULL)) {
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	    return FALSE;
	}
	status = backend->load_truetype_table (scaled_font, TT_TAG_CFF,
					   0, data, &data_length);
	if (unlikely (status))
	    goto fail1;
    }
    /* Try to load a CFF font */
    if (status == CAIRO_INT_STATUS_UNSUPPORTED &&
	backend->load_type1_data &&
	(status = backend->load_type1_data (scaled_font,
					    0, NULL, &data_length)) == CAIRO_INT_STATUS_SUCCESS)
    {
	data = _cairo_malloc (data_length);
	if (unlikely (data == NULL)) {
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	    return FALSE;
	}
	status = backend->load_type1_data (scaled_font, 0, data, &data_length);
	if (unlikely (status))
	    goto fail1;
    }
    if (status)
	goto fail1;
    /* Check if it looks like a CFF font */
    if (!check_fontdata_is_cff (data, data_length))
	goto fail1;
    data_end = data + data_length;
    /* skip header */
    if (data_length < sizeof (cff_header_t))
        goto fail1;
    header = (cff_header_t *) data;
    current_ptr = data + header->header_size;
    /* skip name */
    cff_index_init (&index);
    status = cff_index_read (&index, &current_ptr, data_end);
    cff_index_fini (&index);
    if (status)
        goto fail1;
    /* read top dict */
    cff_index_init (&index);
    status = cff_index_read (&index, &current_ptr, data_end);
    if (unlikely (status))
        goto fail2;
    status = cff_dict_init (&top_dict);
    if (unlikely (status))
	goto fail2;
    element = _cairo_array_index (&index, 0);
    if (element == NULL)
        goto fail3;
    status = cff_dict_read (top_dict, element->data, element->length);
    if (unlikely (status))
        goto fail3;
    /* check for ROS operator indicating a CID font */
    if (cff_dict_get_operands (top_dict, ROS_OP, &size) != NULL)
        is_cid = TRUE;
fail3:
    cff_dict_fini (top_dict);
fail2:
    cff_index_fini (&index);
fail1:
    free (data);
    return is_cid;
}
static cairo_int_status_t
_cairo_cff_font_fallback_create (cairo_scaled_font_subset_t  *scaled_font_subset,
                                 cairo_cff_font_t           **font_return,
                                 const char                  *subset_name)
{
    cairo_status_t status;
    cairo_cff_font_t *font;
    font = _cairo_calloc (sizeof (cairo_cff_font_t));
    if (unlikely (font == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    font->backend = NULL;
    font->scaled_font_subset = scaled_font_subset;
    _cairo_array_init (&font->output, sizeof (char));
    status = _cairo_array_grow_by (&font->output, 4096);
    if (unlikely (status))
	goto fail1;
    font->subset_font_name = strdup (subset_name);
    if (unlikely (font->subset_font_name == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto fail1;
    }
    font->ps_name = strdup (subset_name);
    if (unlikely (font->ps_name == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto fail2;
    }
    font->font_name = NULL;
    font->x_min = 0;
    font->y_min = 0;
    font->x_max = 0;
    font->y_max = 0;
    font->ascent = 0;
    font->descent = 0;
    font->widths = _cairo_calloc_ab (font->scaled_font_subset->num_glyphs, sizeof (int));
    if (unlikely (font->widths == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        goto fail3;
    }
    font->data_length = 0;
    font->data = NULL;
    font->data_end = NULL;
    status = cff_dict_init (&font->top_dict);
    if (unlikely (status))
	goto fail4;
    status = cff_dict_init (&font->private_dict);
    if (unlikely (status))
	goto fail5;
    cff_index_init (&font->strings_index);
    cff_index_init (&font->charstrings_index);
    cff_index_init (&font->global_sub_index);
    cff_index_init (&font->local_sub_index);
    cff_index_init (&font->charstrings_subset_index);
    cff_index_init (&font->strings_subset_index);
    font->global_subs_used = NULL;
    font->local_subs_used = NULL;
    font->subset_subroutines = FALSE;
    font->fdselect = NULL;
    font->fd_dict = NULL;
    font->fd_private_dict = NULL;
    font->fd_local_sub_index = NULL;
    font->fdselect_subset = NULL;
    font->fd_subset_map = NULL;
    font->private_dict_offset = NULL;
    *font_return = font;
    return CAIRO_STATUS_SUCCESS;
fail5:
    _cairo_hash_table_destroy (font->top_dict);
fail4:
    free (font->widths);
fail3:
    free (font->font_name);
    free (font->ps_name);
fail2:
    free (font->subset_font_name);
fail1:
    _cairo_array_fini (&font->output);
    free (font);
    return status;
}
static cairo_int_status_t
cairo_cff_font_fallback_generate (cairo_cff_font_t           *font,
                                  cairo_type2_charstrings_t  *type2_subset,
                                  const char                **data,
                                  unsigned long              *length)
{
    cairo_int_status_t status;
    cff_header_t header;
    cairo_array_t *charstring;
    unsigned char buf[40];
    unsigned char *end_buf, *end_buf2;
    unsigned int i;
    int sid;
    /* Create header */
    header.major = 1;
    header.minor = 0;
    header.header_size = 4;
    header.offset_size = 4;
    font->header = &header;
    /* Create Top Dict */
    font->is_cid = FALSE;
    snprintf((char*)buf, sizeof(buf), "CairoFont-%u-%u",
	     font->scaled_font_subset->font_id,
	     font->scaled_font_subset->subset_id);
    sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
    status = cff_index_append_copy (&font->strings_subset_index,
                                    (unsigned char *)buf,
                                    strlen((char*)buf));
    if (unlikely (status))
	return status;
    end_buf = encode_integer (buf, sid);
    status = cff_dict_set_operands (font->top_dict, FULLNAME_OP,
				    buf, end_buf - buf);
    if (unlikely (status))
	return status;
    status = cff_dict_set_operands (font->top_dict, FAMILYNAME_OP,
				    buf, end_buf - buf);
    if (unlikely (status))
	return status;
    end_buf = encode_integer (buf, type2_subset->x_min);
    end_buf = encode_integer (end_buf, type2_subset->y_min);
    end_buf = encode_integer (end_buf, type2_subset->x_max);
    end_buf = encode_integer (end_buf, type2_subset->y_max);
    status = cff_dict_set_operands (font->top_dict,
	                            FONTBBOX_OP, buf, end_buf - buf);
    if (unlikely (status))
	return status;
    end_buf = encode_integer_max (buf, 0);
    status = cff_dict_set_operands (font->top_dict,
	                            CHARSTRINGS_OP, buf, end_buf - buf);
    if (unlikely (status))
	return status;
    if (font->scaled_font_subset->is_latin) {
	status = cff_dict_set_operands (font->top_dict,
                                        ENCODING_OP, buf, end_buf - buf);
        if (unlikely (status))
	    return status;
	/* Private has two operands - size and offset */
	end_buf2 = encode_integer_max (end_buf, 0);
	cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf2 - buf);
        if (unlikely (status))
	    return status;
    } else {
	status = cff_dict_set_operands (font->top_dict,
					FDSELECT_OP, buf, end_buf - buf);
	if (unlikely (status))
	    return status;
	status = cff_dict_set_operands (font->top_dict,
					FDARRAY_OP, buf, end_buf - buf);
	if (unlikely (status))
	    return status;
    }
    status = cff_dict_set_operands (font->top_dict,
	                            CHARSET_OP, buf, end_buf - buf);
    if (unlikely (status))
	return status;
    if (!font->scaled_font_subset->is_latin) {
	status = cairo_cff_font_set_ros_strings (font);
	if (unlikely (status))
	    return status;
	/* Create CID FD dictionary */
	status = cairo_cff_font_create_cid_fontdict (font);
	if (unlikely (status))
	    return status;
    } else {
	font->private_dict_offset = _cairo_malloc (sizeof (int));
	if (unlikely (font->private_dict_offset == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }
    /* Create charstrings */
    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
        charstring = _cairo_array_index(&type2_subset->charstrings, i);
        status = cff_index_append (&font->charstrings_subset_index,
                                   _cairo_array_index (charstring, 0),
                                   _cairo_array_num_elements (charstring));
        if (unlikely (status))
            return status;
    }
    if (font->scaled_font_subset->is_latin)
	status = cairo_cff_font_add_euro_charset_string (font);
    status = cairo_cff_font_write_subset (font);
    if (unlikely (status))
        return status;
    *data = _cairo_array_index (&font->output, 0);
    *length = _cairo_array_num_elements (&font->output);
    return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_cff_fallback_init (cairo_cff_subset_t          *cff_subset,
                          const char		      *subset_name,
                          cairo_scaled_font_subset_t  *font_subset)
{
    cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
    cairo_status_t status;
    const char *data = NULL; /* squelch bogus compiler warning */
    unsigned long length = 0; /* squelch bogus compiler warning */
    unsigned int i;
    cairo_type2_charstrings_t type2_subset;
    status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
    if (unlikely (status))
	return status;
    status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
    if (unlikely (status))
	goto fail1;
    status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
    if (unlikely (status))
	goto fail2;
    cff_subset->family_name_utf8 = NULL;
    cff_subset->ps_name = strdup (font->ps_name);
    if (unlikely (cff_subset->ps_name == NULL)) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto fail2;
    }
    cff_subset->widths = _cairo_calloc_ab (font->scaled_font_subset->num_glyphs, sizeof (double));
    if (unlikely (cff_subset->widths == NULL)) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto fail3;
    }
    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
        cff_subset->widths[i] = (double)type2_subset.widths[i]/1000;
    cff_subset->x_min = (double)type2_subset.x_min/1000;
    cff_subset->y_min = (double)type2_subset.y_min/1000;
    cff_subset->x_max = (double)type2_subset.x_max/1000;
    cff_subset->y_max = (double)type2_subset.y_max/1000;
    cff_subset->ascent = (double)type2_subset.y_max/1000;
    cff_subset->descent = (double)type2_subset.y_min/1000;
    cff_subset->data = _cairo_malloc (length);
    if (unlikely (cff_subset->data == NULL)) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto fail4;
    }
    memcpy (cff_subset->data, data, length);
    cff_subset->data_length = length;
    _cairo_type2_charstrings_fini (&type2_subset);
    cairo_cff_font_destroy (font);
    return CAIRO_STATUS_SUCCESS;
 fail4:
    free (cff_subset->widths);
 fail3:
    free (cff_subset->ps_name);
 fail2:
    _cairo_type2_charstrings_fini (&type2_subset);
 fail1:
    cairo_cff_font_destroy (font);
    return status;
}
void
_cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
{
    free (subset->ps_name);
    free (subset->widths);
    free (subset->data);
}
#endif /* CAIRO_HAS_FONT_SUBSET */