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