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