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