Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gdevpsft.c,v 1.35 2004/12/08 21:35:13 stefan Exp $ */
18
/* Write an embedded TrueType font */
19
#include "memory_.h"
20
#include <assert.h>
21
#include <stdlib.h>		/* for qsort */
22
#include "gx.h"
23
#include "gscencs.h"
24
#include "gserrors.h"
25
#include "gsmatrix.h"
26
#include "gsutil.h"
27
#include "gxfcid.h"
28
#include "gxfont.h"
29
#include "gxfont42.h"
30
#include "gxttf.h"
31
#include "stream.h"
32
#include "spprint.h"
33
#include "gdevpsf.h"
34
 
35
/* Internally used options */
36
#define WRITE_TRUETYPE_STRIPPED 0x1000	/* internal */
37
#define WRITE_TRUETYPE_CID 0x2000 /* internal */
38
 
39
#define MAX_COMPOSITE_PIECES 3	/* adhoc */
40
 
41
/*
42
 * The following are only for debugging.  They force various format choices
43
 * in the output.  The normal (non-debugging) values for all of these are
44
 * as indicated in the comments.
45
 *
46
 * Note that these options interact.  Here is the complete list of settings
47
 * that make sense.
48
 
49
	0xf000	-1	N/A	1	0,1
50
	0xf000	0,1	0,1	1	0,1
51
 */
52
/* Define whether to use the 0xf000 character bias for generated tables. */
53
#define TT_BIAS 0xf000		/* 0xf000 */
54
/* Define whether to use cmap format 6 never(-1), sometimes(0), always(1). */
55
#define TT_FORCE_CMAP_6 0	/* 0 */
56
/* Define whether to use the bias for the cmap format 6 "first code". */
57
#define TT_BIAS_CMAP_6 0	/* 0 */
58
/* Define whether to generate an OS/2 table if none is supplied. */
59
#define TT_GENERATE_OS_2 1	/* 1 */
60
/* Define whether to adjust the OS/2 range bits. */
61
#define TT_ADJUST_OS_2 1	/* 1 */
62
/*
63
 * End of options.
64
 */
65
 
66
/* ---------------- Utilities ---------------- */
67
 
68
#define ACCESS(base, length, vptr)\
69
  BEGIN\
70
    code = string_proc(pfont, (ulong)(base), length, &vptr);\
71
    if (code < 0) return code;\
72
  END
73
 
74
/* Pad to a multiple of 4 bytes. */
75
private void
76
put_pad(stream *s, uint length)
77
{
78
    static const byte pad_to_4[3] = {0, 0, 0};
79
 
80
    stream_write(s, pad_to_4, (uint)(-(int)length & 3));
81
}
82
 
83
/* Put short and long values on a stream. */
84
private void
85
put_ushort(stream *s, uint v)
86
{
87
    stream_putc(s, (byte)(v >> 8));
88
    stream_putc(s, (byte)v);
89
}
90
private void
91
put_ulong(stream *s, ulong v)
92
{
93
    put_ushort(s, (uint)(v >> 16));
94
    put_ushort(s, (uint)v);
95
}
96
private void
97
put_loca(stream *s, ulong offset, int indexToLocFormat)
98
{
99
    if (indexToLocFormat)
100
	put_ulong(s, offset);
101
    else
102
	put_ushort(s, (uint)(offset >> 1));
103
}
104
 
105
/* Get or put 2- or 4-byte quantities from/into a table. */
106
#define U8(p) ((uint)((p)[0]))
107
#define S8(p) (int)((U8(p) ^ 0x80) - 0x80)
108
#define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
109
#define S16(p) (int)((U16(p) ^ 0x8000) - 0x8000)
110
#define u32(p) get_u32_msb(p)
111
private void
112
put_u16(byte *p, uint v)
113
{
114
    p[0] = (byte)(v >> 8);
115
    p[1] = (byte)v;
116
}
117
private void
118
put_u32(byte *p, ulong v)
119
{
120
    put_u16(p, (ushort)(v >> 16));
121
    put_u16(p + 2, (ushort)v);
122
}
123
private ulong
124
put_table(byte tab[16], const char *tname, ulong checksum, ulong offset,
125
	  uint length)
126
{
127
    memcpy(tab, (const byte *)tname, 4);
128
    put_u32(tab + 4, checksum);
129
    put_u32(tab + 8, offset + 0x40000000);
130
    put_u32(tab + 12, (ulong)length);
131
    return offset + round_up(length, 4);
132
}
133
 
134
/* Write one range of a TrueType font. */
135
private int
136
write_range(stream *s, gs_font_type42 *pfont, ulong start, uint length)
137
{
138
    ulong base = start;
139
    ulong limit = base + length;
140
 
141
    if_debug3('l', "[l]write_range pos = %ld, start = %lu, length = %u\n",
142
	      stell(s), start, length);
143
    while (base < limit) {
144
	uint size = limit - base;
145
	const byte *ptr;
146
	int code;
147
 
148
	/* Write the largest block we can access consecutively. */
149
	while ((code = pfont->data.string_proc(pfont, base, size, &ptr)) < 0) {
150
	    if (size <= 1)
151
		return code;
152
	    size >>= 1;
153
	}
154
	if (code > 0 && size > code)
155
	    size = code; /* Segmented data - see z42_string_proc. */
156
	stream_write(s, ptr, size);
157
	base += size;
158
    }
159
    return 0;
160
}
161
 
162
/*
163
 * Determine the Macintosh glyph number for a given character, if any.
164
 * If no glyph can be found, return -1 and store the name in *pstr.
165
 */
166
private int
167
mac_glyph_index(gs_font *font, int ch, gs_const_string *pstr)
168
{
169
    gs_glyph glyph = font->procs.encode_char(font, (gs_char)ch,
170
					     GLYPH_SPACE_NAME);
171
    int code;
172
 
173
    if (glyph == gs_no_glyph)
174
	return 0;		/* .notdef */
175
    code = font->procs.glyph_name(font, glyph, pstr);
176
    assert(code >= 0);
177
    if (glyph < gs_min_cid_glyph) {
178
	gs_char mac_char;
179
	gs_glyph mac_glyph;
180
	gs_const_string mstr;
181
 
182
	/* Look (not very hard) for a match in the Mac glyph space. */
183
	if (ch >= 32 && ch <= 126)
184
	    mac_char = ch - 29;
185
	else if (ch >= 128 && ch <= 255)
186
	    mac_char = ch - 30;
187
	else
188
	    return -1;
189
	mac_glyph = gs_c_known_encode(mac_char, ENCODING_INDEX_MACGLYPH);
190
	if (mac_glyph == gs_no_glyph)
191
	    return -1;
192
	code = gs_c_glyph_name(mac_glyph, &mstr);
193
	assert(code >= 0);
194
	if (!bytes_compare(pstr->data, pstr->size, mstr.data, mstr.size))
195
	    return (int)mac_char;
196
    }
197
    return -1;
198
}
199
 
