1% writettf.w 2% 3% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> 4% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> 5% 6% This file is part of LuaTeX. 7% 8% LuaTeX is free software; you can redistribute it and/or modify it under 9% the terms of the GNU General Public License as published by the Free 10% Software Foundation; either version 2 of the License, or (at your 11% option) any later version. 12% 13% LuaTeX is distributed in the hope that it will be useful, but WITHOUT 14% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16% License for more details. 17% 18% You should have received a copy of the GNU General Public License along 19% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. 20 21@ @c 22 23 24#include "ptexlib.h" 25#include "font/writettf.h" 26#include <string.h> 27 28#define DEFAULT_NTABS 14 29#define NEW_CMAP_SIZE 2 30 31#define ttf_putchar(A) strbuf_putchar(pdf->fb, (A)) 32#define ttf_offset() strbuf_offset(pdf->fb) 33#define ttf_seek_outbuf(A) strbuf_seek(pdf->fb, (A)) 34 35unsigned char *ttf_buffer = NULL; 36int ttf_size = 0; 37int ttf_curbyte = 0; 38 39typedef struct { 40 char *name; /* name of glyph */ 41 long code; /* charcode in case of subfonts */ 42 long newindex; /* new index of glyph in output file */ 43 44} ttfenc_entry; 45 46typedef struct { 47 TTF_USHORT platform_id; 48 TTF_USHORT encoding_id; 49 TTF_USHORT language_id; 50 TTF_USHORT name_id; 51 TTF_USHORT length; 52 TTF_USHORT offset; 53 TTF_USHORT new_offset; 54 TTF_USHORT new_length; 55} name_record; 56 57typedef struct { 58 char *ttf_name; 59 TTF_USHORT pid; 60 TTF_USHORT eid; 61 long *table; 62} ttf_cmap_entry; 63 64static TTF_USHORT ntabs; 65static TTF_USHORT upem; 66static TTF_FIXED post_format; 67static TTF_SHORT loca_format; 68static TTF_ULONG last_glyf_offset; 69static TTF_USHORT glyphs_count; 70static TTF_USHORT new_glyphs_count; 71static TTF_USHORT nhmtxs; 72static TTF_USHORT new_ntabs; 73 74glyph_entry *glyph_tab; 75dirtab_entry *dir_tab; 76 77static long *glyph_index; 78static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE]; 79static name_record *name_tab; 80static int name_record_num; 81static char *name_buf; 82static int name_buf_size; 83static char *glyph_name_buf; 84static TTF_ULONG checksum; 85static TTF_ULONG tab_length; 86static TTF_ULONG tmp_ulong; 87static TTF_ULONG checkSumAdjustment_offset; 88FILE *ttf_file; 89static ttfenc_entry ttfenc_tab[256]; 90 91fd_entry *fd_cur; /* pointer to the current font descriptor */ 92 93static struct avl_table *ttf_cmap_tree = NULL; 94 95int ttf_length; 96 97@ This used to be macnames.c 98 99@c 100char notdef[] = ".notdef"; 101 102const char *mac_glyph_names[] = { 103/* 0x00 */ 104 notdef, 105 ".null", 106 "CR", 107 "space", 108 "exclam", 109 "quotedbl", 110 "numbersign", 111 "dollar", 112 "percent", 113 "ampersand", 114 "quotesingle", 115 "parenleft", 116 "parenright", 117 "asterisk", 118 "plus", 119 "comma", 120/* 0x10 */ 121 "hyphen", 122 "period", 123 "slash", 124 "zero", 125 "one", 126 "two", 127 "three", 128 "four", 129 "five", 130 "six", 131 "seven", 132 "eight", 133 "nine", 134 "colon", 135 "semicolon", 136 "less", 137/* 0x20 */ 138 "equal", 139 "greater", 140 "question", 141 "at", 142 "A", 143 "B", 144 "C", 145 "D", 146 "E", 147 "F", 148 "G", 149 "H", 150 "I", 151 "J", 152 "K", 153 "L", 154/* 0x30 */ 155 "M", 156 "N", 157 "O", 158 "P", 159 "Q", 160 "R", 161 "S", 162 "T", 163 "U", 164 "V", 165 "W", 166 "X", 167 "Y", 168 "Z", 169 "bracketleft", 170 "backslash", 171/* 0x40 */ 172 "bracketright", 173 "asciicircum", 174 "underscore", 175 "grave", 176 "a", 177 "b", 178 "c", 179 "d", 180 "e", 181 "f", 182 "g", 183 "h", 184 "i", 185 "j", 186 "k", 187 "l", 188/* 0x50 */ 189 "m", 190 "n", 191 "o", 192 "p", 193 "q", 194 "r", 195 "s", 196 "t", 197 "u", 198 "v", 199 "w", 200 "x", 201 "y", 202 "z", 203 "braceleft", 204 "bar", 205/* 0x60 */ 206 "braceright", 207 "asciitilde", 208 "Adieresis", 209 "Aring", 210 "Ccedilla", 211 "Eacute", 212 "Ntilde", 213 "Odieresis", 214 "Udieresis", 215 "aacute", 216 "agrave", 217 "acircumflex", 218 "adieresis", 219 "atilde", 220 "aring", 221 "ccedilla", 222/* 0x70 */ 223 "eacute", 224 "egrave", 225 "ecircumflex", 226 "edieresis", 227 "iacute", 228 "igrave", 229 "icircumflex", 230 "idieresis", 231 "ntilde", 232 "oacute", 233 "ograve", 234 "ocircumflex", 235 "odieresis", 236 "otilde", 237 "uacute", 238 "ugrave", 239/* 0x80 */ 240 "ucircumflex", 241 "udieresis", 242 "dagger", 243 "degree", 244 "cent", 245 "sterling", 246 "section", 247 "bullet", 248 "paragraph", 249 "germandbls", 250 "registered", 251 "copyright", 252 "trademark", 253 "acute", 254 "dieresis", 255 "notequal", 256/* 0x90 */ 257 "AE", 258 "Oslash", 259 "infinity", 260 "plusminus", 261 "lessequal", 262 "greaterequal", 263 "yen", 264 "mu", 265 "partialdiff", 266 "Sigma", 267 "Pi", 268 "pi", 269 "integral", 270 "ordfeminine", 271 "ordmasculine", 272 "Omega", 273/* 0xa0 */ 274 "ae", 275 "oslash", 276 "questiondown", 277 "exclamdown", 278 "logicalnot", 279 "radical", 280 "florin", 281 "approxequal", 282 "Delta", 283 "guillemotleft", 284 "guillemotright", 285 "ellipsis", 286 "nbspace", 287 "Agrave", 288 "Atilde", 289 "Otilde", 290/* 0xb0 */ 291 "OE", 292 "oe", 293 "endash", 294 "emdash", 295 "quotedblleft", 296 "quotedblright", 297 "quoteleft", 298 "quoteright", 299 "divide", 300 "lozenge", 301 "ydieresis", 302 "Ydieresis", 303 "fraction", 304 "currency", 305 "guilsinglleft", 306 "guilsinglright", 307/* 0xc0 */ 308 "fi", 309 "fl", 310 "daggerdbl", 311 "periodcentered", 312 "quotesinglbase", 313 "quotedblbase", 314 "perthousand", 315 "Acircumflex", 316 "Ecircumflex", 317 "Aacute", 318 "Edieresis", 319 "Egrave", 320 "Iacute", 321 "Icircumflex", 322 "Idieresis", 323 "Igrave", 324/* 0xd0 */ 325 "Oacute", 326 "Ocircumflex", 327 "applelogo", 328 "Ograve", 329 "Uacute", 330 "Ucircumflex", 331 "Ugrave", 332 "dotlessi", 333 "circumflex", 334 "tilde", 335 "macron", 336 "breve", 337 "dotaccent", 338 "ring", 339 "cedilla", 340 "hungarumlaut", 341/* 0xe0 */ 342 "ogonek", 343 "caron", 344 "Lslash", 345 "lslash", 346 "Scaron", 347 "scaron", 348 "Zcaron", 349 "zcaron", 350 "brokenbar", 351 "Eth", 352 "eth", 353 "Yacute", 354 "yacute", 355 "Thorn", 356 "thorn", 357 "minus", 358/* 0xf0 */ 359 "multiply", 360 "onesuperior", 361 "twosuperior", 362 "threesuperior", 363 "onehalf", 364 "onequarter", 365 "threequarters", 366 "franc", 367 "Gbreve", 368 "gbreve", 369 "Idot", 370 "Scedilla", 371 "scedilla", 372 "Cacute", 373 "cacute", 374 "Ccaron", 375/* 0x100 */ 376 "ccaron", 377 "dmacron" 378}; 379 380const char *ambiguous_names[] = { 381 "Delta", /* increment */ 382 "Omega", /* Ohm */ 383 "Pi", /* product */ 384 "Sigma", /* summation */ 385 "dmacron", /* dslash */ 386 "macron", /* overscore */ 387 "periodcentered", /* middot */ 388 NULL 389}; 390 391static const char *newtabnames[] = { 392 "OS/2", 393 "PCLT", 394 "cmap", 395 "cvt ", 396 "fpgm", 397 "glyf", 398 "head", 399 "hhea", 400 "hmtx", 401 "loca", 402 "maxp", 403 "name", 404 "post", 405 "prep" 406}; 407 408@ Back to code. Low-level helpers first. 409 410@c 411static ttf_cmap_entry *new_ttf_cmap_entry(void) 412{ 413 ttf_cmap_entry *e; 414 e = xtalloc(1, ttf_cmap_entry); 415 e->ttf_name = NULL; 416 e->table = NULL; 417 return e; 418} 419 420static void destroy_ttf_cmap_entry(void *pa, void *pb) 421{ 422 ttf_cmap_entry *p; 423 (void) pb; 424 p = (ttf_cmap_entry *) pa; 425 xfree(p->ttf_name); 426 xfree(p->table); 427 xfree(p); 428} 429 430void ttf_free(void) 431{ 432 if (ttf_cmap_tree != NULL) 433 avl_destroy(ttf_cmap_tree, destroy_ttf_cmap_entry); 434} 435 436static int comp_ttf_cmap_entry(const void *pa, const void *pb, void *p) 437{ 438 const ttf_cmap_entry *p1 = (const ttf_cmap_entry *) pa, 439 *p2 = (const ttf_cmap_entry *) pb; 440 int i; 441 (void) p; 442 assert(p1->ttf_name != NULL && p2->ttf_name != NULL); 443 if ((i = strcmp(p1->ttf_name, p2->ttf_name)) != 0) 444 return i; 445 cmp_return(p1->pid, p2->pid); 446 cmp_return(p1->eid, p2->eid); 447 return 0; 448} 449 450static unsigned char ttf_addchksm(unsigned char b) 451{ 452 tmp_ulong = (tmp_ulong << 8) + b; 453 tab_length++; 454 if (tab_length % 4 == 0) { 455 checksum += tmp_ulong; 456 tmp_ulong = 0; 457 } 458 return b; 459} 460 461static TTF_ULONG ttf_getchksm(PDF pdf) 462{ 463 while (tab_length % 4 != 0) 464 ttf_putchar(ttf_addchksm(0)); /* |ttf_addchksm| updates |tab_length| */ 465 return checksum; 466} 467 468long ttf_putnum(PDF pdf, int s, long n) 469{ 470 long i = n; 471 char buf[TTF_LONG_SIZE + 1], *p = buf; 472 while (s-- > 0) { 473 *p++ = (char) (i & 0xFF); 474 i >>= 8; 475 } 476 p--; 477 while (p >= buf) 478 ttf_putchar(ttf_addchksm((unsigned char) (*p--))); 479 return n; 480} 481 482long ttf_getnum(int s) 483{ 484 long i = 0; 485 int c; 486 while (s > 0) { 487 if (ttf_eof()) 488 luatex_fail("unexpected EOF"); 489 c = ttf_getchar(); 490 i = (i << 8) + c; 491 s--; 492 } 493 return i; 494} 495 496static long ttf_funit(long n) 497{ 498 if (n < 0) 499 return -((-n / upem) * 1000 + ((-n % upem) * 1000) / upem); 500 else 501 return (n / upem) * 1000 + ((n % upem) * 1000) / upem; 502} 503 504static void ttf_ncopy(PDF pdf, int n) 505{ 506 while (n-- > 0) 507 copy_byte(); 508} 509 510dirtab_entry *ttf_name_lookup(const char *s, boolean required) 511{ 512 dirtab_entry *tab; 513 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) 514 if (strncmp(tab->tag, s, 4) == 0) 515 break; 516 if (tab - dir_tab == ntabs) { 517 if (required) 518 luatex_fail("can't find table `%s'", s); 519 else 520 tab = NULL; 521 } 522 return tab; 523} 524 525dirtab_entry *ttf_seek_tab(const char *name, TTF_LONG offset) 526{ 527 dirtab_entry *tab = ttf_name_lookup(name, true); 528 ttf_curbyte = (int) (tab->offset + (unsigned long) offset); 529 return tab; 530} 531 532static void ttf_seek_off(TTF_LONG offset) 533{ 534 ttf_curbyte = (int) offset; 535} 536 537static void ttf_copy_encoding(void) 538{ 539 int i, *q; 540 void **aa; 541 char **glyph_names; 542 long *charcodes; 543 static char buf[SMALL_BUF_SIZE]; 544 struct avl_traverser t; 545 ttfenc_entry *e = ttfenc_tab; 546 547 assert(fd_cur->tx_tree != NULL); /* this must be set in |create_fontdictionary| */ 548 549 if (fd_cur->fe != NULL) { 550 glyph_names = fd_cur->fe->glyph_names; 551 assert(glyph_names != NULL); 552 553 for (i = 0; i < 256; i++) 554 ttfenc_tab[i].name = (char *) notdef; 555 556 /* a workaround for a bug of AcroReader 4.0 */ 557 if (strcmp(glyph_names[97], "a") == 0) { 558 q = xtalloc(1, int); 559 *q = 'a'; 560 aa = avl_probe(fd_cur->tx_tree, q); 561 assert(aa != NULL); 562 } 563 /* end of workaround */ 564 565 /* take over collected characters from \TeX, reencode them */ 566 avl_t_init(&t, fd_cur->tx_tree); 567 for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL; 568 q = (int *) avl_t_next(&t)) { 569 assert(*q >= 0 && *q < 256); 570 ttfenc_tab[*q].name = glyph_names[*q]; 571 } 572 make_subset_tag(fd_cur); 573 } else if (is_subfont(fd_cur->fm)) { 574 charcodes = fd_cur->fm->subfont->charcodes; 575 assert(charcodes != NULL); 576 577 for (i = 0; i < 256; i++) 578 ttfenc_tab[i].code = -1; 579 580 /* take over collected characters from \TeX */ 581 avl_t_init(&t, fd_cur->tx_tree); 582 for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL; 583 q = (int *) avl_t_next(&t)) { 584 assert(*q >= 0 && *q < 256); 585 e = ttfenc_tab + *q; 586 e->code = charcodes[*q]; 587 if (e->code == -1) 588 luatex_warn 589 ("character %i in subfont %s is not mapped to any charcode", 590 *q, fd_cur->fm->tfm_name); 591 else { 592 assert(e->code < 0x10000); 593 sprintf(buf, "/c%4.4X", (int) e->code); 594 aa = avl_probe(fd_cur->gl_tree, xstrdup(buf)); 595 assert(aa != NULL); 596 } 597 } 598 make_subset_tag(fd_cur); 599 } else 600 assert(0); 601} 602 603@ 604@c 605#define ttf_append_byte(B)\ 606do {\ 607 if (name_tab[i].platform_id == 3)\ 608 *q++ = 0;\ 609 *q++ = B;\ 610} while (0) 611 612static char *strip_spaces_and_delims(char *s, int l) 613{ 614 static char buf[SMALL_BUF_SIZE]; 615 char *p = buf; 616 int i; 617 618 assert(l >= 0 && l < (int) sizeof(buf)); 619 620 for (i = 0; i < l; s++, i++) { 621 if (*s == '(' || *s == ')' || *s == '<' || *s == '>' || 622 *s == '[' || *s == ']' || *s == '{' || *s == '}' || 623 *s == '/' || *s == '%' || isspace((unsigned char)*s)) 624 continue; 625 *p++ = *s; 626 } 627 *p = 0; 628 return buf; 629} 630 631static void ttf_read_name(void) 632{ 633 int i, j; 634 dirtab_entry *tab = ttf_seek_tab("name", TTF_USHORT_SIZE); 635 char *p, buf[SMALL_BUF_SIZE]; 636 name_record_num = get_ushort(); 637 name_tab = xtalloc((unsigned) name_record_num, name_record); 638 name_buf_size = (int) ((unsigned) tab->length - 639 (3 * TTF_USHORT_SIZE + 640 (TTF_ULONG) name_record_num * 6 * TTF_USHORT_SIZE)); 641 name_buf = xtalloc((unsigned) name_buf_size, char); 642 ttf_skip(TTF_USHORT_SIZE); 643 for (i = 0; i < name_record_num; i++) { 644 name_tab[i].platform_id = get_ushort(); 645 name_tab[i].encoding_id = get_ushort(); 646 name_tab[i].language_id = get_ushort(); 647 name_tab[i].name_id = get_ushort(); 648 name_tab[i].length = get_ushort(); 649 name_tab[i].offset = get_ushort(); 650 } 651 for (p = name_buf; p - name_buf < name_buf_size; p++) 652 *p = get_char(); 653 /* look for PS font name */ 654 for (i = 0; i < name_record_num; i++) { 655 if (name_tab[i].platform_id == 1 && 656 name_tab[i].encoding_id == 0 && name_tab[i].name_id == 6) { 657 xfree(fd_cur->fontname); 658 fd_cur->fontname = 659 xstrdup(strip_spaces_and_delims(name_buf + name_tab[i].offset, 660 name_tab[i].length)); 661 fd_cur->font_dim[FONTNAME_CODE].set = true; 662 break; 663 } 664 } 665 if (!fd_cur->font_dim[FONTNAME_CODE].set) { 666 for (i = 0; i < name_record_num; i++) { 667 if (name_tab[i].platform_id == 3 && 668 (name_tab[i].encoding_id == 0 || name_tab[i].encoding_id == 1) 669 && name_tab[i].name_id == 6) { 670 xfree(fd_cur->fontname); 671 assert(name_tab[i].length < sizeof(buf)); 672 for (j = 0, p = buf; j < name_tab[i].length; j += 2) 673 *p++ = name_buf[name_tab[i].offset + j + 1]; 674 *p = 0; 675 fd_cur->fontname = 676 xstrdup(strip_spaces_and_delims(buf, (int) strlen(buf))); 677 fd_cur->font_dim[FONTNAME_CODE].set = true; 678 break; 679 } 680 } 681 } 682} 683 684static void ttf_read_mapx(void) 685{ 686 glyph_entry *glyph; 687 ttf_seek_tab("maxp", TTF_FIXED_SIZE); 688 glyph_tab = 689 xtalloc((unsigned) (1 + (glyphs_count = get_ushort())), glyph_entry); 690 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) { 691 glyph->newindex = -1; 692 glyph->newoffset = 0; 693 glyph->name_index = 0; 694 glyph->name = (char *) notdef; 695 } 696 glyph_index = xtalloc((unsigned) (glyphs_count + 1), long); 697 glyph_index[0] = 0; /* index of ".notdef" glyph */ 698 glyph_index[1] = 1; /* index of ".null" glyph */ 699} 700 701void ttf_read_head(void) 702{ 703 ttf_seek_tab("head", 704 2 * TTF_FIXED_SIZE + 2 * TTF_ULONG_SIZE + TTF_USHORT_SIZE); 705 upem = get_ushort(); 706 ttf_skip(16); 707 fd_cur->font_dim[FONTBBOX1_CODE].val = (int) ttf_funit(get_fword()); 708 fd_cur->font_dim[FONTBBOX2_CODE].val = (int) ttf_funit(get_fword()); 709 fd_cur->font_dim[FONTBBOX3_CODE].val = (int) ttf_funit(get_fword()); 710 fd_cur->font_dim[FONTBBOX4_CODE].val = (int) ttf_funit(get_fword()); 711 fd_cur->font_dim[FONTBBOX1_CODE].set = true; 712 fd_cur->font_dim[FONTBBOX2_CODE].set = true; 713 fd_cur->font_dim[FONTBBOX3_CODE].set = true; 714 fd_cur->font_dim[FONTBBOX4_CODE].set = true; 715 ttf_skip(2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE); 716 loca_format = get_short(); 717} 718 719void ttf_read_hhea(void) 720{ 721 ttf_seek_tab("hhea", TTF_FIXED_SIZE); 722 fd_cur->font_dim[ASCENT_CODE].val = (int) ttf_funit(get_fword()); 723 fd_cur->font_dim[DESCENT_CODE].val = (int) ttf_funit(get_fword()); 724 fd_cur->font_dim[ASCENT_CODE].set = true; 725 fd_cur->font_dim[DESCENT_CODE].set = true; 726 ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3 * TTF_FWORD_SIZE + 727 8 * TTF_SHORT_SIZE); 728 nhmtxs = get_ushort(); 729} 730 731void ttf_read_pclt(void) 732{ 733 if (ttf_name_lookup("PCLT", false) == NULL) 734 return; 735 ttf_seek_tab("PCLT", TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE); 736 fd_cur->font_dim[XHEIGHT_CODE].val = (int) ttf_funit(get_ushort()); 737 ttf_skip(2 * TTF_USHORT_SIZE); 738 fd_cur->font_dim[CAPHEIGHT_CODE].val = (int) ttf_funit(get_ushort()); 739 fd_cur->font_dim[XHEIGHT_CODE].set = true; 740 fd_cur->font_dim[CAPHEIGHT_CODE].set = true; 741} 742 743static void ttf_read_hmtx(void) 744{ 745 glyph_entry *glyph; 746 TTF_UFWORD last_advWidth; 747 ttf_seek_tab("hmtx", 0); 748 for (glyph = glyph_tab; glyph - glyph_tab < nhmtxs; glyph++) { 749 glyph->advWidth = get_ufword(); 750 glyph->lsb = (TTF_FWORD) get_ufword(); 751 } 752 if (nhmtxs < glyphs_count) { 753 last_advWidth = glyph[-1].advWidth; 754 for (; glyph - glyph_tab < glyphs_count; glyph++) { 755 glyph->advWidth = last_advWidth; 756 glyph->lsb = (TTF_FWORD) get_ufword(); 757 } 758 } 759} 760 761void ttf_read_post(void) 762{ 763 int k, nnames; 764 long length; 765 long int_part, frac_part; 766 int sign = 1; 767 TTF_FIXED italic_angle; 768 char *p; 769 glyph_entry *glyph; 770 const dirtab_entry *tab = ttf_seek_tab("post", 0); 771 post_format = get_fixed(); 772 italic_angle = get_fixed(); 773 int_part = (long) (italic_angle >> 16); 774 if (int_part > 0x7FFF) { /* a negative number */ 775 int_part = 0x10000 - int_part; 776 sign = -1; 777 } 778 frac_part = (long) (italic_angle % 0x10000); 779 fd_cur->font_dim[ITALIC_ANGLE_CODE].val = 780 (int) (sign * ((double) int_part + (double) frac_part * 1.0 / 0x10000)); 781 fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true; 782 if (glyph_tab == NULL) 783 return; /* being called from writeotf() */ 784 ttf_skip(2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE); 785 switch (post_format) { 786 case 0x10000: 787 for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) { 788 glyph->name = (const char *) mac_glyph_names[glyph - glyph_tab]; 789 glyph->name_index = (TTF_USHORT) (glyph - glyph_tab); 790 } 791 break; 792 case 0x20000: 793 nnames = get_ushort(); /* some fonts have this value different from nglyphs */ 794 for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) 795 glyph->name_index = get_ushort(); 796 length = 797 (long) ((long) tab->length - 798 (long) ((long) ttf_curbyte - (long) tab->offset)); 799 glyph_name_buf = xtalloc((unsigned) length, char); 800 for (p = glyph_name_buf; p - glyph_name_buf < length;) { 801 for (k = get_byte(); k > 0; k--) 802 *p++ = get_char(); 803 *p++ = 0; 804 } 805 for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) { 806 if (glyph->name_index < NMACGLYPHS) 807 glyph->name = mac_glyph_names[glyph->name_index]; 808 else { 809 p = glyph_name_buf; 810 k = glyph->name_index - NMACGLYPHS; 811 for (; k > 0; k--) 812 p = strend(p) + 1; 813 glyph->name = p; 814 } 815 } 816 break; 817 default: 818 luatex_warn("unsupported format (%.8X) of `post' table, assuming 3.0", 819 (unsigned int) post_format); 820 case 0x00030000: 821 for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) { 822 glyph->name_index = (TTF_USHORT) (glyph - glyph_tab); 823 } 824 } 825} 826 827static void ttf_read_loca(void) 828{ 829 glyph_entry *glyph; 830 ttf_seek_tab("loca", 0); 831 if (loca_format != 0) 832 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++) 833 glyph->offset = (TTF_LONG) get_ulong(); 834 else 835 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++) 836 glyph->offset = get_ushort() << 1; 837} 838 839void ttf_read_tabdir(void) 840{ 841 int i; 842 dirtab_entry *tab; 843 ttf_skip(TTF_FIXED_SIZE); /* ignore the sfnt number */ 844 dir_tab = xtalloc(ntabs = get_ushort(), dirtab_entry); 845 ttf_skip(3 * TTF_USHORT_SIZE); 846 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) { 847 for (i = 0; i < 4; i++) 848 tab->tag[i] = get_char(); 849 tab->checksum = get_ulong(); 850 tab->offset = get_ulong(); 851 tab->length = get_ulong(); 852 } 853} 854 855static ttf_cmap_entry *ttf_read_cmap(char *ttf_name, int pid, int eid, 856 boolean warn) 857{ 858 seg_entry *seg_tab, *s; 859 TTF_USHORT *glyphId, format, segCount; 860 TTF_USHORT ncmapsubtabs, tmp_pid, tmp_eid; 861 TTF_ULONG cmap_offset, tmp_offset; 862 long n, i, k, length, index; 863 ttf_cmap_entry tmp_e, *p; 864 void **aa; 865 866 /* look up in |ttf_cmap_tree| first, return if found */ 867 tmp_e.ttf_name = ttf_name; 868 tmp_e.pid = (TTF_USHORT) pid; 869 tmp_e.eid = (TTF_USHORT) eid; 870 if (ttf_cmap_tree == NULL) { 871 ttf_cmap_tree = avl_create(comp_ttf_cmap_entry, NULL, &avl_xallocator); 872 assert(ttf_cmap_tree != NULL); 873 } 874 p = (ttf_cmap_entry *) avl_find(ttf_cmap_tree, &tmp_e); 875 if (p != NULL) 876 return p; 877 878 /* not found, have to read it */ 879 ttf_seek_tab("cmap", TTF_USHORT_SIZE); /* skip the table version number (=0) */ 880 ncmapsubtabs = get_ushort(); 881 cmap_offset = (TTF_ULONG) (ttf_curbyte - 2 * TTF_USHORT_SIZE); 882 cmap_tab = xtalloc(ncmapsubtabs, cmap_entry); 883 for (i = 0; i < ncmapsubtabs; ++i) { 884 tmp_pid = get_ushort(); 885 tmp_eid = get_ushort(); 886 tmp_offset = get_ulong(); 887 if (tmp_pid == pid && tmp_eid == eid) { 888 ttf_seek_off((TTF_LONG) (cmap_offset + tmp_offset)); 889 format = get_ushort(); 890 if (format == 4) 891 goto read_cmap_format_4; 892 else { 893 if (warn) 894 luatex_warn("cmap format %i unsupported", format); 895 return NULL; 896 } 897 } 898 } 899 if (warn) 900 luatex_warn("cannot find cmap subtable for (pid,eid) = (%i, %i)", 901 pid, eid); 902 return NULL; 903 read_cmap_format_4: 904 /* initialize the new entry */ 905 p = new_ttf_cmap_entry(); 906 p->ttf_name = xstrdup(ttf_name); 907 p->pid = (TTF_USHORT) pid; 908 p->eid = (TTF_USHORT) eid; 909 p->table = xtalloc(0x10000, long); 910 for (i = 0; i < 0x10000; ++i) 911 p->table[i] = -1; /* unassigned yet */ 912 913 /* read the subtable */ 914 length = get_ushort(); /* length of subtable */ 915 (void) get_ushort(); /* skip the version number */ 916 segCount = get_ushort() / 2; 917 (void) get_ushort(); /* skip searchRange */ 918 (void) get_ushort(); /* skip entrySelector */ 919 (void) get_ushort(); /* skip rangeShift */ 920 seg_tab = xtalloc(segCount, seg_entry); 921 for (s = seg_tab; s - seg_tab < segCount; s++) 922 s->endCode = get_ushort(); 923 (void) get_ushort(); /* skip reversedPad */ 924 for (s = seg_tab; s - seg_tab < segCount; s++) 925 s->startCode = get_ushort(); 926 for (s = seg_tab; s - seg_tab < segCount; s++) 927 s->idDelta = get_ushort(); 928 for (s = seg_tab; s - seg_tab < segCount; s++) 929 s->idRangeOffset = get_ushort(); 930 length -= 8 * TTF_USHORT_SIZE + 4 * segCount * TTF_USHORT_SIZE; 931 n = length / TTF_USHORT_SIZE; /* number of glyphID's */ 932 glyphId = xtalloc((unsigned) n, TTF_USHORT); 933 for (i = 0; i < n; i++) 934 glyphId[i] = get_ushort(); 935 for (s = seg_tab; s - seg_tab < segCount; s++) { 936 for (i = s->startCode; i <= s->endCode; i++) { 937 if (i == 0xFFFF) 938 break; 939 if (s->idRangeOffset != 0xFFFF) { 940 if (s->idRangeOffset == 0) 941 index = (s->idDelta + i) & 0xFFFF; 942 else { 943 k = (i - s->startCode) + s->idRangeOffset / 2 + 944 (s - seg_tab) - segCount; 945 assert(k >= 0 && k < n); 946 index = glyphId[k]; 947 if (index != 0) 948 index = (index + s->idDelta) & 0xFFFF; 949 } 950 if (index >= glyphs_count) 951 luatex_fail("cmap: glyph index %li out of range [0..%i)", 952 index, glyphs_count); 953 if (p->table[i] != -1) 954 luatex_warn 955 ("cmap: multiple glyphs are mapped to unicode %.4lX, " 956 "only %li will be used (glyph %li being ignored)", i, 957 p->table[i], index); 958 else 959 p->table[i] = index; 960 } 961 } 962 } 963 xfree(seg_tab); 964 xfree(glyphId); 965 aa = avl_probe(ttf_cmap_tree, p); 966 assert(aa != NULL); 967 return p; 968} 969 970@ 971@c 972static void ttf_read_font(void) 973{ 974 ttf_read_tabdir(); 975 if (ttf_name_lookup("PCLT", false) == NULL) 976 new_ntabs--; 977 if (ttf_name_lookup("fpgm", false) == NULL) 978 new_ntabs--; 979 if (ttf_name_lookup("cvt ", false) == NULL) 980 new_ntabs--; 981 if (ttf_name_lookup("prep", false) == NULL) 982 new_ntabs--; 983 ttf_read_mapx(); 984 ttf_read_head(); 985 ttf_read_hhea(); 986 ttf_read_pclt(); 987 ttf_read_hmtx(); 988 ttf_read_post(); 989 ttf_read_loca(); 990 ttf_read_name(); 991} 992 993static void ttf_reset_chksm(PDF pdf, dirtab_entry * tab) 994{ 995 checksum = 0; 996 tab_length = 0; 997 tmp_ulong = 0; 998 tab->offset = (TTF_ULONG) ttf_offset(); 999 if (tab->offset % 4 != 0) 1000 luatex_warn("offset of `%4.4s' is not a multiple of 4", tab->tag); 1001} 1002 1003 1004static void ttf_set_chksm(PDF pdf, dirtab_entry * tab) 1005{ 1006 tab->length = (TTF_ULONG) ttf_offset() - tab->offset; 1007 tab->checksum = ttf_getchksm(pdf); 1008} 1009 1010static void ttf_copytab(PDF pdf, const char *name) 1011{ 1012 long i; 1013 dirtab_entry *tab = ttf_seek_tab(name, 0); 1014 ttf_reset_chksm(pdf, tab); 1015 for (i = (long) tab->length; i > 0; i--) 1016 copy_char(); 1017 ttf_set_chksm(pdf, tab); 1018} 1019 1020@ 1021@c 1022#define BYTE_ENCODING_LENGTH \ 1023 ((256)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE) 1024 1025static void ttf_byte_encoding(PDF pdf) 1026{ 1027 ttfenc_entry *e; 1028 (void) put_ushort(0); /* format number (0: byte encoding table) */ 1029 (void) put_ushort(BYTE_ENCODING_LENGTH); /* length of table */ 1030 (void) put_ushort(0); /* version number */ 1031 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) 1032 if (e->newindex < 256) { 1033 put_byte(e->newindex); 1034 } else { 1035 if (e->name != notdef) 1036 luatex_warn 1037 ("glyph `%s' has been mapped to `%s' in `ttf_byte_encoding' cmap table", 1038 e->name, notdef); 1039 put_byte(0); /* notdef */ 1040 } 1041} 1042 1043@ 1044@c 1045#define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (256))) 1046 1047static void ttf_trimmed_table_map(PDF pdf) 1048{ 1049 ttfenc_entry *e; 1050 (void) put_ushort(6); /* format number (6): trimmed table mapping */ 1051 (void) put_ushort(TRIMMED_TABLE_MAP_LENGTH); 1052 (void) put_ushort(0); /* version number (0) */ 1053 (void) put_ushort(0); /* first character code */ 1054 (void) put_ushort(256); /* number of character code in table */ 1055 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) 1056 (void) put_ushort(e->newindex); 1057} 1058 1059@ 1060@c 1061#define SEG_MAP_DELTA_LENGTH ((16 + (256))*TTF_USHORT_SIZE) 1062 1063static void ttf_seg_map_delta(PDF pdf) 1064{ 1065 ttfenc_entry *e; 1066 (void) put_ushort(4); /* format number (4: segment mapping to delta values) */ 1067 (void) put_ushort(SEG_MAP_DELTA_LENGTH); 1068 (void) put_ushort(0); /* version number */ 1069 (void) put_ushort(4); /* 2*segCount */ 1070 (void) put_ushort(4); /* searchRange */ 1071 (void) put_ushort(1); /* entrySelector */ 1072 (void) put_ushort(0); /* rangeShift */ 1073 (void) put_ushort(0xF0FF); /* endCount[0] */ 1074 (void) put_ushort(0xFFFF); /* endCount[1] */ 1075 (void) put_ushort(0); /* reversedPad */ 1076 (void) put_ushort(0xF000); /* startCount[0] */ 1077 (void) put_ushort(0xFFFF); /* startCount[1] */ 1078 (void) put_ushort(0); /* idDelta[0] */ 1079 (void) put_ushort(1); /* idDelta[1] */ 1080 (void) put_ushort(2 * TTF_USHORT_SIZE); /* idRangeOffset[0] */ 1081 (void) put_ushort(0); /* idRangeOffset[1] */ 1082 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) 1083 (void) put_ushort(e->newindex); 1084} 1085 1086@ 1087@c 1088#define CMAP_ENTRY_LENGTH (2*TTF_USHORT_SIZE + TTF_ULONG_SIZE) 1089 1090static void ttf_select_cmap(void) 1091{ 1092 assert(sizeof(new_cmap_tab) <= NEW_CMAP_SIZE * sizeof(cmap_entry)); 1093 new_cmap_tab[0].platform_id = 1; /* Macintosh */ 1094 new_cmap_tab[0].encoding_id = 0; /* Symbol; ignore code page */ 1095 new_cmap_tab[0].format = (TTF_USHORT) (new_glyphs_count < 256 ? 0 /* byte encoding */ 1096 : 6); /* trimmed table mapping */ 1097 new_cmap_tab[1].platform_id = 3; /* Microsoft */ 1098 new_cmap_tab[1].encoding_id = 0; /* Symbol; ignore code page */ 1099 new_cmap_tab[1].format = 4; /* segment mapping to delta */ 1100} 1101 1102static void ttf_write_cmap(PDF pdf) 1103{ 1104 cmap_entry *ce; 1105 long offset; 1106 dirtab_entry *tab = ttf_name_lookup("cmap", true); 1107 ttf_select_cmap(); 1108 ttf_reset_chksm(pdf, tab); 1109 (void) put_ushort(0); /* table version number (0) */ 1110 (void) put_ushort(NEW_CMAP_SIZE); /* number of encoding tables */ 1111 offset = 2 * TTF_USHORT_SIZE + NEW_CMAP_SIZE * CMAP_ENTRY_LENGTH; 1112 for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) { 1113 ce->offset = (TTF_ULONG) offset; 1114 switch (ce->format) { 1115 case 0: 1116 offset += BYTE_ENCODING_LENGTH; 1117 break; 1118 case 4: 1119 offset += SEG_MAP_DELTA_LENGTH; 1120 break; 1121 case 6: 1122 offset += TRIMMED_TABLE_MAP_LENGTH; 1123 break; 1124 default: 1125 luatex_fail("invalid format (it should not have happened)"); 1126 } 1127 (void) put_ushort(ce->platform_id); 1128 (void) put_ushort(ce->encoding_id); 1129 put_ulong((long) ce->offset); 1130 } 1131 for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) { 1132 switch (ce->format) { 1133 case 0: 1134 ttf_byte_encoding(pdf); 1135 break; 1136 case 4: 1137 ttf_seg_map_delta(pdf); 1138 break; 1139 case 6: 1140 ttf_trimmed_table_map(pdf); 1141 break; 1142 } 1143 } 1144 ttf_set_chksm(pdf, tab); 1145} 1146 1147@ 1148@c 1149static int prepend_subset_tags(int index, char *p) 1150{ 1151 boolean is_unicode; 1152 int i; 1153 assert(index >= 0 && index < name_record_num && fd_cur->subset_tag != NULL); 1154 is_unicode = (name_tab[index].platform_id == 3); 1155 if (is_unicode) { 1156 for (i = 0; i < 6; ++i) { 1157 *p++ = 0; 1158 *p++ = fd_cur->subset_tag[i]; 1159 } 1160 *p++ = 0; 1161 *p++ = '+'; 1162 return 14; 1163 } else { 1164 strncpy(p, fd_cur->subset_tag, 6); 1165 p += 6; 1166 *p++ = '+'; 1167 return 7; 1168 } 1169} 1170 1171 1172static void ttf_write_name(PDF pdf) 1173{ 1174 int i, l; 1175 char *p; 1176 int new_name_buf_size; 1177 char *new_name_buf; 1178 name_record *n; 1179 dirtab_entry *tab = ttf_name_lookup("name", true); 1180 if (is_subsetted(fd_cur->fm)) { 1181 l = 0; 1182 for (i = 0; i < name_record_num; i++) 1183 l += name_tab[i].length + 14; /* maximum lengh of new stogare area */ 1184 new_name_buf = xtalloc((unsigned) l, char); 1185 /* additional space for subset tags */ 1186 p = new_name_buf; 1187 for (i = 0; i < name_record_num; i++) { 1188 n = name_tab + i; 1189 n->new_offset = (TTF_USHORT) (p - new_name_buf); 1190 if ((n->name_id == 1 || n->name_id == 3 || 1191 n->name_id == 4 || n->name_id == 6) && 1192 ((n->platform_id == 1 && n->encoding_id == 0) || 1193 (n->platform_id == 3 && n->encoding_id == 0) || 1194 (n->platform_id == 3 && n->encoding_id == 1))) { 1195 l = prepend_subset_tags(i, p); 1196 p += l; 1197 } else 1198 l = 0; 1199 memcpy(p, name_buf + n->offset, n->length); 1200 p += n->length; 1201 n->new_length = (TTF_USHORT) (n->length + l); 1202 } 1203 new_name_buf_size = (int) (p - new_name_buf); 1204 } else { 1205 new_name_buf = name_buf; 1206 new_name_buf_size = name_buf_size; 1207 } 1208 ttf_reset_chksm(pdf, tab); 1209 (void) put_ushort(0); /* Format selector */ 1210 (void) put_ushort(name_record_num); 1211 (void) put_ushort(3 * TTF_USHORT_SIZE + 1212 name_record_num * 6 * TTF_USHORT_SIZE); 1213 for (i = 0; i < name_record_num; i++) { 1214 (void) put_ushort(name_tab[i].platform_id); 1215 (void) put_ushort(name_tab[i].encoding_id); 1216 (void) put_ushort(name_tab[i].language_id); 1217 (void) put_ushort(name_tab[i].name_id); 1218 (void) put_ushort(name_tab[i].new_length); 1219 (void) put_ushort(name_tab[i].new_offset); 1220 } 1221 for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++) 1222 put_char(*p); 1223 ttf_set_chksm(pdf, tab); 1224 if (new_name_buf != name_buf) 1225 xfree(new_name_buf); 1226} 1227 1228@ 1229@c 1230static void ttf_write_dirtab(PDF pdf) 1231{ 1232 dirtab_entry *tab; 1233 TTF_ULONG i, k; 1234 char *p; 1235 const int save_offset = ttf_offset(); 1236 ttf_seek_outbuf(TABDIR_OFF); 1237 if (is_subsetted(fd_cur->fm)) { 1238 for (i = 0; i < DEFAULT_NTABS; i++) { 1239 tab = ttf_name_lookup(newtabnames[i], false); 1240 if (tab == NULL) 1241 continue; 1242 for (k = 0; k < 4; k++) 1243 put_char(tab->tag[k]); 1244 put_ulong((long) tab->checksum); 1245 put_ulong((long) tab->offset); 1246 put_ulong((long) tab->length); 1247 } 1248 } else { 1249 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) { 1250 for (k = 0; k < 4; k++) 1251 put_char(tab->tag[k]); 1252 put_ulong((long) tab->checksum); 1253 put_ulong((long) tab->offset); 1254 put_ulong((long) tab->length); 1255 } 1256 } 1257 /* adjust checkSumAdjustment */ 1258 tmp_ulong = 0; 1259 checksum = 0; 1260 for (p = (char *) pdf->fb->data, i = 0; i < (unsigned) save_offset;) { 1261 tmp_ulong = (tmp_ulong << 8) + (TTF_ULONG) * p++; 1262 i++; 1263 if (i % 4 == 0) { 1264 checksum += tmp_ulong; 1265 tmp_ulong = 0; 1266 } 1267 } 1268 if (i % 4 != 0) { 1269 luatex_warn("font length is not a multiple of 4 (%li)", i); 1270 checksum <<= 8 * (4 - i % 4); 1271 } 1272 k = 0xB1B0AFBA - checksum; 1273 ttf_seek_outbuf((int) checkSumAdjustment_offset); 1274 put_ulong((long) k); 1275 ttf_seek_outbuf(save_offset); 1276} 1277 1278@ 1279@c 1280static void ttf_write_glyf(PDF pdf) 1281{ 1282 long *id, k; 1283 TTF_USHORT idx; 1284 TTF_USHORT flags; 1285 dirtab_entry *tab = ttf_name_lookup("glyf", true); 1286 const long glyf_offset = (long) tab->offset; 1287 const long new_glyf_offset = ttf_offset(); 1288 ttf_reset_chksm(pdf, tab); 1289 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) { 1290 glyph_tab[*id].newoffset = ttf_offset() - new_glyf_offset; 1291 if (glyph_tab[*id].offset != glyph_tab[*id + 1].offset) { 1292 ttf_seek_off(glyf_offset + glyph_tab[*id].offset); 1293 k = copy_short(); 1294 ttf_ncopy(pdf, 4 * TTF_FWORD_SIZE); 1295 if (k < 0) { 1296 do { 1297 flags = copy_ushort(); 1298 idx = get_ushort(); 1299 if (glyph_tab[idx].newindex < 0) { 1300 glyph_tab[idx].newindex = (TTF_SHORT) new_glyphs_count; 1301 glyph_index[new_glyphs_count++] = idx; 1302 /* 1303 N.B.: Here we change |new_glyphs_count|, 1304 which appears in the condition of the |for| loop 1305 */ 1306 } 1307 (void) put_ushort(glyph_tab[idx].newindex); 1308 if (flags & ARG_1_AND_2_ARE_WORDS) 1309 ttf_ncopy(pdf, 2 * TTF_SHORT_SIZE); 1310 else 1311 ttf_ncopy(pdf, TTF_USHORT_SIZE); 1312 if (flags & WE_HAVE_A_SCALE) 1313 ttf_ncopy(pdf, TTF_F2DOT14_SIZE); 1314 else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) 1315 ttf_ncopy(pdf, 2 * TTF_F2DOT14_SIZE); 1316 else if (flags & WE_HAVE_A_TWO_BY_TWO) 1317 ttf_ncopy(pdf, 4 * TTF_F2DOT14_SIZE); 1318 } while (flags & MORE_COMPONENTS); 1319 if (flags & WE_HAVE_INSTRUCTIONS) 1320 ttf_ncopy(pdf, copy_ushort()); 1321 } else 1322 ttf_ncopy(pdf, (int) 1323 (glyph_tab[*id + 1].offset - glyph_tab[*id].offset - 1324 TTF_USHORT_SIZE - 4 * TTF_FWORD_SIZE)); 1325 } 1326 } 1327 last_glyf_offset = (TTF_ULONG) ttf_offset() - (TTF_ULONG) new_glyf_offset; 1328 ttf_set_chksm(pdf, tab); 1329} 1330 1331@ Reindexing glyphs: we append index of used glyphs to |glyph_index| 1332 while going through |ttfenc_tab|. After appending a new entry to 1333 |glyph_index| we set field |newindex| of corresponding entries in both 1334 |glyph_tab| and |ttfenc_tab| to the newly created index. 1335 1336@c 1337static void ttf_reindex_glyphs(void) 1338{ 1339 ttfenc_entry *e; 1340 glyph_entry *glyph; 1341 int index; 1342 long *t; 1343 ttf_cmap_entry *cmap = NULL; 1344 boolean cmap_not_found = false; 1345 1346 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) { 1347 e->newindex = 0; /* index of ".notdef" glyph */ 1348 1349 /* handle case of subfonts first */ 1350 if (is_subfont(fd_cur->fm)) { 1351 if (e->code == -1) 1352 continue; 1353 assert(fd_cur->fm->pid != -1 && fd_cur->fm->eid != -1); 1354 if (cmap == NULL && !cmap_not_found) { 1355 cmap = 1356 ttf_read_cmap(fd_cur->fm->ff_name, fd_cur->fm->pid, 1357 fd_cur->fm->eid, true); 1358 if (cmap == NULL) 1359 cmap_not_found = true; 1360 } 1361 if (cmap == NULL) 1362 continue; 1363 t = cmap->table; 1364 assert(t != NULL && e->code < 0x10000); 1365 if (t[e->code] < 0) { 1366 luatex_warn 1367 ("subfont %s: wrong mapping: character %li --> 0x%4.4lX --> .notdef", 1368 fd_cur->fm->tfm_name, (long) (e - ttfenc_tab), e->code); 1369 continue; 1370 } 1371 assert(t[e->code] >= 0 && t[e->code] < glyphs_count); /* t has been read from ttf */ 1372 glyph = glyph_tab + t[e->code]; 1373 goto append_new_glyph; 1374 } 1375 1376 /* handle case of reencoded fonts */ 1377 if (e->name == notdef) 1378 continue; 1379 /* scan form `index123' */ 1380 if (sscanf(e->name, GLYPH_PREFIX_INDEX "%i", &index) == 1) { 1381 if (index >= glyphs_count) { 1382 luatex_warn("`%s' out of valid range [0..%i)", 1383 e->name, glyphs_count); 1384 continue; 1385 } 1386 glyph = glyph_tab + index; 1387 goto append_new_glyph; 1388 } 1389 /* scan form `uniABCD' */ 1390 if (sscanf(e->name, GLYPH_PREFIX_UNICODE "%X", &index) == 1) { 1391 if (cmap == NULL && !cmap_not_found) { 1392 /* need to read the unicode mapping, ie (pid,eid) = (3,1) or (0,3) */ 1393 cmap = ttf_read_cmap(fd_cur->fm->ff_name, 3, 1, false); 1394 if (cmap == NULL) 1395 cmap = ttf_read_cmap(fd_cur->fm->ff_name, 0, 3, false); 1396 if (cmap == NULL) { 1397 luatex_warn 1398 ("no unicode mapping found, all `uniXXXX' names will be ignored"); 1399 cmap_not_found = true; /* once only */ 1400 } 1401 } 1402 if (cmap == NULL) 1403 continue; 1404 t = cmap->table; 1405 assert(t != NULL); 1406 if (t[index] != -1) { 1407 if (t[index] >= glyphs_count) { 1408 luatex_warn 1409 ("`%s' is mapped to index %li which is out of valid range [0..%i)", 1410 e->name, t[index], glyphs_count); 1411 continue; 1412 } 1413 glyph = glyph_tab + t[index]; 1414 goto append_new_glyph; 1415 } else { 1416 luatex_warn("`unicode %s%.4X' is not mapped to any glyph", 1417 GLYPH_PREFIX_UNICODE, index); 1418 continue; 1419 } 1420 } 1421 /* look up by name */ 1422 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) 1423 if (glyph->name != notdef && strcmp(glyph->name, e->name) == 0) 1424 break; 1425 if (!(glyph - glyph_tab < glyphs_count)) { 1426 luatex_warn("glyph `%s' not found", e->name); 1427 continue; 1428 } 1429 append_new_glyph: 1430 assert(glyph > glyph_tab && glyph - glyph_tab < glyphs_count); 1431 if (glyph->newindex < 0) { 1432 glyph_index[new_glyphs_count] = (short) (glyph - glyph_tab); 1433 glyph->newindex = (TTF_SHORT) new_glyphs_count; 1434 new_glyphs_count++; 1435 } 1436 e->newindex = glyph->newindex; 1437 } 1438} 1439 1440@ To calculate the checkSum for the 'head' table which itself includes the 1441 checkSumAdjustment entry for the entire font, do the following: 1442 1443 \item Set the checkSumAdjustment to 0. 1444 \item Calculate the checksum for all the tables including the 'head' table 1445 and enter that value into the table directory. 1446 \item Calculate the checksum for the entire font. 1447 \item Subtract that value from the hex value B1B0AFBA. 1448 \item Store the result in checkSumAdjustment. 1449 1450 The checkSum for the 'head table which includes the checkSumAdjustment 1451 entry for the entire font is now incorrect. That is not a problem. Do not 1452 change it. An application attempting to verify that the 'head' table has 1453 not changed should calculate the checkSum for that table by not including 1454 the checkSumAdjustment value, and compare the result with the entry in the 1455 table directory. 1456 1457 The table directory also includes the offset of the associated tagged 1458 table from the beginning of the font file and the length of that table. 1459 1460 1461@c 1462static void ttf_write_head(PDF pdf) 1463{ 1464 dirtab_entry *tab; 1465 tab = ttf_seek_tab("head", 0); 1466 ttf_reset_chksm(pdf, tab); 1467 ttf_ncopy(pdf, 2 * TTF_FIXED_SIZE); 1468 checkSumAdjustment_offset = (TTF_ULONG) ttf_offset(); 1469 put_ulong(0); 1470 ttf_skip(TTF_ULONG_SIZE); /* skip checkSumAdjustment */ 1471 ttf_ncopy(pdf, TTF_ULONG_SIZE + 2 * TTF_USHORT_SIZE + 16 + 1472 4 * TTF_FWORD_SIZE + 2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE); 1473 if (is_subsetted(fd_cur->fm)) { 1474 (void) put_short(loca_format); 1475 (void) put_short(0); 1476 } else 1477 ttf_ncopy(pdf, 2 * TTF_SHORT_SIZE); 1478 ttf_set_chksm(pdf, tab); 1479} 1480 1481@ 1482@c 1483static void ttf_write_hhea(PDF pdf) 1484{ 1485 dirtab_entry *tab; 1486 tab = ttf_seek_tab("hhea", 0); 1487 ttf_reset_chksm(pdf, tab); 1488 ttf_ncopy(pdf, TTF_FIXED_SIZE + 3 * TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 1489 3 * TTF_FWORD_SIZE + 8 * TTF_SHORT_SIZE); 1490 (void) put_ushort(new_glyphs_count); 1491 ttf_set_chksm(pdf, tab); 1492} 1493 1494@ 1495@c 1496static void ttf_write_htmx(PDF pdf) 1497{ 1498 long *id; 1499 dirtab_entry *tab = ttf_seek_tab("hmtx", 0); 1500 ttf_reset_chksm(pdf, tab); 1501 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) { 1502 put_ufword(glyph_tab[*id].advWidth); 1503 put_ufword(glyph_tab[*id].lsb); 1504 } 1505 ttf_set_chksm(pdf, tab); 1506} 1507 1508@ 1509@c 1510static void ttf_write_loca(PDF pdf) 1511{ 1512 long *id; 1513 dirtab_entry *tab = ttf_seek_tab("loca", 0); 1514 ttf_reset_chksm(pdf, tab); 1515 loca_format = 0; 1516 if (last_glyf_offset >= 0x00020000 || (last_glyf_offset & 1)) 1517 loca_format = 1; 1518 else 1519 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) 1520 if (glyph_tab[*id].newoffset & 1) { 1521 loca_format = 1; 1522 break; 1523 } 1524 if (loca_format != 0) { 1525 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) 1526 put_ulong(glyph_tab[*id].newoffset); 1527 put_ulong((long) last_glyf_offset); 1528 } else { 1529 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) 1530 (void) put_ushort(glyph_tab[*id].newoffset / 2); 1531 (void) put_ushort((long) (last_glyf_offset / 2)); 1532 } 1533 ttf_set_chksm(pdf, tab); 1534} 1535 1536@ 1537@c 1538static void ttf_write_mapx(PDF pdf) 1539{ 1540 dirtab_entry *tab = ttf_seek_tab("maxp", TTF_FIXED_SIZE + TTF_USHORT_SIZE); 1541 ttf_reset_chksm(pdf, tab); 1542 put_fixed(0x00010000); 1543 (void) put_ushort(new_glyphs_count); 1544 ttf_ncopy(pdf, 13 * TTF_USHORT_SIZE); 1545 ttf_set_chksm(pdf, tab); 1546} 1547 1548@ 1549@c 1550static void ttf_write_OS2(PDF pdf) 1551{ 1552 dirtab_entry *tab = ttf_seek_tab("OS/2", 0); 1553 TTF_USHORT version; 1554 ttf_reset_chksm(pdf, tab); 1555 version = get_ushort(); 1556 if (version > 3) 1557 luatex_fail("unknown version of OS/2 table (%.4X)", version); 1558 (void) put_ushort(0x0001); /* fix version to 1 */ 1559 ttf_ncopy(pdf, 1560 2 * TTF_USHORT_SIZE + 13 * TTF_SHORT_SIZE + 10 * TTF_BYTE_SIZE); 1561 ttf_skip(4 * TTF_ULONG_SIZE); /* ulUnicodeRange 1--4 */ 1562 put_ulong(0x00000003); /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */ 1563 put_ulong(0x10000000); /* Private Use (0xE000--0xF8FF) */ 1564 put_ulong(0x00000000); 1565 put_ulong(0x00000000); 1566 ttf_ncopy(pdf, 4 * TTF_CHAR_SIZE + TTF_USHORT_SIZE); /* achVendID + fsSelection */ 1567 ttf_skip(2 * TTF_USHORT_SIZE); 1568 (void) put_ushort(0x0000); /* usFirstCharIndex */ 1569 (void) put_ushort(0xF0FF); /* usLastCharIndex */ 1570 ttf_ncopy(pdf, 5 * TTF_USHORT_SIZE); 1571 /* for version 0 the OS/2 table ends here, the rest is for version 1 */ 1572 put_ulong(0x80000000); /* Symbol Character Set---don't use any code page */ 1573 put_ulong(0x00000000); 1574 ttf_set_chksm(pdf, tab); 1575} 1576 1577@ 1578@c 1579static boolean unsafe_name(const char *s) 1580{ 1581 const char **p; 1582 for (p = ambiguous_names; *p != NULL; p++) 1583 if (strcmp(s, *p) == 0) 1584 return true; 1585 return false; 1586} 1587 1588static void ttf_write_post(PDF pdf) 1589{ 1590 dirtab_entry *tab = ttf_seek_tab("post", TTF_FIXED_SIZE); 1591 glyph_entry *glyph; 1592 const char *s; 1593 long *id; 1594 int k, l; 1595 ttf_reset_chksm(pdf, tab); 1596 if (!fd_cur->write_ttf_glyph_names || post_format == 0x00030000) { 1597 put_fixed(0x00030000); 1598 ttf_ncopy(pdf, 1599 TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE); 1600 } else { 1601 put_fixed(0x00020000); 1602 ttf_ncopy(pdf, 1603 TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE); 1604 (void) put_ushort(new_glyphs_count); 1605 k = 0; 1606 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) { 1607 glyph = glyph_tab + *id; 1608 if (glyph->name_index >= NMACGLYPHS || unsafe_name(glyph->name)) 1609 glyph->name_index = (TTF_USHORT) (NMACGLYPHS + k++); 1610 (void) put_ushort(glyph->name_index); 1611 } 1612 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) { 1613 glyph = glyph_tab + *id; 1614 if (glyph->name_index >= NMACGLYPHS) { 1615 s = glyph->name; 1616 l = (int) strlen(s); 1617 put_byte(l); 1618 while (l-- > 0) 1619 put_char(*s++); 1620 } 1621 } 1622 } 1623 ttf_set_chksm(pdf, tab); 1624} 1625 1626@ 1627@c 1628static void ttf_init_font(PDF pdf, int n) 1629{ 1630 int i, k; 1631 for (i = 1, k = 0; i <= n; i <<= 1, k++); 1632 put_fixed(0x00010000); /* font version */ 1633 (void) put_ushort(n); /* number of tables */ 1634 (void) put_ushort(i << 3); /* search range */ 1635 (void) put_ushort(k - 1); /* entry selector */ 1636 (void) put_ushort((n << 4) - (i << 3)); /* range shift */ 1637 ttf_seek_outbuf(TABDIR_OFF + n * 4 * TTF_ULONG_SIZE); 1638} 1639 1640@ 1641@c 1642static void ttf_subset_font(PDF pdf) 1643{ 1644 ttf_init_font(pdf, new_ntabs); 1645 if (ttf_name_lookup("PCLT", false) != NULL) 1646 ttf_copytab(pdf, "PCLT"); 1647 if (ttf_name_lookup("fpgm", false) != NULL) 1648 ttf_copytab(pdf, "fpgm"); 1649 if (ttf_name_lookup("cvt ", false) != NULL) 1650 ttf_copytab(pdf, "cvt "); 1651 if (ttf_name_lookup("prep", false) != NULL) 1652 ttf_copytab(pdf, "prep"); 1653 ttf_reindex_glyphs(); 1654 ttf_write_glyf(pdf); 1655 ttf_write_loca(pdf); 1656 ttf_write_OS2(pdf); 1657 ttf_write_head(pdf); 1658 ttf_write_hhea(pdf); 1659 ttf_write_htmx(pdf); 1660 ttf_write_mapx(pdf); 1661 ttf_write_name(pdf); 1662 ttf_write_post(pdf); 1663 ttf_write_cmap(pdf); 1664 ttf_write_dirtab(pdf); 1665} 1666 1667@ 1668@c 1669static void ttf_copy_font(PDF pdf) 1670{ 1671 dirtab_entry *tab; 1672 ttf_init_font(pdf, ntabs); 1673 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) { 1674 if (strncmp(tab->tag, "head", 4) == 0) 1675 ttf_write_head(pdf); 1676 else 1677 ttf_copytab(pdf, tab->tag); 1678 } 1679 ttf_write_dirtab(pdf); 1680} 1681 1682@ 1683@c 1684void writettf(PDF pdf, fd_entry * fd) 1685{ 1686 int callback_id; 1687 int file_opened = 0; 1688 fd_cur = fd; /* |fd_cur| is global inside \.{writettf.w} */ 1689 assert(fd_cur->fm != NULL); 1690 assert(is_truetype(fd_cur->fm)); 1691 assert(is_included(fd_cur->fm)); 1692 1693 if (is_subsetted(fd_cur->fm) && (fd_cur->fe == NULL) 1694 && !is_subfont(fd_cur->fm)) { 1695 luatex_fail("Subset TrueType must be a reencoded or a subfont"); 1696 } 1697 ttf_curbyte = 0; 1698 ttf_size = 0; 1699 1700 cur_file_name = 1701 luatex_find_file(fd_cur->fm->ff_name, find_truetype_file_callback); 1702 if (cur_file_name == NULL) { 1703 luatex_fail("cannot find TrueType font file for reading (%s)", fd_cur->fm->ff_name); 1704 } 1705 callback_id = callback_defined(read_truetype_file_callback); 1706 if (callback_id > 0) { 1707 if (run_callback(callback_id, "S->bSd", cur_file_name, 1708 &file_opened, &ttf_buffer, &ttf_size) && 1709 file_opened && ttf_size > 0) { 1710 } else { 1711 luatex_fail("cannot open TrueType font file for reading (%s)", cur_file_name); 1712 } 1713 } else { 1714 if (!ttf_open(cur_file_name)) { 1715 luatex_fail("cannot open TrueType font file for reading (%s)", cur_file_name); 1716 } 1717 ttf_read_file(); 1718 ttf_close(); 1719 } 1720 if (tracefilenames) { 1721 if (is_subsetted(fd_cur->fm)) 1722 tex_printf("<%s", cur_file_name); 1723 else 1724 tex_printf("<<%s", cur_file_name); 1725 } 1726 fd_cur->ff_found = true; 1727 new_glyphs_count = 2; 1728 new_ntabs = DEFAULT_NTABS; 1729 dir_tab = NULL; 1730 glyph_tab = NULL; 1731 glyph_index = NULL; 1732 glyph_name_buf = NULL; 1733 name_tab = NULL; 1734 name_buf = NULL; 1735 ttf_read_font(); 1736 1737 pdf_save_offset(pdf); 1738 pdf_flush(pdf); 1739 1740 if (is_subsetted(fd_cur->fm)) { 1741 ttf_copy_encoding(); 1742 ttf_subset_font(pdf); 1743 } else 1744 ttf_copy_font(pdf); 1745 ttf_length = ttf_offset(); 1746 1747 xfree(dir_tab); 1748 xfree(glyph_tab); 1749 xfree(glyph_index); 1750 xfree(glyph_name_buf); 1751 xfree(name_tab); 1752 xfree(name_buf); 1753 if (tracefilenames) { 1754 if (is_subsetted(fd_cur->fm)) 1755 tex_printf(">"); 1756 else 1757 tex_printf(">>"); 1758 } 1759 xfree(ttf_buffer); 1760 cur_file_name = NULL; 1761} 1762 1763static void do_writeotf(PDF pdf, fd_entry * fd) 1764{ 1765 long i; 1766 dirtab_entry *tab; 1767 (void) fd; 1768 dir_tab = NULL; 1769 glyph_tab = NULL; 1770 if (tracefilenames) 1771 tex_printf("<<%s", cur_file_name); 1772 ttf_read_tabdir(); 1773 /* read font parameters */ 1774 if (ttf_name_lookup("head", false) != NULL) 1775 ttf_read_head(); 1776 if (ttf_name_lookup("hhea", false) != NULL) 1777 ttf_read_hhea(); 1778 if (ttf_name_lookup("PCLT", false) != NULL) 1779 ttf_read_pclt(); 1780 if (ttf_name_lookup("post", false) != NULL) 1781 ttf_read_post(); 1782 /* copy font file */ 1783 tab = ttf_seek_tab("CFF ", 0); 1784 for (i = (long) tab->length; i > 0; i--) 1785 copy_char(); 1786 xfree(dir_tab); 1787 if (tracefilenames) 1788 tex_printf(">>"); 1789} 1790 1791@ 1792@c 1793void writeotf(PDF pdf, fd_entry * fd) 1794{ 1795 int callback_id; 1796 int file_opened = 0; 1797 1798 fd_cur = fd; 1799 assert(fd_cur->fm != NULL); 1800 assert(is_opentype(fd_cur->fm)); 1801 assert(is_included(fd_cur->fm)); 1802 1803 ttf_curbyte = 0; 1804 ttf_size = 0; 1805 cur_file_name = 1806 luatex_find_file(fd_cur->fm->ff_name, find_opentype_file_callback); 1807 if (cur_file_name == NULL) { 1808 luatex_fail("cannot find OpenType font file for reading (%s)", fd_cur->fm->ff_name); 1809 } 1810 callback_id = callback_defined(read_opentype_file_callback); 1811 if (callback_id > 0) { 1812 if (run_callback(callback_id, "S->bSd", cur_file_name, 1813 &file_opened, &ttf_buffer, &ttf_size) && 1814 file_opened && ttf_size > 0) { 1815 } else { 1816 luatex_fail("cannot open OpenType font file for reading (%s)", cur_file_name); 1817 } 1818 } else { 1819 if (!otf_open(cur_file_name)) { 1820 luatex_fail("cannot open OpenType font file for reading (%s)", cur_file_name); 1821 } 1822 ttf_read_file(); 1823 ttf_close(); 1824 } 1825 1826 fd_cur->ff_found = true; 1827 do_writeotf(pdf, fd); 1828 xfree(ttf_buffer); 1829 cur_file_name = NULL; 1830} 1831 1832