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