200
/* ---------------- Individual tables ---------------- */
201
 
202
/* ------ cmap ------ */
203
 
204
/* Write a generated cmap table. */
205
static const byte cmap_initial_0[] = {
206
    0, 0,		/* table version # = 0 */
207
    0, 2,		/* # of encoding tables = 2 */
208
 
209
	/* First table, Macintosh */
210
    0, 1,		/* platform ID = Macintosh */
211
    0, 0,		/* platform encoding ID = ??? */
212
    0, 0, 0, 4+8+8,	/* offset to table start */
213
	/* Second table, Windows */
214
    0, 3,		/* platform ID = Microsoft */
215
    0, 0,		/* platform encoding ID = unknown */
216
    0, 0, 1, 4+8+8+6,	/* offset to table start */
217
 
218
	/* Start of Macintosh format 0 table */
219
    0, 0,		/* format = 0, byte encoding table */
220
    1, 6,		/* length */
221
    0, 0		/* version number */
222
};
223
static const byte cmap_initial_6[] = {
224
    0, 0,		/* table version # = 0 */
225
    0, 2,		/* # of encoding tables = 2 */
226
 
227
	/* First table, Macintosh */
228
    0, 1,		/* platform ID = Macintosh */
229
    0, 0,		/* platform encoding ID = ??? */
230
    0, 0, 0, 4+8+8,	/* offset to table start */
231
	/* Second table, Windows */
232
    0, 3,		/* platform ID = Microsoft */
233
    0, 0,		/* platform encoding ID = unknown */
234
    0, 0, 0, 4+8+8+10,	/* offset to table start */
235
			/* *VARIABLE*, add 2 x # of entries */
236
 
237
	/* Start of Macintosh format 6 table */
238
    0, 6,		/* format = 6, trimmed table mapping */
239
    0, 10,		/* length *VARIABLE*, add 2 x # of entries */
240
    0, 0,		/* version number */
241
    0, 0,		/* first character code */
242
    0, 0		/* # of entries *VARIABLE* */
243
};
244
static const byte cmap_initial_4[] = {
245
    0, 0,		/* table version # = 0 */
246
    0, 1,		/* # of encoding tables = 2 */
247
 
248
	/* Single table, Windows */
249
    0, 3,		/* platform ID = Microsoft */
250
    0, 0,		/* platform encoding ID = unknown */
251
    0, 0, 0, 4+8	/* offset to table start */
252
};
253
static const byte cmap_sub_initial[] = {
254
    0, 4,		/* format = 4, segment mapping */
255
    0, 32,		/* length ** VARIABLE, add 2 x # of glyphs ** */
256
    0, 0,		/* version # */
257
    0, 4,		/* 2 x segCount */
258
    0, 4,		/* searchRange = 2 x 2 ^ floor(log2(segCount)) */
259
    0, 1,		/* floor(log2(segCount)) */
260
    0, 0,		/* 2 x segCount - searchRange */
261
 
262
    0, 0,		/* endCount[0] **VARIABLE** */
263
    255, 255,		/* endCount[1] */
264
    0, 0,		/* reservedPad */
265
    0, 0,		/* startCount[0] **VARIABLE** */
266
    255, 255,		/* startCount[1] */
267
    0, 0,		/* idDelta[0] */
268
    0, 1,		/* idDelta[1] */
269
    0, 4,		/* idRangeOffset[0] */
270
    0, 0		/* idRangeOffset[1] */
271
};
272
/*
273
 * The following nonsense is required because C defines sizeof()
274
 * inconsistently.
275
 */
276
#define CMAP_ENTRIES_SIZE (256 * 2)
277
private void
278
write_cmap_0(stream *s, byte* entries /*[CMAP_ENTRIES_SIZE]*/, uint num_glyphs)
279
{
280
    int i;
281
 
282
    memset(entries + 2 * num_glyphs, 0, CMAP_ENTRIES_SIZE - 2 * num_glyphs);
283
    stream_write(s, cmap_initial_0, sizeof(cmap_initial_0));
284
    for (i = 0; i <= 0xff; ++i)
285
	sputc(s, (byte)entries[2 * i + 1]);
286
}
287
private void
288
write_cmap_6(stream *s, byte *entries /*[CMAP_ENTRIES_SIZE]*/, uint first_code,
289
	     uint first_entry, uint num_entries)
290
{
291
    byte cmap_data[sizeof(cmap_initial_6)];
292
 
293
    memcpy(cmap_data, cmap_initial_6, sizeof(cmap_initial_6));
294
    put_u16(cmap_data + 18,
295
	    U16(cmap_data + 18) + num_entries * 2);  /* offset */
296
    put_u16(cmap_data + 22,
297
	    U16(cmap_data + 22) + num_entries * 2);  /* length */
298
    put_u16(cmap_data + 26,
299
#if TT_BIAS_CMAP_6
300
	    first_code +
301
#endif
302
	    first_entry);
303
    put_u16(cmap_data + 28, num_entries);
304
    stream_write(s, cmap_data, sizeof(cmap_data));
305
    stream_write(s, entries + first_entry * 2, num_entries * 2);
306
}
307
private void
308
write_cmap(stream *s, gs_font *font, uint first_code, int num_glyphs,
309
	   gs_glyph max_glyph, int options, uint cmap_length)
