xref: /plan9/sys/src/cmd/gs/src/gdevpsft.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
1 /* Copyright (C) 1999, 2000 Aladdin Enterprises.  All rights reserved.
2 
3   This file is part of AFPL Ghostscript.
4 
5   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
6   distributor accepts any responsibility for the consequences of using it, or
7   for whether it serves any particular purpose or works at all, unless he or
8   she says so in writing.  Refer to the Aladdin Free Public License (the
9   "License") for full details.
10 
11   Every copy of AFPL Ghostscript must include a copy of the License, normally
12   in a plain ASCII text file named PUBLIC.  The License grants you the right
13   to copy, modify and redistribute AFPL Ghostscript, but only under certain
14   conditions described in the License.  Among other things, the License
15   requires that the copyright notice and this notice be preserved on all
16   copies.
17 */
18 
19 /*$Id: gdevpsft.c,v 1.8 2001/07/30 07:03:18 lpd Exp $ */
20 /* Write an embedded TrueType font */
21 #include "memory_.h"
22 #include <stdlib.h>		/* for qsort */
23 #include "gx.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 #define MAX_COMPOSITE_PIECES 3	/* adhoc */
36 
37 /* ---------------- Utilities ---------------- */
38 
39 #define ACCESS(base, length, vptr)\
40   BEGIN\
41     code = string_proc(pfont, (ulong)(base), length, &vptr);\
42     if (code < 0) return code;\
43   END
44 
45 /* Pad to a multiple of 4 bytes. */
46 private void
47 put_pad(stream *s, uint length)
48 {
49     static const byte pad_to_4[3] = {0, 0, 0};
50 
51     stream_write(s, pad_to_4, (uint)(-length & 3));
52 }
53 
54 /* Put short and long values on a stream. */
55 private void
56 put_ushort(stream *s, uint v)
57 {
58     stream_putc(s, (byte)(v >> 8));
59     stream_putc(s, (byte)v);
60 }
61 private void
62 put_ulong(stream *s, ulong v)
63 {
64     put_ushort(s, (uint)(v >> 16));
65     put_ushort(s, (uint)v);
66 }
67 private void
68 put_loca(stream *s, ulong offset, int indexToLocFormat)
69 {
70     if (indexToLocFormat)
71 	put_ulong(s, offset);
72     else
73 	put_ushort(s, (uint)(offset >> 1));
74 }
75 
76 /* Get or put 2- or 4-byte quantities from/into a table. */
77 #define U8(p) ((uint)((p)[0]))
78 #define S8(p) (int)((U8(p) ^ 0x80) - 0x80)
79 #define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
80 #define S16(p) (int)((U16(p) ^ 0x8000) - 0x8000)
81 #define u32(p) get_u32_msb(p)
82 private void
83 put_u16(byte *p, uint v)
84 {
85     p[0] = (byte)(v >> 8);
86     p[1] = (byte)v;
87 }
88 private void
89 put_u32(byte *p, ulong v)
90 {
91     p[0] = (byte)(v >> 24);
92     p[1] = (byte)(v >> 16);
93     p[2] = (byte)(v >> 8);
94     p[3] = (byte)v;
95 }
96 private ulong
97 put_table(byte tab[16], const char *tname, ulong checksum, ulong offset,
98 	  uint length)
99 {
100     memcpy(tab, (const byte *)tname, 4);
101     put_u32(tab + 4, checksum);
102     put_u32(tab + 8, offset + 0x40000000);
103     put_u32(tab + 12, (ulong)length);
104     return offset + round_up(length, 4);
105 }
106 
107 /* Write one range of a TrueType font. */
108 private int
109 write_range(stream *s, gs_font_type42 *pfont, ulong start, uint length)
110 {
111     ulong base = start;
112     ulong limit = base + length;
113     int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
114 	pfont->data.string_proc;
115 
116     if_debug3('l', "[l]write_range pos = %ld, start = %lu, length = %u\n",
117 	      stell(s), start, length);
118     while (base < limit) {
119 	uint size = limit - base;
120 	const byte *ptr;
121 	int code;
122 
123 	/* Write the largest block we can access consecutively. */
124 	while ((code = string_proc(pfont, base, size, &ptr)) < 0) {
125 	    if (size <= 1)
126 		return code;
127 	    size >>= 1;
128 	}
129 	stream_write(s, ptr, size);
130 	base += size;
131     }
132     return 0;
133 }
134 
135 /*
136  * Determine the Macintosh glyph number for a given character, if any.
137  * If no glyph can be found, return -1 and store the name in *pstr.
138  */
139 private int
140 mac_glyph_index(gs_font *font, int ch, gs_const_string *pstr)
141 {
142     gs_glyph glyph = font->procs.encode_char(font, (gs_char)ch,
143 					     GLYPH_SPACE_NAME);
144 
145     if (glyph == gs_no_glyph)
146 	return 0;		/* .notdef */
147     pstr->data = (const byte *)
148 	font->procs.callbacks.glyph_name(glyph, &pstr->size);
149     if (glyph < gs_min_cid_glyph) {
150 	gs_char mac_char;
151 	gs_glyph mac_glyph;
152 	gs_const_string mstr;
153 
154 	/* Look (not very hard) for a match in the Mac glyph space. */
155 	if (ch >= 32 && ch <= 126)
156 	    mac_char = ch - 29;
157 	else if (ch >= 128 && ch <= 255)
158 	    mac_char = ch - 30;
159 	else
160 	    return -1;
161 	mac_glyph =
162 	    font->procs.callbacks.known_encode(mac_char,
163 					       ENCODING_INDEX_MACGLYPH);
164 	if (mac_glyph == gs_no_glyph)
165 	    return -1;
166 	mstr.data =(const byte *)
167 	    font->procs.callbacks.glyph_name(mac_glyph, &mstr.size);
168 	if (!bytes_compare(pstr->data, pstr->size, mstr.data, mstr.size))
169 	    return (int)mac_char;
170     }
171     return -1;
172 }
173 
174 /* ---------------- Individual tables ---------------- */
175 
176 /* ------ cmap ------ */
177 
178 /* Write a generated cmap table. */
179 static const byte cmap_initial_0[] = {
180     0, 0,		/* table version # = 0 */
181     0, 2,		/* # of encoding tables = 2 */
182 
183 	/* First table, Macintosh */
184     0, 1,		/* platform ID = Macintosh */
185     0, 0,		/* platform encoding ID = ??? */
186     0, 0, 0, 4+8+8,	/* offset to table start */
187 	/* Second table, Windows */
188     0, 3,		/* platform ID = Microsoft */
189     0, 0,		/* platform encoding ID = unknown */
190     0, 0, 1, 4+8+8+6,	/* offset to table start */
191 
192 	/* Start of Macintosh format 0 table */
193     0, 0,		/* format = 0, byte encoding table */
194     1, 6,		/* length */
195     0, 0		/* version number */
196 };
197 static const byte cmap_initial_6[] = {
198     0, 0,		/* table version # = 0 */
199     0, 2,		/* # of encoding tables = 2 */
200 
201 	/* First table, Macintosh */
202     0, 1,		/* platform ID = Macintosh */
203     0, 0,		/* platform encoding ID = ??? */
204     0, 0, 0, 4+8+8,	/* offset to table start */
205 	/* Second table, Windows */
206     0, 3,		/* platform ID = Microsoft */
207     0, 0,		/* platform encoding ID = unknown */
208     0, 0, 0, 4+8+8+10,	/* offset to table start */
209 			/* *VARIABLE*, add 2 x # of entries */
210 
211 	/* Start of Macintosh format 6 table */
212     0, 6,		/* format = 6, trimmed table mapping */
213     0, 10,		/* length *VARIABLE*, add 2 x # of entries */
214     0, 0,		/* version number */
215     0, 0,		/* first character code */
216     0, 0		/* # of entries *VARIABLE* */
217 };
218 static const byte cmap_initial_4[] = {
219     0, 0,		/* table version # = 0 */
220     0, 1,		/* # of encoding tables = 2 */
221 
222 	/* Single table, Windows */
223     0, 3,		/* platform ID = Microsoft */
224     0, 0,		/* platform encoding ID = unknown */
225     0, 0, 0, 4+8	/* offset to table start */
226 };
227 static const byte cmap_sub_initial[] = {
228     0, 4,		/* format = 4, segment mapping */
229     0, 32,		/* length ** VARIABLE, add 2 x # of glyphs ** */
230     0, 0,		/* version # */
231     0, 4,		/* 2 x segCount */
232     0, 4,		/* searchRange = 2 x 2 ^ floor(log2(segCount)) */
233     0, 1,		/* floor(log2(segCount)) */
234     0, 0,		/* 2 x segCount - searchRange */
235 
236     0, 0,		/* endCount[0] **VARIABLE** */
237     255, 255,		/* endCount[1] */
238     0, 0,		/* reservedPad */
239     0, 0,		/* startCount[0] **VARIABLE** */
240     255, 255,		/* startCount[1] */
241     0, 0,		/* idDelta[0] */
242     0, 1,		/* idDelta[1] */
243     0, 4,		/* idRangeOffset[0] */
244     0, 0		/* idRangeOffset[1] */
245 };
246 private void
247 write_cmap(stream *s, gs_font *font, uint first_code, int num_glyphs,
248 	   gs_glyph max_glyph, int options, uint cmap_length)
249 {
250     byte cmap_sub[sizeof(cmap_sub_initial)];
251     byte entries[256 * 2];
252     int first_entry = 0, end_entry = num_glyphs;
253     bool can_use_trimmed = !(options & WRITE_TRUETYPE_NO_TRIMMED_TABLE);
254     uint merge = 0;
255     uint num_entries;
256     int i;
257 
258     /* Collect the table entries. */
259 
260     for (i = 0; i < num_glyphs; ++i) {
261 	gs_glyph glyph =
262 	    font->procs.encode_char(font, (gs_char)i, GLYPH_SPACE_INDEX);
263 	uint glyph_index;
264 
265 	if (glyph == gs_no_glyph || glyph < gs_min_cid_glyph ||
266 	    glyph > max_glyph
267 	    )
268 	    glyph = gs_min_cid_glyph;
269 	glyph_index = (uint)(glyph - gs_min_cid_glyph);
270 	merge |= glyph_index;
271 	put_u16(entries + 2 * i, glyph_index);
272     }
273     while (end_entry > first_entry && !U16(entries + 2 * end_entry - 2))
274 	--end_entry;
275     while (first_entry < end_entry && !U16(entries + 2 * first_entry))
276 	++first_entry;
277     num_entries = end_entry - first_entry;
278 
279     /* Write the table header and Macintosh sub-table (if any). */
280     if (merge == (byte)merge && (num_entries <= 127 || !can_use_trimmed)) {
281 	/* Use byte encoding format. */
282 	memset(entries + 2 * num_glyphs, 0,
283 	       sizeof(entries) - 2 * num_glyphs);
284 	stream_write(s, cmap_initial_0, sizeof(cmap_initial_0));
285 	for (i = 0; i <= 0xff; ++i)
286 	    sputc(s, (byte)entries[2 * i + 1]);
287     } else if (can_use_trimmed) {
288 	/* Use trimmed table format. */
289 	byte cmap_data[sizeof(cmap_initial_6)];
290 
291 	memcpy(cmap_data, cmap_initial_6, sizeof(cmap_initial_6));
292 	put_u16(cmap_data + 18,
293 		U16(cmap_data + 18) + num_entries * 2);  /* offset */
294 	put_u16(cmap_data + 22,
295 		U16(cmap_data + 22) + num_entries * 2);  /* length */
296 	put_u16(cmap_data + 26, first_code + first_entry);
297 	put_u16(cmap_data + 28, num_entries);
298 	stream_write(s, cmap_data, sizeof(cmap_data));
299 	stream_write(s, entries + first_entry * 2, num_entries * 2);
300     } else {
301 	/*
302 	 * Punt.  Acrobat Reader 3 can't handle any other Mac table format.
303 	 * (AR3 for Linux doesn't seem to be able to handle Windows format,
304 	 * either, but maybe AR3 for Windows can.)
305 	 */
306 	stream_write(s, cmap_initial_4, sizeof(cmap_initial_4));
307     }
308 
309     /* Write the Windows sub-table. */
310 
311     memcpy(cmap_sub, cmap_sub_initial, sizeof(cmap_sub_initial));
312     put_u16(cmap_sub + 2, U16(cmap_sub + 2) + num_entries * 2); /* length */
313     put_u16(cmap_sub + 14, first_code + end_entry - 1); /* endCount[0] */
314     put_u16(cmap_sub + 20, first_code + first_entry); /* startCount[0] */
315     stream_write(s, cmap_sub, sizeof(cmap_sub));
316     stream_write(s, entries + first_entry * 2, num_entries * 2);
317     put_pad(s, cmap_length);
318 }
319 private uint
320 size_cmap(gs_font *font, uint first_code, int num_glyphs, gs_glyph max_glyph,
321 	  int options)
322 {
323     stream poss;
324 
325     swrite_position_only(&poss);
326     write_cmap(&poss, font, first_code, num_glyphs, max_glyph, options, 0);
327     return stell(&poss);
328 }
329 
330 /* ------ name ------ */
331 
332 /* Write a generated name table. */
333 static const byte name_initial[] = {
334     0, 0,			/* format */
335     0, 1,			/* # of records = 1 */
336     0, 18,			/* start of string storage */
337 
338     0, 2,			/* platform ID = ISO */
339     0, 2,			/* encoding ID = ISO 8859-1 */
340     0, 0,			/* language ID (none) */
341     0, 6,			/* name ID = PostScript name */
342     0, 0,			/* length *VARIABLE* */
343     0, 0			/* start of string within string storage */
344 };
345 private uint
346 size_name(const gs_const_string *font_name)
347 {
348     return sizeof(name_initial) + font_name->size;
349 }
350 private void
351 write_name(stream *s, const gs_const_string *font_name)
352 {
353     byte name_bytes[sizeof(name_initial)];
354 
355     memcpy(name_bytes, name_initial, sizeof(name_initial));
356     put_u16(name_bytes + 14, font_name->size);
357     stream_write(s, name_bytes, sizeof(name_bytes));
358     stream_write(s, font_name->data, font_name->size);
359     put_pad(s, size_name(font_name));
360 }
361 
362 /* ------ OS/2 ------ */
363 
364 /* Write a generated OS/2 table. */
365 #define OS_2_LENGTH sizeof(ttf_OS_2_t)
366 private void
367 update_OS_2(ttf_OS_2_t *pos2, uint first_glyph, int num_glyphs)
368 {
369     put_u16(pos2->usFirstCharIndex, first_glyph);
370     put_u16(pos2->usLastCharIndex, first_glyph + num_glyphs - 1);
371 }
372 private void
373 write_OS_2(stream *s, gs_font *font, uint first_glyph, int num_glyphs)
374 {
375     ttf_OS_2_t os2;
376 
377     /*
378      * We don't bother to set most of the fields.  The really important
379      * ones, which affect character mapping, are usFirst/LastCharIndex.
380      * We also need to set usWeightClass and usWidthClass to avoid
381      * crashing ttfdump.
382      */
383     memset(&os2, 0, sizeof(os2));
384     put_u16(os2.version, 1);
385     put_u16(os2.usWeightClass, 400); /* Normal */
386     put_u16(os2.usWidthClass, 5); /* Normal */
387     update_OS_2(&os2, first_glyph, num_glyphs);
388     if (first_glyph >= 0xf000)
389 	os2.ulCodePageRanges[3] = 1; /* bit 31, symbolic */
390     stream_write(s, &os2, sizeof(os2));
391     put_pad(s, sizeof(os2));
392 }
393 
394 /* ------ post ------ */
395 
396 /* Construct and then write the post table. */
397 typedef struct post_glyph_s {
398     byte char_index;
399     byte size;
400     ushort glyph_index;
401 } post_glyph_t;
402 private int
403 compare_post_glyphs(const void *pg1, const void *pg2)
404 {
405     gs_glyph g1 = ((const post_glyph_t *)pg1)->glyph_index,
406 	g2 = ((const post_glyph_t *)pg2)->glyph_index;
407 
408     return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
409 }
410 typedef struct post_s {
411     post_glyph_t glyphs[256 + 1];
412     int count, glyph_count;
413     uint length;
414 } post_t;
415 
416 /*
417  * If necessary, compute the length of the post table.  Note that we
418  * only generate post entries for characters in the Encoding.
419  */
420 private void
421 compute_post(gs_font *font, post_t *post)
422 {
423     int i;
424 
425     for (i = 0, post->length = 32 + 2; i <= 255; ++i) {
426 	gs_const_string str;
427 	gs_glyph glyph = font->procs.encode_char(font, (gs_char)i,
428 						 GLYPH_SPACE_INDEX);
429 	int mac_index = mac_glyph_index(font, i, &str);
430 
431 	if (mac_index != 0) {
432 	    post->glyphs[post->count].char_index = i;
433 	    post->glyphs[post->count].size =
434 		(mac_index < 0 ? str.size + 1 : 0);
435 	    post->glyphs[post->count].glyph_index = glyph - gs_min_cid_glyph;
436 	    post->count++;
437 	}
438     }
439     if (post->count) {
440 	int j;
441 
442 	qsort(post->glyphs, post->count, sizeof(post->glyphs[0]),
443 	      compare_post_glyphs);
444 	/* Eliminate duplicate references to the same glyph. */
445 	for (i = j = 0; i < post->count; ++i) {
446 	    if (i == 0 ||
447 		post->glyphs[i].glyph_index !=
448 		post->glyphs[i - 1].glyph_index
449 		) {
450 		post->length += post->glyphs[i].size;
451 		post->glyphs[j++] = post->glyphs[i];
452 	    }
453 	}
454 	post->count = j;
455 	post->glyph_count = post->glyphs[post->count - 1].glyph_index + 1;
456     }
457     post->length += post->glyph_count * 2;
458 }
459 
460 /* Write the post table */
461 private void
462 write_post(stream *s, gs_font *font, post_t *post)
463 {
464     byte post_initial[32 + 2];
465     uint name_index;
466     uint glyph_index;
467     int i;
468 
469     memset(post_initial, 0, 32);
470     put_u32(post_initial, 0x00020000);
471     put_u16(post_initial + 32, post->glyph_count);
472     stream_write(s, post_initial, sizeof(post_initial));
473 
474     /* Write the name index table. */
475 
476     for (i = 0, name_index = 258, glyph_index = 0; i < post->count; ++i) {
477 	gs_const_string str;
478 	int ch = post->glyphs[i].char_index;
479 	int mac_index = mac_glyph_index(font, ch, &str);
480 
481 	for (; glyph_index < post->glyphs[i].glyph_index; ++glyph_index)
482 	    put_ushort(s, 0);
483 	glyph_index++;
484 	if (mac_index >= 0)
485 	    put_ushort(s, mac_index);
486 	else {
487 	    put_ushort(s, name_index);
488 	    name_index++;
489 	}
490     }
491 
492     /* Write the string names of the glyphs. */
493 
494     for (i = 0; i < post->count; ++i) {
495 	gs_const_string str;
496 	int ch = post->glyphs[i].char_index;
497 	int mac_index = mac_glyph_index(font, ch, &str);
498 
499 	if (mac_index < 0) {
500 	    spputc(s, str.size);
501 	    stream_write(s, str.data, str.size);
502 	}
503     }
504     put_pad(s, post->length);
505 }
506 
507 /* ---------------- Main program ---------------- */
508 
509 /* Write the definition of a TrueType font. */
510 private int
511 compare_table_tags(const void *pt1, const void *pt2)
512 {
513     ulong t1 = u32(pt1), t2 = u32(pt2);
514 
515     return (t1 < t2 ? -1 : t1 > t2 ? 1 : 0);
516 }
517 private int
518 psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
519 			psf_glyph_enum_t *penum, bool is_subset,
520 			const gs_const_string *alt_font_name)
521 {
522     gs_font *const font = (gs_font *)pfont;
523     gs_const_string font_name;
524     int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
525 	pfont->data.string_proc;
526     const byte *OffsetTable;
527     uint numTables_stored, numTables, numTables_out;
528 #define MAX_NUM_TABLES 40
529     byte tables[MAX_NUM_TABLES * 16];
530     uint i;
531     ulong offset;
532     gs_glyph glyph, glyph_prev;
533     ulong max_glyph;
534     uint glyf_length, glyf_checksum = 0 /****** NO CHECKSUM ******/;
535     uint loca_length, loca_checksum[2];
536     uint numGlyphs;		/* original value from maxp */
537     byte head[56];		/* 0 mod 4 */
538     post_t post;
539     ulong head_checksum, file_checksum = 0;
540     int indexToLocFormat;
541     bool
542 	writing_cid = (options & WRITE_TRUETYPE_CID) != 0,
543 	have_cmap = writing_cid,
544 	have_name = !(options & WRITE_TRUETYPE_NAME),
545 	have_OS_2 = writing_cid,
546 	have_post = writing_cid;
547     uint cmap_length;
548     ulong OS_2_start;
549     uint OS_2_length = OS_2_LENGTH;
550     int code;
551 
552     if (alt_font_name)
553 	font_name = *alt_font_name;
554     else
555 	font_name.data = font->font_name.chars,
556 	    font_name.size = font->font_name.size;
557 
558     /*
559      * Count the number of tables, including the eventual glyf and loca
560      * (which may not actually be present in the font), and copy the
561      * table directory.
562      */
563 
564     ACCESS(0, 12, OffsetTable);
565     numTables_stored = U16(OffsetTable + 4);
566     for (i = numTables = 0; i < numTables_stored; ++i) {
567 	const byte *tab;
568 	const byte *data;
569 	ulong start;
570 	uint length;
571 
572 	if (numTables == MAX_NUM_TABLES)
573 	    return_error(gs_error_limitcheck);
574 	ACCESS(12 + i * 16, 16, tab);
575 	start = u32(tab + 8);
576 	length = u32(tab + 12);
577 	/* Copy the table data now, since another ACCESS may invalidate it. */
578 	memcpy(&tables[numTables * 16], tab, 16);
579 
580 #define W(a,b,c,d)\
581   ( ((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
582 
583 	switch (W(tab[0], tab[1], tab[2], tab[3])) {
584 	case W('h','e','a','d'):
585 	    if (length != 54)
586 		return_error(gs_error_invalidfont);
587 	    ACCESS(start, length, data);
588 	    memcpy(head, data, length);
589 	    continue;
590 	case W('g','l','y','f'): /* synthesized */
591 	case W('g','l','y','x'): /* Adobe bogus */
592 	case W('l','o','c','a'): /* synthesized */
593 	case W('l','o','c','x'): /* Adobe bogus */
594 	case W('g','d','i','r'): /* Adobe marker */
595 	    continue;
596 	case W('c','m','a','p'):
597 	    if (options & (WRITE_TRUETYPE_CMAP | WRITE_TRUETYPE_CID))
598 		continue;
599 	    have_cmap = true;
600 	    break;
601 	case W('m','a','x','p'):
602 	    ACCESS(start, length, data);
603 	    numGlyphs = U16(data + 4);
604 	    break;
605 	case W('n','a','m','e'):
606 	    if (writing_cid)
607 		continue;
608 	    have_name = true;
609 	    break;
610 	case W('O','S','/','2'):
611 	    if (writing_cid)
612 		continue;
613 	    have_OS_2 = true;
614 	    if (length > OS_2_LENGTH)
615 		return_error(gs_error_invalidfont);
616 	    OS_2_start = start;
617 	    OS_2_length = length;
618 	    continue;
619 	case W('p','o','s','t'):
620 	    have_post = true;
621 	    break;
622 	case W('h','h','e','a'):
623 	case W('c','v','t',' '):
624 	case W('p','r','e','p'):
625 	case W('h','m','t','x'):
626 	case W('f','p','g','m'):
627 	case W('g','a','s','p'):
628 	case W('k','e','r','n'):
629 	case W('v','h','e','a'):
630 	case W('v','m','t','x'):
631 	    break;		/* always copy these if present */
632 	default:
633 	    if (writing_cid)
634 		continue;
635 	    break;
636 	}
637 #undef W
638 	numTables++;
639     }
640 
641     /*
642      * Enumerate the glyphs to get the size of glyf and loca,
643      * and to compute the checksums for these tables.
644      */
645 
646     /****** NO CHECKSUMS YET ******/
647     for (max_glyph = 0, glyf_length = 0;
648 	 (code = psf_enumerate_glyphs_next(penum, &glyph)) != 1;
649 	 ) {
650 	uint glyph_index;
651 	gs_const_string glyph_string;
652 
653 	if (glyph < gs_min_cid_glyph)
654 	    return_error(gs_error_invalidfont);
655 	glyph_index = glyph - gs_min_cid_glyph;
656 	if_debug1('L', "[L]glyph_index %u\n", glyph_index);
657 	if ((code = pfont->data.get_outline(pfont, glyph_index, &glyph_string)) >= 0) {
658 	    max_glyph = max(max_glyph, glyph_index);
659 	    glyf_length += glyph_string.size;
660 	    if_debug1('L', "[L]  size %u\n", glyph_string.size);
661 	    if (code > 0)
662 		gs_free_const_string(pfont->memory, glyph_string.data,
663 				     glyph_string.size,
664 				     "psf_write_truetype_data");
665 	}
666     }
667     /* Acrobat Reader won't accept fonts with empty glyfs. */
668     if (glyf_length == 0)
669 	glyf_length = 1;
670     if_debug2('l', "[l]max_glyph = %lu, glyf_length = %lu\n",
671 	      (ulong)max_glyph, (ulong)glyf_length);
672     /*
673      * For subset fonts, we should trim the loca table so that it only
674      * contains entries through max_glyph.  Unfortunately, this would
675      * require changing numGlyphs in maxp, which in turn would affect hdmx,
676      * hhea, hmtx, vdmx, vhea, vmtx, and possibly other tables.  This is way
677      * more work than we want to do right now.
678      */
679     /*loca_length = (max_glyph + 2) << 2;*/
680     loca_length = (numGlyphs + 1) << 2;
681     indexToLocFormat = (glyf_length > 0x1fffc);
682     if (!indexToLocFormat)
683 	loca_length >>= 1;
684 
685     /*
686      * If necessary, compute the length of the post table.  Note that we
687      * only generate post entries for characters in the Encoding.  */
688 
689     if (!have_post) {
690 	memset(&post, 0, sizeof(post));
691 	if (options & WRITE_TRUETYPE_POST)
692 	    compute_post(font, &post);
693 	else
694 	    post.length = 32;	/* dummy table */
695     }
696 
697     /* Fix up the head table. */
698 
699     memset(head + 8, 0, 4);
700     head[51] = (byte)indexToLocFormat;
701     memset(head + 54, 0, 2);
702     for (head_checksum = 0, i = 0; i < 56; i += 4)
703 	head_checksum += u32(&head[i]);
704 
705     /*
706      * Construct the table directory, except for glyf, loca, head, OS/2,
707      * and, if necessary, generated cmap, name, and post tables.
708      * Note that the existing directory is already sorted by tag.
709      */
710 
711     numTables_out = numTables + 3 /* head, glyf, loca */
712 	+ !writing_cid		/* OS/2 */
713 	+ !have_cmap + !have_name + !have_post;
714     if (numTables_out >= MAX_NUM_TABLES)
715 	return_error(gs_error_limitcheck);
716     offset = 12 + numTables_out * 16;
717     for (i = 0; i < numTables; ++i) {
718 	byte *tab = &tables[i * 16];
719 	ulong length = u32(tab + 12);
720 
721 	offset += round_up(length, 4);
722     }
723 
724     /* Make the table directory entries for generated tables. */
725 
726     {
727 	byte *tab = &tables[numTables * 16];
728 
729 	offset = put_table(tab, "glyf", glyf_checksum, offset, glyf_length);
730 	tab += 16;
731 
732 	offset = put_table(tab, "loca", loca_checksum[indexToLocFormat],
733 			   offset, loca_length);
734 	tab += 16;
735 
736 	if (!have_cmap) {
737 	    cmap_length = size_cmap(font, 0xf000, 256,
738 				    gs_min_cid_glyph + max_glyph, options);
739 	    offset = put_table(tab, "cmap", 0L /****** NO CHECKSUM ******/,
740 			       offset, cmap_length);
741 	    tab += 16;
742 	}
743 
744 	if (!have_name) {
745 	    offset = put_table(tab, "name", 0L /****** NO CHECKSUM ******/,
746 			       offset, size_name(&font_name));
747 	    tab += 16;
748 	}
749 
750 	if (!writing_cid) {
751 	    offset = put_table(tab, "OS/2", 0L /****** NO CHECKSUM ******/,
752 			       offset, OS_2_length);
753 	    tab += 16;
754 	}
755 
756 	if (!have_post) {
757 	    offset = put_table(tab, "post", 0L /****** NO CHECKSUM ******/,
758 			       offset, post.length);
759 	    tab += 16;
760 	}
761 
762 	/*
763 	 * Note that the 'head' table must have length 54, even though
764 	 * it occupies 56 bytes on the file.
765 	 */
766 	offset = put_table(tab, "head", head_checksum, offset, 54);
767 	tab += 16;
768     }
769     numTables = numTables_out;
770 
771     /* Write the font header. */
772 
773     {
774 	static const byte version[4] = {0, 1, 0, 0};
775 
776 	stream_write(s, version, 4);
777     }
778     put_ushort(s, numTables);
779     for (i = 0; 1 << i <= numTables; ++i)
780 	DO_NOTHING;
781     --i;
782     put_ushort(s, 16 << i);	/* searchRange */
783     put_ushort(s, i);		/* entrySelectors */
784     put_ushort(s, numTables * 16 - (16 << i)); /* rangeShift */
785 
786     /* Write the table directory. */
787 
788     qsort(tables, numTables, 16, compare_table_tags);
789     offset = 12 + numTables * 16;
790     for (i = 0; i < numTables; ++i) {
791 	const byte *tab = &tables[i * 16];
792 	byte entry[16];
793 
794 	memcpy(entry, tab, 16);
795 	if (entry[8] < 0x40) {
796 	    /* Not a generated table. */
797 	    uint length = u32(tab + 12);
798 
799 	    put_u32(entry + 8, offset);
800 	    offset += round_up(length, 4);
801 	} else {
802 	    entry[8] -= 0x40;
803 	}
804 	stream_write(s, entry, 16);
805     }
806 
807     /* Write tables other than the ones we generate here. */
808 
809     for (i = 0; i < numTables; ++i) {
810 	const byte *tab = &tables[i * 16];
811 
812 	if (tab[8] < 0x40) {
813 	    ulong start = u32(tab + 8);
814 	    uint length = u32(tab + 12);
815 
816 	    write_range(s, pfont, start, length);
817 	    put_pad(s, length);
818 	}
819     }
820 
821     /* Write glyf. */
822 
823     if (is_subset)
824 	psf_enumerate_glyphs_reset(penum);
825     else
826 	psf_enumerate_glyphs_begin(penum, font, NULL, max_glyph + 1,
827 				   GLYPH_SPACE_INDEX);
828     for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
829 	gs_const_string glyph_string;
830 
831 	if ((code = pfont->data.get_outline(pfont, glyph - gs_min_cid_glyph,
832 					    &glyph_string)) >= 0
833 	    ) {
834 	    stream_write(s, glyph_string.data, glyph_string.size);
835 	    offset += glyph_string.size;
836 	    if_debug2('L', "[L]glyf index = %u, size = %u\n",
837 		      i, glyph_string.size);
838 	    if (code > 0)
839 		gs_free_const_string(pfont->memory, glyph_string.data,
840 				     glyph_string.size,
841 				     "psf_write_truetype_data");
842 	}
843     }
844     if_debug1('l', "[l]glyf final offset = %lu\n", offset);
845     /* Add a dummy byte if necessary to make glyf non-empty. */
846     while (offset < glyf_length)
847 	stream_putc(s, 0), ++offset;
848     put_pad(s, (uint)offset);
849 
850     /* Write loca. */
851 
852     psf_enumerate_glyphs_reset(penum);
853     glyph_prev = gs_min_cid_glyph;
854     for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
855 	gs_const_string glyph_string;
856 
857 	for (; glyph_prev <= glyph; ++glyph_prev)
858 	    put_loca(s, offset, indexToLocFormat);
859 	if ((code = pfont->data.get_outline(pfont, glyph - gs_min_cid_glyph,
860 				    &glyph_string)) >= 0
861 	    ) {
862 	    offset += glyph_string.size;
863 	    if (code > 0)
864 		gs_free_const_string(pfont->memory, glyph_string.data,
865 				     glyph_string.size,
866 				     "psf_write_truetype_data");
867 	}
868 
869     }
870     /* Pad to numGlyphs + 1 entries (including the trailing entry). */
871     for (; glyph_prev <= gs_min_cid_glyph + numGlyphs; ++glyph_prev)
872 	put_loca(s, offset, indexToLocFormat);
873     put_pad(s, loca_length);
874 
875     /* If necessary, write cmap, name, and OS/2. */
876 
877     if (!have_cmap)
878 	write_cmap(s, font, 0xf000, 256, gs_min_cid_glyph + max_glyph,
879 		   options, cmap_length);
880     if (!have_name)
881 	write_name(s, &font_name);
882     if (!have_OS_2)
883 	write_OS_2(s, font, 0xf000, 256);
884     else if (!have_cmap) {
885 	/*
886 	 * Adjust the first and last character indices in the OS/2 table
887 	 * to reflect the values in the generated cmap.
888 	 */
889 	const byte *pos2;
890 	ttf_OS_2_t os2;
891 
892 	ACCESS(OS_2_start, OS_2_length, pos2);
893 	memcpy(&os2, pos2, min(OS_2_length, sizeof(os2)));
894 	update_OS_2(&os2, 0xf000, 256);
895 	stream_write(s, &os2, OS_2_length);
896 	put_pad(s, OS_2_length);
897     } else if (!writing_cid) {
898 	/* Just copy the existing OS/2 table. */
899 	write_range(s, pfont, OS_2_start, OS_2_length);
900 	put_pad(s, OS_2_length);
901     }
902 
903     /* If necessary, write post. */
904 
905     if (!have_post) {
906 	if (options & WRITE_TRUETYPE_POST)
907 	    write_post(s, font, &post);
908 	else {
909 	    byte post_initial[32 + 2];
910 
911 	    memset(post_initial, 0, 32);
912 	    put_u32(post_initial, 0x00030000);
913 	    stream_write(s, post_initial, 32);
914 	}
915     }
916 
917     /* Write head. */
918 
919     /****** CHECKSUM WAS NEVER COMPUTED ******/
920     /*
921      * The following nonsense is to avoid warnings about the constant
922      * 0xb1b0afbaL being "unsigned in ANSI C, signed with -traditional".
923      */
924 #if ARCH_SIZEOF_LONG > ARCH_SIZEOF_INT
925 #  define HEAD_MAGIC 0xb1b0afbaL
926 #else
927 #  define HEAD_MAGIC ((ulong)~0x4e4f5045)
928 #endif
929     put_u32(head + 8, HEAD_MAGIC - file_checksum); /* per spec */
930 #undef HEAD_MAGIC
931     stream_write(s, head, 56);
932 
933     return 0;
934 }
935 
936 /* Write a TrueType font. */
937 int
938 psf_write_truetype_font(stream *s, gs_font_type42 *pfont, int options,
939 			gs_glyph *orig_subset_glyphs, uint orig_subset_size,
940 			const gs_const_string *alt_font_name)
941 {
942     gs_font *const font = (gs_font *)pfont;
943     psf_glyph_enum_t genum;
944     gs_glyph subset_data[256 * MAX_COMPOSITE_PIECES];
945     gs_glyph *subset_glyphs = orig_subset_glyphs;
946     uint subset_size = orig_subset_size;
947 
948     /* Sort the subset glyphs, if any. */
949 
950     if (subset_glyphs) {
951 	/* Add the component glyphs for composites. */
952 	int code;
953 
954 	memcpy(subset_data, orig_subset_glyphs,
955 	       sizeof(gs_glyph) * subset_size);
956 	subset_glyphs = subset_data;
957 	code = psf_add_subset_pieces(subset_glyphs, &subset_size,
958 				     countof(subset_data),
959 				     countof(subset_data),
960 				     font);
961 	if (code < 0)
962 	    return code;
963 	subset_size = psf_sort_glyphs(subset_glyphs, subset_size);
964     }
965     psf_enumerate_glyphs_begin(&genum, font, subset_glyphs,
966 			       (subset_glyphs ? subset_size : 0),
967 			       GLYPH_SPACE_INDEX);
968     return psf_write_truetype_data(s, pfont, options & ~WRITE_TRUETYPE_CID,
969 				   &genum, subset_glyphs != 0, alt_font_name);
970 }
971 
972 /* Write a CIDFontType 2 font. */
973 int
974 psf_write_cid2_font(stream *s, gs_font_cid2 *pfont, int options,
975 		    const byte *subset_bits, uint subset_size,
976 		    const gs_const_string *alt_font_name)
977 {
978     gs_font *const font = (gs_font *)pfont;
979     psf_glyph_enum_t genum;
980 
981     psf_enumerate_bits_begin(&genum, font, subset_bits,
982 			     (subset_bits ? subset_size : 0),
983 			     GLYPH_SPACE_INDEX);
984     return psf_write_truetype_data(s, (gs_font_type42 *)font,
985 				   WRITE_TRUETYPE_CID, &genum,
986 				   subset_bits != 0, alt_font_name);
987 }
988