310
{
311
    byte cmap_sub[sizeof(cmap_sub_initial)];
312
    byte entries[CMAP_ENTRIES_SIZE];
313
    int first_entry = 0, end_entry = num_glyphs;
314
    bool can_use_trimmed = !(options & WRITE_TRUETYPE_NO_TRIMMED_TABLE);
315
    uint merge = 0;
316
    uint num_entries;
317
    int i;
318
 
319
    /* Collect the table entries. */
320
 
321
    for (i = 0; i < num_glyphs; ++i) {
322
	gs_glyph glyph =
323
	    font->procs.encode_char(font, (gs_char)i, GLYPH_SPACE_INDEX);
324
	uint glyph_index;
325
 
326
	if (glyph == gs_no_glyph || glyph < GS_MIN_GLYPH_INDEX ||
327
	    glyph > max_glyph
328
	    )
329
	    glyph = GS_MIN_GLYPH_INDEX;
330
	glyph_index = (uint)(glyph - GS_MIN_GLYPH_INDEX);
331
	merge |= glyph_index;
332
	put_u16(entries + 2 * i, glyph_index);
333
    }
334
    while (end_entry > first_entry && !U16(entries + 2 * end_entry - 2))
335
	--end_entry;
336
    while (first_entry < end_entry && !U16(entries + 2 * first_entry))
337
	++first_entry;
338
    num_entries = end_entry - first_entry;
339
 
340
    /* Write the table header and Macintosh sub-table (if any). */
341
 
342
#if TT_FORCE_CMAP_6 > 0
343
    /* Always use format 6. */
344
    write_cmap_6(s, entries, first_code, first_entry, num_entries);
345
#else
346
# if TT_FORCE_CMAP_6 < 0
347
    /* Never use format 6.  Use format 0 if possible. */
348
    if (merge == (byte)merge)
349
	write_cmap_0(s, entries, num_glyphs);
350
    else
351
# else /* TT_FORCE_CMAP == 0 */
352
    /*
353
     * Use format 0 if possible and (economical or format 6 disallowed),
354
     * otherwise format 6 if allowed.
355
     */
356
    if (merge == (byte)merge && (num_entries <= 127 || !can_use_trimmed))
357
	write_cmap_0(s, entries, num_glyphs);
358
    else if (can_use_trimmed)
359
	write_cmap_6(s, entries, first_code, first_entry, num_entries);
360
    else
361
# endif
362
    {
363
	/*
364
	 * Punt.  Acrobat Reader 3 can't handle any other Mac table format.
365
	 * (AR3 for Linux doesn't seem to be able to handle Windows format,
366
	 * either, but maybe AR3 for Windows can.)
367
	 */
368
	stream_write(s, cmap_initial_4, sizeof(cmap_initial_4));
369
    }
370
#endif
371
 
372
    /* Write the Windows sub-table. */
373
 
374
    memcpy(cmap_sub, cmap_sub_initial, sizeof(cmap_sub_initial));
375
    put_u16(cmap_sub + 2, U16(cmap_sub + 2) + num_entries * 2); /* length */
376
    put_u16(cmap_sub + 14, first_code + end_entry - 1); /* endCount[0] */
377
    put_u16(cmap_sub + 20, first_code + first_entry); /* startCount[0] */
378
    stream_write(s, cmap_sub, sizeof(cmap_sub));
379
    stream_write(s, entries + first_entry * 2, num_entries * 2);
380
    put_pad(s, cmap_length);
381
}
382
private uint
383
size_cmap(gs_font *font, uint first_code, int num_glyphs, gs_glyph max_glyph,
384
	  int options)
385
{
386
    stream poss;
387
 
388
    s_init(&poss, NULL);
389
    swrite_position_only(&poss);
390
    write_cmap(&poss, font, first_code, num_glyphs, max_glyph, options, 0);
391
    return stell(&poss);
392
}
393
 
394
/* ------ hmtx/vmtx ------ */
395
 
396
/*
397
 * avoid fp exceptions storing large doubles into integers by limiting
398
 * the range of the results.  these are band-aids that don't fix the
399
 * root cause of the out-of-range results, but they keep gs on the rails.
400
 */
401
 
402
ushort
403
limdbl2ushort(double d)
404
{
405
	if (d < 0)
406
		return 0;
407
	else if (d > 64000)
408
		return 64000;
409
	else
410
		return d;
411
}
412
 
413
long
414
limdbl2long(double d)
415
{
416
	if (d > 2e9)
417
		return 2e9;
418
	else if (d < -2e9)
419
		return -2e9;
420
	else
421
		return d;
422
}
423
 
424
private void
425
write_mtx(stream *s, gs_font_type42 *pfont, const gs_type42_mtx_t *pmtx,
426
	  int wmode)
427
{
428
    uint num_metrics = pmtx->numMetrics;
429
    uint len = num_metrics * 4;
430
    double factor = pfont->data.unitsPerEm * (wmode ? -1 : 1);
431
    float sbw[4];
432
    uint i;
433
 
434
    sbw[0] = sbw[1] = sbw[2] = sbw[3] = 0; /* in case of failures */
435
    for (i = 0; i < pmtx->numMetrics; ++i) {
436
	DISCARD(pfont->data.get_metrics(pfont, i, wmode, sbw));
437
	put_ushort(s, limdbl2ushort(sbw[wmode + 2] * factor)); /* width */
438
	put_ushort(s, limdbl2ushort(sbw[wmode] * factor)); /* lsb, may be <0 */
439
    }
440
    for (; len < pmtx->length; ++i, len += 2) {
441
	DISCARD(pfont->data.get_metrics(pfont, i, wmode, sbw));
442
	put_ushort(s, limdbl2ushort(sbw[wmode] * factor)); /* lsb, may be <0 */
443
    }
444
}
445
 
446
/* Compute the metrics from the glyph_info. */
447
private uint
448
size_mtx(gs_font_type42 *pfont, gs_type42_mtx_t *pmtx, uint max_glyph,
449
	 int wmode)
450
{
451
    int prev_width = min_int, wmode2;
452
    uint last_width = 0; /* pacify compilers */
453
    double factor = pfont->data.unitsPerEm * (wmode ? -1 : 1);
454
    uint i, j;
455
 
456
    for (i = 0; i <= max_glyph; ++i) {
457
	float sbw[4];
458
	int code, width;
459
 
460
	for (j = 0; j < 4; j++)
461
		sbw[j] = 0;
462
	code = pfont->data.get_metrics(pfont, i, wmode, sbw);
463
	if (code < 0)
464
	    continue;
465
	wmode2 = wmode + 2;
466
	if (wmode2 < 0 || wmode2 >= 4)
467
		abort();	/* "wmode2 out of range" */
468
	width = limdbl2long(sbw[wmode2] * factor + 0.5);
469
	if (width != prev_width)
470
	    prev_width = width, last_width = i;
471
    }
472
    pmtx->numMetrics = last_width + 1;
473
    pmtx->length = pmtx->numMetrics * 4 + (max_glyph - last_width) * 2;
474
    return pmtx->length;
475
}
476
 
477
/* ------ name ------ */
478
 
479
/* Write a generated name table. */
480
static const byte name_initial[] = {
481
    0, 0,			/* format */
482
    0, 1,			/* # of records = 1 */
483
    0, 18,			/* start of string storage */
484
 
485
    0, 2,			/* platform ID = ISO */
486
    0, 2,			/* encoding ID = ISO 8859-1 */
487
    0, 0,			/* language ID (none) */
488
    0, 6,			/* name ID = PostScript name */
489
    0, 0,			/* length *VARIABLE* */
490
    0, 0			/* start of string within string storage */
491
};
492
private uint
493
size_name(const gs_const_string *font_name)
494
{
495
    return sizeof(name_initial) + font_name->size;
496
}
497
private void
498
write_name(stream *s, const gs_const_string *font_name)
499
{
500
    byte name_bytes[sizeof(name_initial)];
501
 
502
    memcpy(name_bytes, name_initial, sizeof(name_initial));
503
    put_u16(name_bytes + 14, font_name->size);
504
    stream_write(s, name_bytes, sizeof(name_bytes));
505
    stream_write(s, font_name->data, font_name->size);
506
    put_pad(s, size_name(font_name));
507
}
508
 
509
/* ------ OS/2 ------ */
510
 
511
/* Write a generated OS/2 table. */
512
#define OS_2_LENGTH sizeof(ttf_OS_2_t)
513
private void
514
update_OS_2(ttf_OS_2_t *pos2, uint first_glyph, int num_glyphs)
515
{
516
    put_u16(pos2->usFirstCharIndex, first_glyph);
517
    put_u16(pos2->usLastCharIndex, first_glyph + num_glyphs - 1);
518
#if TT_ADJUST_OS_2
519
    if (first_glyph >= 0xf000) {
520
	/* This font is being treated as a symbolic font. */
521
	memset(pos2->ulUnicodeRanges, 0, sizeof(pos2->ulUnicodeRanges));
522
	pos2->ulUnicodeRanges[7] = 8; /* bit 60, private use range */
523
	memset(pos2->ulCodePageRanges, 0, sizeof(pos2->ulCodePageRanges));
524
	pos2->ulCodePageRanges[3] = 1; /* bit 31, symbolic */
525
    }
526
#endif
527
}
528
private void
529
write_OS_2(stream *s, gs_font *font, uint first_glyph, int num_glyphs)
530
{
531
    ttf_OS_2_t os2;
532
 
533
    /*
534
     * We don't bother to set most of the fields.  The really important
535
     * ones, which affect character mapping, are usFirst/LastCharIndex.
536
     * We also need to set usWeightClass and usWidthClass to avoid
537
     * crashing ttfdump.
538
     */
539
    memset(&os2, 0, sizeof(os2));
540
    put_u16(os2.version, 1);
541
    put_u16(os2.usWeightClass, 400); /* Normal */
542
    put_u16(os2.usWidthClass, 5); /* Normal */
543
    update_OS_2(&os2, first_glyph, num_glyphs);
544
    stream_write(s, &os2, sizeof(os2));
545
    put_pad(s, sizeof(os2));
546
}
547
 
548
/* ------ post ------ */
549
 
550
/* Construct and then write the post table. */
551
typedef struct post_glyph_s {
552
    byte char_index;
553
    byte size;
554
    ushort glyph_index;
555
} post_glyph_t;
556
private int
557
compare_post_glyphs(const void *pg1, const void *pg2)
558
{
559
    gs_glyph g1 = ((const post_glyph_t *)pg1)->glyph_index,
560
	g2 = ((const post_glyph_t *)pg2)->glyph_index;
561
 
562
    return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
563
}
564
typedef struct post_s {
565
    post_glyph_t glyphs[256 + 1];
566
    int count, glyph_count;
567
    uint length;
568
} post_t;
569
 
570
/*
571
 * If necessary, compute the length of the post table.  Note that we
572
 * only generate post entries for characters in the Encoding.
573
 */
574
private void
575
compute_post(gs_font *font, post_t *post)
576
{
577
    int i;
578
 
579
    for (i = 0, post->length = 32 + 2; i <= 255; ++i) {
580
	gs_const_string str;
581
	gs_glyph glyph = font->procs.encode_char(font, (gs_char)i,
582
						 GLYPH_SPACE_INDEX);
583
	int mac_index = mac_glyph_index(font, i, &str);
584
 
585
	if (mac_index != 0) {
586
	    post->glyphs[post->count].char_index = i;
587
	    post->glyphs[post->count].size =
588
		(mac_index < 0 ? str.size + 1 : 0);
589
	    post->glyphs[post->count].glyph_index = glyph - GS_MIN_GLYPH_INDEX;
590
	    post->count++;
591
	}
592
    }
593
    if (post->count) {
594
	int j;
595
 
596
	qsort(post->glyphs, post->count, sizeof(post->glyphs[0]),
597
	      compare_post_glyphs);
598
	/* Eliminate duplicate references to the same glyph. */
599
	for (i = j = 0; i < post->count; ++i) {
600
	    if (i == 0 ||
601
		post->glyphs[i].glyph_index !=
602
		post->glyphs[i - 1].glyph_index
603
		) {
604
		post->length += post->glyphs[i].size;
605
		post->glyphs[j++] = post->glyphs[i];
606
	    }
607
	}
608
	post->count = j;
609
	post->glyph_count = post->glyphs[post->count - 1].glyph_index + 1;
610
    }
611
    post->length += post->glyph_count * 2;
612
}
613
 
614
/* Write the post table */
615
private void
616
write_post(stream *s, gs_font *font, post_t *post)
617
{
618
    byte post_initial[32 + 2];
619
    uint name_index;
620
    uint glyph_index;
621
    int i;
622
 
623
    memset(post_initial, 0, 32);
624
    put_u32(post_initial, 0x00020000);
625
    put_u16(post_initial + 32, post->glyph_count);
626
    stream_write(s, post_initial, sizeof(post_initial));
627
 
628
    /* Write the name index table. */
629
 
630
    for (i = 0, name_index = 258, glyph_index = 0; i < post->count; ++i) {
631
	gs_const_string str;
632
	int ch = post->glyphs[i].char_index;
633
	int mac_index = mac_glyph_index(font, ch, &str);
634
 
635
	for (; glyph_index < post->glyphs[i].glyph_index; ++glyph_index)
636
	    put_ushort(s, 0);
637
	glyph_index++;
638
	if (mac_index >= 0)
639
	    put_ushort(s, mac_index);
640
	else {
641
	    put_ushort(s, name_index);
642
	    name_index++;
643
	}
644
    }
645
 
646
    /* Write the string names of the glyphs. */
647
 
648
    for (i = 0; i < post->count; ++i) {
649
	gs_const_string str;
650
	int ch = post->glyphs[i].char_index;
651
	int mac_index = mac_glyph_index(font, ch, &str);
652
 
653
	if (mac_index < 0) {
654
	    spputc(s, (byte)str.size);
655
	    stream_write(s, str.data, str.size);
656
	}
657
    }
658
    put_pad(s, post->length);
659
}
660
 
661
/* ---------------- Main program ---------------- */
662
 
663
/* Write the definition of a TrueType font. */
664
private int
665
compare_table_tags(const void *pt1, const void *pt2)
666
{
667
    ulong t1 = u32(pt1), t2 = u32(pt2);
668
 
669
    return (t1 < t2 ? -1 : t1 > t2 ? 1 : 0);
670
}
671
private int
672
psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
673
			psf_glyph_enum_t *penum, bool is_subset,
674
			const gs_const_string *alt_font_name)
675
{
676
    gs_font *const font = (gs_font *)pfont;
677
    gs_const_string font_name;
678
    int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
679
	pfont->data.string_proc;
680
    const byte *OffsetTable;
681
    uint numTables_stored, numTables, numTables_out;
682
#define MAX_NUM_TABLES 40
683
    byte tables[MAX_NUM_TABLES * 16];
684
    uint i;
685
    ulong offset;
686
    gs_glyph glyph, glyph_prev;
687
    ulong max_glyph;
688
    uint glyf_length, loca_length;
689
    ulong glyf_checksum = 0L; /****** NO CHECKSUM ******/
690
    ulong loca_checksum[2] = {0L,0L};
691
    ulong glyf_alignment = 0;
692
    uint numGlyphs = 0;		/* original value from maxp */
693
    byte head[56];		/* 0 mod 4 */
694
    gs_type42_mtx_t mtx[2];
695
    post_t post;
696
    ulong head_checksum, file_checksum = 0;
697
    int indexToLocFormat = 0;
698
    bool
699
	writing_cid = (options & WRITE_TRUETYPE_CID) != 0,
700
	writing_stripped = (options & WRITE_TRUETYPE_STRIPPED) != 0,
701
	generate_mtx = (options & WRITE_TRUETYPE_HVMTX) != 0,
702
	no_generate = writing_cid | writing_stripped,
703
	have_cmap = no_generate,
704
	have_name = !(options & WRITE_TRUETYPE_NAME),
705
	have_OS_2 = no_generate,
706
	have_post = no_generate;
707
    int have_hvhea[2];
708
    uint cmap_length = 0;
709
    ulong OS_2_start = 0;
710
    uint OS_2_length = OS_2_LENGTH;
711
    int code;
712
 
713
    have_hvhea[0] = have_hvhea[1] = 0;
714
    if (alt_font_name)
715
	font_name = *alt_font_name;
716
    else
717
	font_name.data = font->font_name.chars,
718
	    font_name.size = font->font_name.size;
719
 
720
    /*
721
     * Count the number of tables, including the eventual glyf and loca
722
     * (which may not actually be present in the font), and copy the
723
     * table directory.
724
     */
725
 
726
    ACCESS(0, 12, OffsetTable);
727
    numTables_stored = U16(OffsetTable + 4);
728
    for (i = numTables = 0; i < numTables_stored; ++i) {
729
	const byte *tab;
730
	const byte *data;
731
	ulong start;
732
	uint length;
733
 
734
	if (numTables == MAX_NUM_TABLES)
735
	    return_error(gs_error_limitcheck);
736
	ACCESS(12 + i * 16, 16, tab);
737
	start = u32(tab + 8);
738
	length = u32(tab + 12);
739
	/* Copy the table data now, since another ACCESS may invalidate it. */
740
	memcpy(&tables[numTables * 16], tab, 16);
741
 
742
#define W(a,b,c,d)\
743
  ( ((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
744
 
745
	switch (u32(tab)) {
746
	case W('h','e','a','d'):
747
	    if (length != 54)
748
		return_error(gs_error_invalidfont);
749
	    ACCESS(start, length, data);
750
	    memcpy(head, data, length);
751
	    continue;
752
	case W('g','l','y','f'): /* synthesized */
753
	case W('g','l','y','x'): /* Adobe bogus */
754
	case W('l','o','c','a'): /* synthesized */
755
	case W('l','o','c','x'): /* Adobe bogus */
756
	case W('g','d','i','r'): /* Adobe marker */
757
	    continue;
758
	case W('c','m','a','p'):
759
	    if (options & (WRITE_TRUETYPE_CMAP | WRITE_TRUETYPE_CID))
760
		continue;
761
	    have_cmap = true;
762
	    break;
763
	case W('m','a','x','p'):
764
	    ACCESS(start, length, data);
765
	    numGlyphs = U16(data + 4);
766
	    break;
767
	case W('n','a','m','e'):
768
	    if (writing_cid)
769
		continue;
770
	    have_name = true;
771
	    break;
772
	case W('O','S','/','2'):
773
	    if (writing_cid)
774
		continue;
775
	    have_OS_2 = true;
776
	    if (length > OS_2_LENGTH)
777
		return_error(gs_error_invalidfont);
778
	    OS_2_start = start;
779
	    OS_2_length = length;
780
	    continue;
781
	case W('p','o','s','t'):
782
	    have_post = true;
783
	    break;
784
	case W('h','h','e','a'):
785
	    have_hvhea[0] = 1;
786
	    break;
787
	case W('v','h','e','a'):
788
	    have_hvhea[1] = 1;
789
	    break;
790
	case W('h','m','t','x'):
791
	case W('v','m','t','x'):
792
	    if (generate_mtx)
793
		continue;
794
	    /* falls through */
795
	case W('c','v','t',' '):
796
	case W('f','p','g','m'):
797
	case W('g','a','s','p'):
798
	case W('k','e','r','n'):
799
	case W('p','r','e','p'):
800
	    break;		/* always copy these if present */
801
	default:
802
	    if (writing_cid)
803
		continue;
804
	    break;
805
	}
806
	numTables++;
807
    }
808
 
809
    /*
810
     * Enumerate the glyphs to get the size of glyf and loca,
811
     * and to compute the checksums for these tables.
812
     */
813
 
814
    /****** NO CHECKSUMS YET ******/
815
    for (max_glyph = 0, glyf_length = 0;
816
	 (code = psf_enumerate_glyphs_next(penum, &glyph)) != 1;
817
	 ) {
818
	uint glyph_index;
819
	gs_glyph_data_t glyph_data;
820
 
821
	if (glyph < gs_min_cid_glyph)
822
	    return_error(gs_error_invalidfont);
823
	glyph_index = glyph  & ~GS_GLYPH_TAG;
824
	if_debug1('L', "[L]glyph_index %u\n", glyph_index);
825
	glyph_data.memory = pfont->memory;
826
	if ((code = pfont->data.get_outline(pfont, glyph_index, &glyph_data)) >= 0) {
827
	    /* Since indexToLocFormat==0 assumes even glyph lengths,
828
	       round it up here. If later we choose indexToLocFormat==1,
829
	       subtract the glyf_alignment to compensate it. */
830
	    uint l = (glyph_data.bits.size + 1) & ~1;
831
 
832
	    max_glyph = max(max_glyph, glyph_index);
833
	    glyf_length += l;
834
	    if (l != glyph_data.bits.size)
835
		glyf_alignment++;
836
	    if_debug1('L', "[L]  size %u\n", glyph_data.bits.size);
837
	    gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
838
	}
839
    }
840
    /*
841
     * For subset fonts, we should trim the loca table so that it only
842
     * contains entries through max_glyph.  Unfortunately, this would
843
     * require changing numGlyphs in maxp, which in turn would affect hdmx,
844
     * hhea, hmtx, vdmx, vhea, vmtx, and possibly other tables.  This is way
845
     * more work than we want to do right now.
846
     */
847
    if (writing_stripped) {
848
	glyf_length = 0;
849
	loca_length = 0;
850
    } else {
851
	/*loca_length = (max_glyph + 2) << 2;*/
852
	loca_length = (numGlyphs + 1) << 2;
853
	indexToLocFormat = (glyf_length > 0x1fffc);
854
	if (!indexToLocFormat)
855
	    loca_length >>= 1;
856
	else
857
	    glyf_length -= glyf_alignment;
858
	/* Acrobat Reader won't accept fonts with empty glyfs. */
859
	if (glyf_length == 0)
860
	    glyf_length = 1;
861
    }
862
    if_debug2('l', "[l]max_glyph = %lu, glyf_length = %lu\n",
863
	      (ulong)max_glyph, (ulong)glyf_length);
864
 
865
    /*
866
     * If necessary, compute the length of the post table.  Note that we
867
     * only generate post entries for characters in the Encoding.  */
868
 
869
    if (!have_post) {
870
	memset(&post, 0, sizeof(post));
871
	if (options & WRITE_TRUETYPE_POST)
872
	    compute_post(font, &post);
873
	else
874
	    post.length = 32;	/* dummy table */
875
    }
876
 
877
    /* Fix up the head table. */
878
 
879
    memset(head + 8, 0, 4);
880
    head[51] = (byte)indexToLocFormat;
881
    memset(head + 54, 0, 2);
882
    for (head_checksum = 0, i = 0; i < 56; i += 4)
883
	head_checksum += u32(&head[i]);
884
 
885
    /*
886
     * Construct the table directory, except for glyf, loca, head, OS/2,
887
     * and, if necessary, generated cmap, name, and post tables.
888
     * Note that the existing directory is already sorted by tag.
889
     */
890
 
891
    numTables_out = numTables + 1 /* head */
892
	+ !writing_stripped * 2	/* glyf, loca */
893
	+ generate_mtx * (have_hvhea[0] + have_hvhea[1]) /* hmtx, vmtx */
894
	+ !have_OS_2		/* OS/2 */
895
	+ !have_cmap + !have_name + !have_post;
896
    if (numTables_out >= MAX_NUM_TABLES)
897
	return_error(gs_error_limitcheck);
898
    offset = 12 + numTables_out * 16;
899
    for (i = 0; i < numTables; ++i) {
900
	byte *tab = &tables[i * 16];
901
	ulong length = u32(tab + 12);
902
 
903
	offset += round_up(length, 4);
904
    }
905
 
906
    /* Make the table directory entries for generated tables. */
907
 
908
    {
909
	byte *tab = &tables[numTables * 16];
910
 
911
	if (!writing_stripped) {
912
	    offset = put_table(tab, "glyf", glyf_checksum,
913
			       offset, glyf_length);
914
	    tab += 16;
915
 
916
	    offset = put_table(tab, "loca", loca_checksum[indexToLocFormat],
917
			       offset, loca_length);
918
	    tab += 16;
919
	}
920
 
921
	if (!have_cmap) {
922
	    cmap_length = size_cmap(font, TT_BIAS, 256,
923
				    GS_MIN_GLYPH_INDEX + max_glyph, options);
924
	    offset = put_table(tab, "cmap", 0L /****** NO CHECKSUM ******/,
925
			       offset, cmap_length);
926
	    tab += 16;
927
	}
928
 
929
	if (!have_name) {
930
	    offset = put_table(tab, "name", 0L /****** NO CHECKSUM ******/,
931
			       offset, size_name(&font_name));
932
	    tab += 16;
933
	}
934
 
935
	if (!no_generate) {
936
	    offset = put_table(tab, "OS/2", 0L /****** NO CHECKSUM ******/,
937
			       offset, OS_2_length);
938
	    tab += 16;
939
	}
940
 
941
	if (generate_mtx)
942
	    for (i = 0; i < 2; ++i)
943
		if (have_hvhea[i]) {
944
		    offset = put_table(tab, (i ? "vmtx" : "hmtx"),
945
				       0L /****** NO CHECKSUM ******/,
946
				       offset,
947
				       size_mtx(pfont, &mtx[i], max_glyph, i));
948
		    tab += 16;
949
		}
950
 
951
	if (!have_post) {
952
	    offset = put_table(tab, "post", 0L /****** NO CHECKSUM ******/,
953
			       offset, post.length);
954
	    tab += 16;
955
	}
956
 
957
	/*
958
	 * Note that the 'head' table must have length 54, even though
959
	 * it occupies 56 bytes on the file.
960
	 */
961
	offset = put_table(tab, "head", head_checksum, offset, 54);
962
	tab += 16;
963
    }
964
    numTables = numTables_out;
965
 
966
    /* Write the font header. */
967
 
968
    {
969
	static const byte version[4] = {0, 1, 0, 0};
970
 
971
	stream_write(s, version, 4);
972
    }
973
    put_ushort(s, numTables);
974
    for (i = 0; 1 << i <= numTables; ++i)
975
	DO_NOTHING;
976
    --i;
977
    put_ushort(s, 16 << i);	/* searchRange */
978
    put_ushort(s, i);		/* entrySelectors */
979
    put_ushort(s, numTables * 16 - (16 << i)); /* rangeShift */
980
 
981
    /* Write the table directory. */
982
 
983
    qsort(tables, numTables, 16, compare_table_tags);
984
    offset = 12 + numTables * 16;
985
    for (i = 0; i < numTables; ++i) {
986
	const byte *tab = &tables[i * 16];
987
	byte entry[16];
988
 
989
	memcpy(entry, tab, 16);
990
	if (entry[8] < 0x40) {
991
	    /* Not a generated table. */
992
	    uint length = u32(tab + 12);
993
 
994
	    put_u32(entry + 8, offset);
995
	    offset += round_up(length, 4);
996
	} else {
997
	    entry[8] -= 0x40;
998
	}
999
	stream_write(s, entry, 16);
1000
    }
1001
 
1002
    /* Write tables other than the ones we generate here. */
1003
 
1004
    for (i = 0; i < numTables; ++i) {
1005
	const byte *tab = &tables[i * 16];
1006
 
1007
	if (tab[8] < 0x40) {
1008
	    ulong start = u32(tab + 8);
1009
	    uint length = u32(tab + 12);
1010
 
1011
	    switch (u32(tab)) {
1012
	    case W('O','S','/','2'):
1013
		if (!have_cmap) {
1014
		    /*
1015
		     * Adjust the first and last character indices in the OS/2
1016
		     * table to reflect the values in the generated cmap.
1017
		     */
1018
		    const byte *pos2;
1019
		    ttf_OS_2_t os2;
1020
 
1021
		    ACCESS(OS_2_start, OS_2_length, pos2);
1022
		    memcpy(&os2, pos2, min(OS_2_length, sizeof(os2)));
1023
		    update_OS_2(&os2, TT_BIAS, 256);
1024
		    stream_write(s, &os2, OS_2_length);
1025
		    put_pad(s, OS_2_length);
1026
		} else {
1027
		    /* Just copy the existing OS/2 table. */
1028
		    write_range(s, pfont, OS_2_start, OS_2_length);
1029
		    put_pad(s, OS_2_length);
1030
		}
1031
	    break;
1032
	    case W('h','h','e','a'):
1033
	    case W('v','h','e','a'):
1034
		if (generate_mtx) {
1035
		    write_range(s, pfont, start, length - 2); /* 34 */
1036
		    put_ushort(s, mtx[tab[0] == 'v'].numMetrics);
1037
		    break;
1038
		}
1039
		/* falls through */
1040
	    default:
1041
		write_range(s, pfont, start, length);
1042
	    }
1043
	    put_pad(s, length);
1044
	}
1045
    }
1046
 
1047
    if (!writing_stripped) {
1048
 
1049
	/* Write glyf. */
1050
 
1051
	psf_enumerate_glyphs_reset(penum);
1052
	for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
1053
	    gs_glyph_data_t glyph_data;
1054
 
1055
	    glyph_data.memory = pfont->memory;
1056
	    if ((code = pfont->data.get_outline(pfont,
1057
						glyph & ~GS_GLYPH_TAG,
1058
						&glyph_data)) >= 0
1059
		) {
1060
		uint l = glyph_data.bits.size, zero = 0;
1061
 
1062
		if (!indexToLocFormat)
1063
		    l = (l + 1) & ~1;
1064
		stream_write(s, glyph_data.bits.data, glyph_data.bits.size);
1065
		if (glyph_data.bits.size < l)
1066
		    stream_write(s, &zero, 1);
1067
		offset += l;
1068
		if_debug2('L', "[L]glyf index = %u, size = %u\n",
1069
			  i, glyph_data.bits.size);
1070
		gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
1071
	    }
1072
	}
1073
	if_debug1('l', "[l]glyf final offset = %lu\n", offset);
1074
	/* Add a dummy byte if necessary to make glyf non-empty. */
1075
	while (offset < glyf_length)
1076
	    stream_putc(s, 0), ++offset;
1077
	put_pad(s, (uint)offset);
1078
 
1079
	/* Write loca. */
1080
 
1081
	psf_enumerate_glyphs_reset(penum);
1082
	glyph_prev = 0;
1083
	for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
1084
	    gs_glyph_data_t glyph_data;
1085
	    uint glyph_index = glyph & ~GS_GLYPH_TAG;
1086
 
1087
	    for (; glyph_prev <= glyph_index; ++glyph_prev)
1088
		put_loca(s, offset, indexToLocFormat);
1089
	    glyph_data.memory = pfont->memory;
1090
	    if ((code = pfont->data.get_outline(pfont, glyph_index,
1091
						&glyph_data)) >= 0
1092
		) {
1093
		uint l = glyph_data.bits.size;
1094
 
1095
		if (!indexToLocFormat)
1096
		    l = (l + 1) & ~1;
1097
		offset += l;
1098
		gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
1099
	    }
1100
 
1101
	}
1102
	/* Pad to numGlyphs + 1 entries (including the trailing entry). */
1103
	for (; glyph_prev <= numGlyphs; ++glyph_prev)
1104
	    put_loca(s, offset, indexToLocFormat);
1105
	put_pad(s, loca_length);
1106
 
1107
	/* If necessary, write cmap, name, and OS/2. */
1108
 
1109
	if (!have_cmap)
1110
	    write_cmap(s, font, TT_BIAS, 256, GS_MIN_GLYPH_INDEX + max_glyph,
1111
		       options, cmap_length);
1112
	if (!have_name)
1113
	    write_name(s, &font_name);
1114
	if (!have_OS_2)
1115
	    write_OS_2(s, font, TT_BIAS, 256);
1116
 
1117
	/* If necessary, write [hv]mtx. */
1118
 
1119
	if (generate_mtx)
1120
	    for (i = 0; i < 2; ++i)
1121
		if (have_hvhea[i]) {
1122
		    write_mtx(s, pfont, &mtx[i], i);
1123
		    put_pad(s, mtx[i].length);
1124
		}
1125
 
1126
	/* If necessary, write post. */
1127
 
1128
	if (!have_post) {
1129
	    if (options & WRITE_TRUETYPE_POST)
1130
		write_post(s, font, &post);
1131
	    else {
1132
		byte post_initial[32 + 2];
1133
 
1134
		memset(post_initial, 0, 32);
1135
		put_u32(post_initial, 0x00030000);
1136
		stream_write(s, post_initial, 32);
1137
	    }
1138
	}
1139
    }
1140
 
1141
    /* Write head. */
1142
 
1143
    /****** CHECKSUM WAS NEVER COMPUTED ******/
1144
    /*
1145
     * The following nonsense is to avoid warnings about the constant
1146
     * 0xb1b0afbaL being "unsigned in ANSI C, signed with -traditional".
1147
     */
1148
#if ARCH_SIZEOF_LONG > ARCH_SIZEOF_INT
1149
#  define HEAD_MAGIC 0xb1b0afbaL
1150
#else
1151
#  define HEAD_MAGIC ((ulong)~0x4e4f5045)
1152
#endif
1153
    put_u32(head + 8, HEAD_MAGIC - file_checksum); /* per spec */
1154
#undef HEAD_MAGIC
1155
    stream_write(s, head, 56);
1156
 
1157
    return 0;
1158
}
1159
 
1160
/* Write a TrueType font. */
1161
int
1162
psf_write_truetype_font(stream *s, gs_font_type42 *pfont, int options,
1163
			gs_glyph *orig_subset_glyphs, uint orig_subset_size,
1164
			const gs_const_string *alt_font_name)
1165
{
1166
    gs_font *const font = (gs_font *)pfont;
1167
    psf_glyph_enum_t genum;
1168
    gs_glyph subset_data[256 * MAX_COMPOSITE_PIECES];
1169
    gs_glyph *subset_glyphs = orig_subset_glyphs;
1170
    uint subset_size = orig_subset_size;
1171
 
1172
    /* Sort the subset glyphs, if any. */
1173
 
1174
    if (subset_glyphs) {
1175
	/* Add the component glyphs for composites. */
1176
	int code;
1177
 
1178
	memcpy(subset_data, orig_subset_glyphs,
1179
	       sizeof(gs_glyph) * subset_size);
1180
	subset_glyphs = subset_data;
1181
	code = psf_add_subset_pieces(subset_glyphs, &subset_size,
1182
				     countof(subset_data),
1183
				     countof(subset_data),
1184
				     font);
1185
	if (code < 0)
1186
	    return code;
1187
	subset_size = psf_sort_glyphs(subset_glyphs, subset_size);
1188
    }
1189
    psf_enumerate_glyphs_begin(&genum, font, subset_glyphs,
1190
			       (subset_glyphs ? subset_size : 0),
1191
			       GLYPH_SPACE_INDEX);
1192
    return psf_write_truetype_data(s, pfont, options & ~WRITE_TRUETYPE_CID,
1193
				   &genum, subset_glyphs != 0, alt_font_name);
1194
}
1195
/* Write a stripped TrueType font. */
1196
int
1197
psf_write_truetype_stripped(stream *s, gs_font_type42 *pfont)
1198
{
1199
    psf_glyph_enum_t genum;
1200
    byte no_subset = 0;
1201
 
1202
    psf_enumerate_bits_begin(&genum, (gs_font *)pfont, &no_subset, 0,
1203
			     GLYPH_SPACE_INDEX);
1204
    return psf_write_truetype_data(s, pfont, WRITE_TRUETYPE_STRIPPED,
1205
				   &genum, true, NULL);
1206
}
1207
 
1208
/* Write a CIDFontType 2 font. */
1209
int
1210
psf_write_cid2_font(stream *s, gs_font_cid2 *pfont, int options,
1211
		    const byte *subset_bits, uint subset_size,
1212
		    const gs_const_string *alt_font_name)
1213
{
1214
    gs_font *const font = (gs_font *)pfont;
1215
    psf_glyph_enum_t genum;
1216
 
1217
    psf_enumerate_bits_begin(&genum, font, subset_bits,
1218
			     (subset_bits ? subset_size : 0),
1219
			     GLYPH_SPACE_INDEX);
1220
    return psf_write_truetype_data(s, (gs_font_type42 *)font,
1221
				   options | WRITE_TRUETYPE_CID, &genum,
1222
				   subset_bits != 0, alt_font_name);
1223
}
1224
 
1225
/* Write a stripped CIDFontType 2 font. */
1226
int
1227
psf_write_cid2_stripped(stream *s, gs_font_cid2 *pfont)
1228
{
1229
    gs_font *const font = (gs_font *)pfont;
1230
    psf_glyph_enum_t genum;
1231
    byte no_subset = 0;
1232
 
1233
    psf_enumerate_bits_begin(&genum, font, &no_subset, 0,
1234
			     GLYPH_SPACE_INDEX);
1235
    return psf_write_truetype_data(s, (gs_font_type42 *)font,
1236
				   WRITE_TRUETYPE_STRIPPED |
1237
				     WRITE_TRUETYPE_CID,
1238
				   &genum, true, NULL);
1239
}