beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / font / writettf.w
blobe1edea5e2ab0bc421fa3247dceabe720c0551df9
1 % writettf.w
3 % Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
4 % Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org>
6 % This file is part of LuaTeX.
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.
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.
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/>.
21 @ @c
24 #include "ptexlib.h"
25 #include "font/writettf.h"
26 #include <string.h>
28 #define DEFAULT_NTABS 14
29 #define NEW_CMAP_SIZE 2
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))
35 unsigned char *ttf_buffer = NULL;
36 int ttf_size = 0;
37 int ttf_curbyte = 0;
39 typedef 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 */
44 } ttfenc_entry;
46 typedef 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;
57 typedef struct {
58 char *ttf_name;
59 TTF_USHORT pid;
60 TTF_USHORT eid;
61 long *table;
62 } ttf_cmap_entry;
64 static TTF_USHORT ntabs;
65 static TTF_USHORT upem;
66 static TTF_FIXED post_format;
67 static TTF_SHORT loca_format;
68 static TTF_ULONG last_glyf_offset;
69 static TTF_USHORT glyphs_count;
70 static TTF_USHORT new_glyphs_count;
71 static TTF_USHORT nhmtxs;
72 static TTF_USHORT new_ntabs;
74 glyph_entry *glyph_tab;
75 dirtab_entry *dir_tab;
77 static long *glyph_index;
78 static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE];
79 static name_record *name_tab;
80 static int name_record_num;
81 static char *name_buf;
82 static int name_buf_size;
83 static char *glyph_name_buf;
84 static TTF_ULONG checksum;
85 static TTF_ULONG tab_length;
86 static TTF_ULONG tmp_ulong;
87 static TTF_ULONG checkSumAdjustment_offset;
88 FILE *ttf_file;
89 static ttfenc_entry ttfenc_tab[256];
91 fd_entry *fd_cur; /* pointer to the current font descriptor */
93 static struct avl_table *ttf_cmap_tree = NULL;
95 int ttf_length;
97 @ This used to be macnames.c
100 char notdef[] = ".notdef";
102 const 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"
380 const 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
391 static 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"
408 @ Back to code. Low-level helpers first.
411 static ttf_cmap_entry *new_ttf_cmap_entry(void)
413 ttf_cmap_entry *e;
414 e = xtalloc(1, ttf_cmap_entry);
415 e->ttf_name = NULL;
416 e->table = NULL;
417 return e;
420 static void destroy_ttf_cmap_entry(void *pa, void *pb)
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);
430 void ttf_free(void)
432 if (ttf_cmap_tree != NULL)
433 avl_destroy(ttf_cmap_tree, destroy_ttf_cmap_entry);
436 static int comp_ttf_cmap_entry(const void *pa, const void *pb, void *p)
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;
450 static unsigned char ttf_addchksm(unsigned char b)
452 tmp_ulong = (tmp_ulong << 8) + b;
453 tab_length++;
454 if (tab_length % 4 == 0) {
455 checksum += tmp_ulong;
456 tmp_ulong = 0;
458 return b;
461 static TTF_ULONG ttf_getchksm(PDF pdf)
463 while (tab_length % 4 != 0)
464 ttf_putchar(ttf_addchksm(0)); /* |ttf_addchksm| updates |tab_length| */
465 return checksum;
468 long ttf_putnum(PDF pdf, int s, long n)
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;
476 p--;
477 while (p >= buf)
478 ttf_putchar(ttf_addchksm((unsigned char) (*p--)));
479 return n;
482 long ttf_getnum(int s)
484 long i = 0;
485 int c;
486 while (s > 0) {
487 if (ttf_eof())
488 normal_error("ttf font","unexpected EOF");
489 c = ttf_getchar();
490 i = (i << 8) + c;
491 s--;
493 return i;
496 static long ttf_funit(long n)
498 if (n < 0)
499 return -((-n / upem) * 1000 + ((-n % upem) * 1000) / upem);
500 else
501 return (n / upem) * 1000 + ((n % upem) * 1000) / upem;
504 static void ttf_ncopy(PDF pdf, int n)
506 while (n-- > 0)
507 copy_byte();
510 dirtab_entry *ttf_name_lookup(const char *s, boolean required)
512 dirtab_entry *tab;
513 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
514 if (strncmp(tab->tag, s, 4) == 0)
515 break;
517 if (tab - dir_tab == ntabs) {
518 if (required)
519 formatted_error("ttf font","can't find table '%s'", s);
520 else
521 tab = NULL;
523 return tab;
526 dirtab_entry *ttf_seek_tab(const char *name, TTF_LONG offset)
528 dirtab_entry *tab = ttf_name_lookup(name, true);
529 ttf_curbyte = (int) (tab->offset + (unsigned long) offset);
530 return tab;
533 static void ttf_seek_off(TTF_LONG offset)
535 ttf_curbyte = (int) offset;
538 static void ttf_copy_encoding(void)
540 int i, *q;
541 void **aa;
542 char **glyph_names;
543 long *charcodes;
544 static char buf[SMALL_BUF_SIZE];
545 struct avl_traverser t;
546 ttfenc_entry *e = ttfenc_tab;
548 assert(fd_cur->tx_tree != NULL); /* this must be set in |create_fontdictionary| */
550 if (fd_cur->fe != NULL) {
551 glyph_names = fd_cur->fe->glyph_names;
552 assert(glyph_names != NULL);
554 for (i = 0; i < 256; i++)
555 ttfenc_tab[i].name = (char *) notdef;
557 /* a workaround for a bug of AcroReader 4.0 */
558 if (strcmp(glyph_names[97], "a") == 0) {
559 q = xtalloc(1, int);
560 *q = 'a';
561 aa = avl_probe(fd_cur->tx_tree, q);
562 assert(aa != NULL);
564 /* end of workaround */
566 /* take over collected characters from \TeX, reencode them */
567 avl_t_init(&t, fd_cur->tx_tree);
568 for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
569 q = (int *) avl_t_next(&t)) {
570 assert(*q >= 0 && *q < 256);
571 ttfenc_tab[*q].name = glyph_names[*q];
573 make_subset_tag(fd_cur);
574 } else if (is_subfont(fd_cur->fm)) {
575 charcodes = fd_cur->fm->subfont->charcodes;
576 assert(charcodes != NULL);
578 for (i = 0; i < 256; i++)
579 ttfenc_tab[i].code = -1;
581 /* take over collected characters from \TeX */
582 avl_t_init(&t, fd_cur->tx_tree);
583 for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
584 q = (int *) avl_t_next(&t)) {
585 assert(*q >= 0 && *q < 256);
586 e = ttfenc_tab + *q;
587 e->code = charcodes[*q];
588 if (e->code == -1)
589 formatted_warning("ttf font", "character %i in subfont %s is not mapped to any charcode", *q, fd_cur->fm->tfm_name);
590 else {
591 assert(e->code < 0x10000);
592 sprintf(buf, "/c%4.4X", (int) e->code);
593 aa = avl_probe(fd_cur->gl_tree, xstrdup(buf));
594 assert(aa != NULL);
597 make_subset_tag(fd_cur);
598 } else
599 assert(0);
604 #define ttf_append_byte(B)\
605 do {\
606 if (name_tab[i].platform_id == 3)\
607 *q++ = 0;\
608 *q++ = B;\
609 } while (0)
611 static char *strip_spaces_and_delims(char *s, int l)
613 static char buf[SMALL_BUF_SIZE];
614 char *p = buf;
615 int i;
617 assert(l >= 0 && l < (int) sizeof(buf));
619 for (i = 0; i < l; s++, i++) {
620 if (*s == '(' || *s == ')' || *s == '<' || *s == '>' ||
621 *s == '[' || *s == ']' || *s == '{' || *s == '}' ||
622 *s == '/' || *s == '%' || isspace((unsigned char)*s))
623 continue;
624 *p++ = *s;
626 *p = 0;
627 return buf;
630 static void ttf_read_name(void)
632 int i, j;
633 dirtab_entry *tab = ttf_seek_tab("name", TTF_USHORT_SIZE);
634 char *p, buf[SMALL_BUF_SIZE];
635 name_record_num = get_ushort();
636 name_tab = xtalloc((unsigned) name_record_num, name_record);
637 name_buf_size = (int) ((unsigned) tab->length -
638 (3 * TTF_USHORT_SIZE +
639 (TTF_ULONG) name_record_num * 6 * TTF_USHORT_SIZE));
640 name_buf = xtalloc((unsigned) name_buf_size, char);
641 ttf_skip(TTF_USHORT_SIZE);
642 for (i = 0; i < name_record_num; i++) {
643 name_tab[i].platform_id = get_ushort();
644 name_tab[i].encoding_id = get_ushort();
645 name_tab[i].language_id = get_ushort();
646 name_tab[i].name_id = get_ushort();
647 name_tab[i].length = get_ushort();
648 name_tab[i].offset = get_ushort();
650 for (p = name_buf; p - name_buf < name_buf_size; p++)
651 *p = get_char();
652 /* look for PS font name */
653 for (i = 0; i < name_record_num; i++) {
654 if (name_tab[i].platform_id == 1 &&
655 name_tab[i].encoding_id == 0 && name_tab[i].name_id == 6) {
656 xfree(fd_cur->fontname);
657 fd_cur->fontname =
658 xstrdup(strip_spaces_and_delims(name_buf + name_tab[i].offset,
659 name_tab[i].length));
660 fd_cur->font_dim[FONTNAME_CODE].set = true;
661 break;
664 if (!fd_cur->font_dim[FONTNAME_CODE].set) {
665 for (i = 0; i < name_record_num; i++) {
666 if (name_tab[i].platform_id == 3 &&
667 (name_tab[i].encoding_id == 0 || name_tab[i].encoding_id == 1)
668 && name_tab[i].name_id == 6) {
669 xfree(fd_cur->fontname);
670 assert(name_tab[i].length < sizeof(buf));
671 for (j = 0, p = buf; j < name_tab[i].length; j += 2)
672 *p++ = name_buf[name_tab[i].offset + j + 1];
673 *p = 0;
674 fd_cur->fontname =
675 xstrdup(strip_spaces_and_delims(buf, (int) strlen(buf)));
676 fd_cur->font_dim[FONTNAME_CODE].set = true;
677 break;
683 static void ttf_read_mapx(void)
685 glyph_entry *glyph;
686 ttf_seek_tab("maxp", TTF_FIXED_SIZE);
687 glyph_tab =
688 xtalloc((unsigned) (1 + (glyphs_count = get_ushort())), glyph_entry);
689 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) {
690 glyph->newindex = -1;
691 glyph->newoffset = 0;
692 glyph->name_index = 0;
693 glyph->name = (char *) notdef;
695 glyph_index = xtalloc((unsigned) (glyphs_count + 1), long);
696 glyph_index[0] = 0; /* index of ".notdef" glyph */
697 glyph_index[1] = 1; /* index of ".null" glyph */
700 void ttf_read_head(void)
702 ttf_seek_tab("head",
703 2 * TTF_FIXED_SIZE + 2 * TTF_ULONG_SIZE + TTF_USHORT_SIZE);
704 upem = get_ushort();
705 ttf_skip(16);
706 fd_cur->font_dim[FONTBBOX1_CODE].val = (int) ttf_funit(get_fword());
707 fd_cur->font_dim[FONTBBOX2_CODE].val = (int) ttf_funit(get_fword());
708 fd_cur->font_dim[FONTBBOX3_CODE].val = (int) ttf_funit(get_fword());
709 fd_cur->font_dim[FONTBBOX4_CODE].val = (int) ttf_funit(get_fword());
710 fd_cur->font_dim[FONTBBOX1_CODE].set = true;
711 fd_cur->font_dim[FONTBBOX2_CODE].set = true;
712 fd_cur->font_dim[FONTBBOX3_CODE].set = true;
713 fd_cur->font_dim[FONTBBOX4_CODE].set = true;
714 ttf_skip(2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
715 loca_format = get_short();
718 void ttf_read_hhea(void)
720 ttf_seek_tab("hhea", TTF_FIXED_SIZE);
721 fd_cur->font_dim[ASCENT_CODE].val = (int) ttf_funit(get_fword());
722 fd_cur->font_dim[DESCENT_CODE].val = (int) ttf_funit(get_fword());
723 fd_cur->font_dim[ASCENT_CODE].set = true;
724 fd_cur->font_dim[DESCENT_CODE].set = true;
725 ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3 * TTF_FWORD_SIZE +
726 8 * TTF_SHORT_SIZE);
727 nhmtxs = get_ushort();
730 void ttf_read_pclt(void)
732 if (ttf_name_lookup("PCLT", false) == NULL)
733 return;
734 ttf_seek_tab("PCLT", TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE);
735 fd_cur->font_dim[XHEIGHT_CODE].val = (int) ttf_funit(get_ushort());
736 ttf_skip(2 * TTF_USHORT_SIZE);
737 fd_cur->font_dim[CAPHEIGHT_CODE].val = (int) ttf_funit(get_ushort());
738 fd_cur->font_dim[XHEIGHT_CODE].set = true;
739 fd_cur->font_dim[CAPHEIGHT_CODE].set = true;
742 static void ttf_read_hmtx(void)
744 glyph_entry *glyph;
745 TTF_UFWORD last_advWidth;
746 ttf_seek_tab("hmtx", 0);
747 for (glyph = glyph_tab; glyph - glyph_tab < nhmtxs; glyph++) {
748 glyph->advWidth = get_ufword();
749 glyph->lsb = (TTF_FWORD) get_ufword();
751 if (nhmtxs < glyphs_count) {
752 last_advWidth = glyph[-1].advWidth;
753 for (; glyph - glyph_tab < glyphs_count; glyph++) {
754 glyph->advWidth = last_advWidth;
755 glyph->lsb = (TTF_FWORD) get_ufword();
760 void ttf_read_post(void)
762 int k, nnames;
763 long length;
764 long int_part, frac_part;
765 int sign = 1;
766 TTF_FIXED italic_angle;
767 char *p;
768 glyph_entry *glyph;
769 const dirtab_entry *tab = ttf_seek_tab("post", 0);
770 post_format = get_fixed();
771 italic_angle = get_fixed();
772 int_part = (long) (italic_angle >> 16);
773 if (int_part > 0x7FFF) { /* a negative number */
774 int_part = 0x10000 - int_part;
775 sign = -1;
777 frac_part = (long) (italic_angle % 0x10000);
778 fd_cur->font_dim[ITALIC_ANGLE_CODE].val =
779 (int) (sign * ((double) int_part + (double) frac_part * 1.0 / 0x10000));
780 fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true;
781 if (glyph_tab == NULL)
782 return; /* being called from writeotf() */
783 ttf_skip(2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
784 switch (post_format) {
785 case 0x10000:
786 for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
787 glyph->name = (const char *) mac_glyph_names[glyph - glyph_tab];
788 glyph->name_index = (TTF_USHORT) (glyph - glyph_tab);
790 break;
791 case 0x20000:
792 nnames = get_ushort(); /* some fonts have this value different from nglyphs */
793 for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++)
794 glyph->name_index = get_ushort();
795 length =
796 (long) ((long) tab->length -
797 (long) ((long) ttf_curbyte - (long) tab->offset));
798 glyph_name_buf = xtalloc((unsigned) length, char);
799 for (p = glyph_name_buf; p - glyph_name_buf < length;) {
800 for (k = get_byte(); k > 0; k--)
801 *p++ = get_char();
802 *p++ = 0;
804 for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) {
805 if (glyph->name_index < NMACGLYPHS)
806 glyph->name = mac_glyph_names[glyph->name_index];
807 else {
808 p = glyph_name_buf;
809 k = glyph->name_index - NMACGLYPHS;
810 for (; k > 0; k--)
811 p = strend(p) + 1;
812 glyph->name = p;
815 break;
816 default:
817 formatted_warning("ttf font", "unsupported format '%.8X' of 'post' table, assuming 3.0", (unsigned int) post_format);
818 case 0x00030000:
819 for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
820 glyph->name_index = (TTF_USHORT) (glyph - glyph_tab);
825 static void ttf_read_loca(void)
827 glyph_entry *glyph;
828 ttf_seek_tab("loca", 0);
829 if (loca_format != 0)
830 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
831 glyph->offset = (TTF_LONG) get_ulong();
832 else
833 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
834 glyph->offset = get_ushort() << 1;
837 void otc_read_tabdir(int index)
839 unsigned long i, num, rem=0;
840 dirtab_entry *tab;
841 ttf_skip(TTF_FIXED_SIZE); /* ignore TTCTag 'ttcf' */
842 ttf_skip(TTF_ULONG_SIZE); /* ignorethe version number */
843 num = get_ulong();
844 for (i = 0; i < num; i++) {
845 if (i==index) rem = get_ulong(); else ttf_skip(TTF_ULONG_SIZE);
847 ttf_skip(rem - TTF_FIXED_SIZE - (num+2)*TTF_ULONG_SIZE);
848 ttf_skip(TTF_FIXED_SIZE); /* ignore the sfnt number */
849 dir_tab = xtalloc(ntabs = get_ushort(), dirtab_entry);
850 ttf_skip(3 * TTF_USHORT_SIZE);
851 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
852 for (i = 0; i < 4; i++)
853 tab->tag[i] = get_char();
854 tab->checksum = get_ulong();
855 tab->offset = get_ulong();
856 tab->length = get_ulong();
860 void ttf_read_tabdir(void)
862 int i;
863 dirtab_entry *tab;
864 ttf_skip(TTF_FIXED_SIZE); /* ignore the sfnt number */
865 dir_tab = xtalloc(ntabs = get_ushort(), dirtab_entry);
866 ttf_skip(3 * TTF_USHORT_SIZE);
867 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
868 for (i = 0; i < 4; i++)
869 tab->tag[i] = get_char();
870 tab->checksum = get_ulong();
871 tab->offset = get_ulong();
872 tab->length = get_ulong();
876 static ttf_cmap_entry *ttf_read_cmap(char *ttf_name, int pid, int eid,
877 boolean warn)
879 seg_entry *seg_tab, *s;
880 TTF_USHORT *glyphId, format, segCount;
881 TTF_USHORT ncmapsubtabs, tmp_pid, tmp_eid;
882 TTF_ULONG cmap_offset, tmp_offset;
883 long n, i, k, length, index;
884 ttf_cmap_entry tmp_e, *p;
885 void **aa;
887 /* look up in |ttf_cmap_tree| first, return if found */
888 tmp_e.ttf_name = ttf_name;
889 tmp_e.pid = (TTF_USHORT) pid;
890 tmp_e.eid = (TTF_USHORT) eid;
891 if (ttf_cmap_tree == NULL) {
892 ttf_cmap_tree = avl_create(comp_ttf_cmap_entry, NULL, &avl_xallocator);
893 assert(ttf_cmap_tree != NULL);
895 p = (ttf_cmap_entry *) avl_find(ttf_cmap_tree, &tmp_e);
896 if (p != NULL)
897 return p;
899 /* not found, have to read it */
900 ttf_seek_tab("cmap", TTF_USHORT_SIZE); /* skip the table version number (=0) */
901 ncmapsubtabs = get_ushort();
902 cmap_offset = (TTF_ULONG) (ttf_curbyte - 2 * TTF_USHORT_SIZE);
903 cmap_tab = xtalloc(ncmapsubtabs, cmap_entry);
904 for (i = 0; i < ncmapsubtabs; ++i) {
905 tmp_pid = get_ushort();
906 tmp_eid = get_ushort();
907 tmp_offset = get_ulong();
908 if (tmp_pid == pid && tmp_eid == eid) {
909 ttf_seek_off((TTF_LONG) (cmap_offset + tmp_offset));
910 format = get_ushort();
911 if (format == 4)
912 goto read_cmap_format_4;
913 else {
914 if (warn)
915 formatted_warning("ttf font", "cmap format %i unsupported", format);
916 return NULL;
920 if (warn)
921 formatted_warning("ttf font", "cannot find cmap subtable for (pid,eid) = (%i,%i)", pid, eid);
922 return NULL;
923 read_cmap_format_4:
924 /* initialize the new entry */
925 p = new_ttf_cmap_entry();
926 p->ttf_name = xstrdup(ttf_name);
927 p->pid = (TTF_USHORT) pid;
928 p->eid = (TTF_USHORT) eid;
929 p->table = xtalloc(0x10000, long);
930 for (i = 0; i < 0x10000; ++i)
931 p->table[i] = -1; /* unassigned yet */
933 /* read the subtable */
934 length = get_ushort(); /* length of subtable */
935 (void) get_ushort(); /* skip the version number */
936 segCount = get_ushort() / 2;
937 (void) get_ushort(); /* skip searchRange */
938 (void) get_ushort(); /* skip entrySelector */
939 (void) get_ushort(); /* skip rangeShift */
940 seg_tab = xtalloc(segCount, seg_entry);
941 for (s = seg_tab; s - seg_tab < segCount; s++)
942 s->endCode = get_ushort();
943 (void) get_ushort(); /* skip reversedPad */
944 for (s = seg_tab; s - seg_tab < segCount; s++)
945 s->startCode = get_ushort();
946 for (s = seg_tab; s - seg_tab < segCount; s++)
947 s->idDelta = get_ushort();
948 for (s = seg_tab; s - seg_tab < segCount; s++)
949 s->idRangeOffset = get_ushort();
950 length -= 8 * TTF_USHORT_SIZE + 4 * segCount * TTF_USHORT_SIZE;
951 n = length / TTF_USHORT_SIZE; /* number of glyphID's */
952 glyphId = xtalloc((unsigned) n, TTF_USHORT);
953 for (i = 0; i < n; i++)
954 glyphId[i] = get_ushort();
955 for (s = seg_tab; s - seg_tab < segCount; s++) {
956 for (i = s->startCode; i <= s->endCode; i++) {
957 if (i == 0xFFFF)
958 break;
959 if (s->idRangeOffset != 0xFFFF) {
960 if (s->idRangeOffset == 0)
961 index = (s->idDelta + i) & 0xFFFF;
962 else {
963 k = (i - s->startCode) + s->idRangeOffset / 2 +
964 (s - seg_tab) - segCount;
965 assert(k >= 0 && k < n);
966 index = glyphId[k];
967 if (index != 0)
968 index = (index + s->idDelta) & 0xFFFF;
970 if (index >= glyphs_count)
971 formatted_error("ttf font",
972 "cmap issue, glyph index %li out of range [0..%i)",
973 index, glyphs_count);
974 if (p->table[i] != -1)
975 formatted_warning("ttf font",
976 "cmap issue, multiple glyphs are mapped to unicode %.4lX, %li will be used, %li is ignored)",
977 i, p->table[i], index);
978 else
979 p->table[i] = index;
983 xfree(seg_tab);
984 xfree(glyphId);
985 aa = avl_probe(ttf_cmap_tree, p);
986 assert(aa != NULL);
987 return p;
992 static void ttf_read_font(void)
994 ttf_read_tabdir();
995 if (ttf_name_lookup("PCLT", false) == NULL)
996 new_ntabs--;
997 if (ttf_name_lookup("fpgm", false) == NULL)
998 new_ntabs--;
999 if (ttf_name_lookup("cvt ", false) == NULL)
1000 new_ntabs--;
1001 if (ttf_name_lookup("prep", false) == NULL)
1002 new_ntabs--;
1003 ttf_read_mapx();
1004 ttf_read_head();
1005 ttf_read_hhea();
1006 ttf_read_pclt();
1007 ttf_read_hmtx();
1008 ttf_read_post();
1009 ttf_read_loca();
1010 ttf_read_name();
1013 static void ttf_reset_chksm(PDF pdf, dirtab_entry * tab)
1015 checksum = 0;
1016 tab_length = 0;
1017 tmp_ulong = 0;
1018 tab->offset = (TTF_ULONG) ttf_offset();
1019 if (tab->offset % 4 != 0)
1020 formatted_warning("ttf font","offset of `%4.4s' is not a multiple of 4", tab->tag);
1024 static void ttf_set_chksm(PDF pdf, dirtab_entry * tab)
1026 tab->length = (TTF_ULONG) ttf_offset() - tab->offset;
1027 tab->checksum = ttf_getchksm(pdf);
1030 static void ttf_copytab(PDF pdf, const char *name)
1032 long i;
1033 dirtab_entry *tab = ttf_seek_tab(name, 0);
1034 ttf_reset_chksm(pdf, tab);
1035 for (i = (long) tab->length; i > 0; i--)
1036 copy_char();
1037 ttf_set_chksm(pdf, tab);
1042 #define BYTE_ENCODING_LENGTH \
1043 ((256)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE)
1045 static void ttf_byte_encoding(PDF pdf)
1047 ttfenc_entry *e;
1048 (void) put_ushort(0); /* format number (0: byte encoding table) */
1049 (void) put_ushort(BYTE_ENCODING_LENGTH); /* length of table */
1050 (void) put_ushort(0); /* version number */
1051 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
1052 if (e->newindex < 256) {
1053 put_byte(e->newindex);
1054 } else {
1055 if (e->name != notdef)
1056 formatted_warning("ttf font",
1057 "glyph '%s' has been mapped to '%s' in 'ttf_byte_encoding' cmap table",
1058 e->name, notdef);
1059 put_byte(0); /* notdef */
1065 #define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (256)))
1067 static void ttf_trimmed_table_map(PDF pdf)
1069 ttfenc_entry *e;
1070 (void) put_ushort(6); /* format number (6): trimmed table mapping */
1071 (void) put_ushort(TRIMMED_TABLE_MAP_LENGTH);
1072 (void) put_ushort(0); /* version number (0) */
1073 (void) put_ushort(0); /* first character code */
1074 (void) put_ushort(256); /* number of character code in table */
1075 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
1076 (void) put_ushort(e->newindex);
1081 #define SEG_MAP_DELTA_LENGTH ((16 + (256))*TTF_USHORT_SIZE)
1083 static void ttf_seg_map_delta(PDF pdf)
1085 ttfenc_entry *e;
1086 (void) put_ushort(4); /* format number (4: segment mapping to delta values) */
1087 (void) put_ushort(SEG_MAP_DELTA_LENGTH);
1088 (void) put_ushort(0); /* version number */
1089 (void) put_ushort(4); /* 2*segCount */
1090 (void) put_ushort(4); /* searchRange */
1091 (void) put_ushort(1); /* entrySelector */
1092 (void) put_ushort(0); /* rangeShift */
1093 (void) put_ushort(0xF0FF); /* endCount[0] */
1094 (void) put_ushort(0xFFFF); /* endCount[1] */
1095 (void) put_ushort(0); /* reversedPad */
1096 (void) put_ushort(0xF000); /* startCount[0] */
1097 (void) put_ushort(0xFFFF); /* startCount[1] */
1098 (void) put_ushort(0); /* idDelta[0] */
1099 (void) put_ushort(1); /* idDelta[1] */
1100 (void) put_ushort(2 * TTF_USHORT_SIZE); /* idRangeOffset[0] */
1101 (void) put_ushort(0); /* idRangeOffset[1] */
1102 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
1103 (void) put_ushort(e->newindex);
1108 #define CMAP_ENTRY_LENGTH (2*TTF_USHORT_SIZE + TTF_ULONG_SIZE)
1110 static void ttf_select_cmap(void)
1112 assert(sizeof(new_cmap_tab) <= NEW_CMAP_SIZE * sizeof(cmap_entry));
1113 new_cmap_tab[0].platform_id = 1; /* Macintosh */
1114 new_cmap_tab[0].encoding_id = 0; /* Symbol; ignore code page */
1115 new_cmap_tab[0].format = (TTF_USHORT) (new_glyphs_count < 256 ? 0 /* byte encoding */
1116 : 6); /* trimmed table mapping */
1117 new_cmap_tab[1].platform_id = 3; /* Microsoft */
1118 new_cmap_tab[1].encoding_id = 0; /* Symbol; ignore code page */
1119 new_cmap_tab[1].format = 4; /* segment mapping to delta */
1122 static void ttf_write_cmap(PDF pdf)
1124 cmap_entry *ce;
1125 long offset;
1126 dirtab_entry *tab = ttf_name_lookup("cmap", true);
1127 ttf_select_cmap();
1128 ttf_reset_chksm(pdf, tab);
1129 (void) put_ushort(0); /* table version number (0) */
1130 (void) put_ushort(NEW_CMAP_SIZE); /* number of encoding tables */
1131 offset = 2 * TTF_USHORT_SIZE + NEW_CMAP_SIZE * CMAP_ENTRY_LENGTH;
1132 for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
1133 ce->offset = (TTF_ULONG) offset;
1134 switch (ce->format) {
1135 case 0:
1136 offset += BYTE_ENCODING_LENGTH;
1137 break;
1138 case 4:
1139 offset += SEG_MAP_DELTA_LENGTH;
1140 break;
1141 case 6:
1142 offset += TRIMMED_TABLE_MAP_LENGTH;
1143 break;
1144 default:
1145 normal_error("ttf font","invalid format (it should not have happened)");
1147 (void) put_ushort(ce->platform_id);
1148 (void) put_ushort(ce->encoding_id);
1149 put_ulong((long) ce->offset);
1151 for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
1152 switch (ce->format) {
1153 case 0:
1154 ttf_byte_encoding(pdf);
1155 break;
1156 case 4:
1157 ttf_seg_map_delta(pdf);
1158 break;
1159 case 6:
1160 ttf_trimmed_table_map(pdf);
1161 break;
1164 ttf_set_chksm(pdf, tab);
1169 static int prepend_subset_tags(int index, char *p)
1171 boolean is_unicode;
1172 int i;
1173 assert(index >= 0 && index < name_record_num && fd_cur->subset_tag != NULL);
1174 is_unicode = (name_tab[index].platform_id == 3);
1175 if (is_unicode) {
1176 for (i = 0; i < 6; ++i) {
1177 *p++ = 0;
1178 *p++ = fd_cur->subset_tag[i];
1180 *p++ = 0;
1181 *p++ = '+';
1182 return 14;
1183 } else {
1184 strncpy(p, fd_cur->subset_tag, 6);
1185 p += 6;
1186 *p++ = '+';
1187 return 7;
1192 static void ttf_write_name(PDF pdf)
1194 int i, l;
1195 char *p;
1196 int new_name_buf_size;
1197 char *new_name_buf;
1198 name_record *n;
1199 dirtab_entry *tab = ttf_name_lookup("name", true);
1200 if (is_subsetted(fd_cur->fm)) {
1201 l = 0;
1202 for (i = 0; i < name_record_num; i++)
1203 l += name_tab[i].length + 14; /* maximum lengh of new stogare area */
1204 new_name_buf = xtalloc((unsigned) l, char);
1205 /* additional space for subset tags */
1206 p = new_name_buf;
1207 for (i = 0; i < name_record_num; i++) {
1208 n = name_tab + i;
1209 n->new_offset = (TTF_USHORT) (p - new_name_buf);
1210 if ((n->name_id == 1 || n->name_id == 3 ||
1211 n->name_id == 4 || n->name_id == 6) &&
1212 ((n->platform_id == 1 && n->encoding_id == 0) ||
1213 (n->platform_id == 3 && n->encoding_id == 0) ||
1214 (n->platform_id == 3 && n->encoding_id == 1))) {
1215 l = prepend_subset_tags(i, p);
1216 p += l;
1217 } else
1218 l = 0;
1219 memcpy(p, name_buf + n->offset, n->length);
1220 p += n->length;
1221 n->new_length = (TTF_USHORT) (n->length + l);
1223 new_name_buf_size = (int) (p - new_name_buf);
1224 } else {
1225 new_name_buf = name_buf;
1226 new_name_buf_size = name_buf_size;
1228 ttf_reset_chksm(pdf, tab);
1229 (void) put_ushort(0); /* Format selector */
1230 (void) put_ushort(name_record_num);
1231 (void) put_ushort(3 * TTF_USHORT_SIZE +
1232 name_record_num * 6 * TTF_USHORT_SIZE);
1233 for (i = 0; i < name_record_num; i++) {
1234 (void) put_ushort(name_tab[i].platform_id);
1235 (void) put_ushort(name_tab[i].encoding_id);
1236 (void) put_ushort(name_tab[i].language_id);
1237 (void) put_ushort(name_tab[i].name_id);
1238 (void) put_ushort(name_tab[i].new_length);
1239 (void) put_ushort(name_tab[i].new_offset);
1241 for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++)
1242 put_char(*p);
1243 ttf_set_chksm(pdf, tab);
1244 if (new_name_buf != name_buf)
1245 xfree(new_name_buf);
1250 static void ttf_write_dirtab(PDF pdf)
1252 dirtab_entry *tab;
1253 TTF_ULONG i, k;
1254 char *p;
1255 const int save_offset = ttf_offset();
1256 ttf_seek_outbuf(TABDIR_OFF);
1257 if (is_subsetted(fd_cur->fm)) {
1258 for (i = 0; i < DEFAULT_NTABS; i++) {
1259 tab = ttf_name_lookup(newtabnames[i], false);
1260 if (tab == NULL)
1261 continue;
1262 for (k = 0; k < 4; k++)
1263 put_char(tab->tag[k]);
1264 put_ulong((long) tab->checksum);
1265 put_ulong((long) tab->offset);
1266 put_ulong((long) tab->length);
1268 } else {
1269 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
1270 for (k = 0; k < 4; k++)
1271 put_char(tab->tag[k]);
1272 put_ulong((long) tab->checksum);
1273 put_ulong((long) tab->offset);
1274 put_ulong((long) tab->length);
1277 /* adjust checkSumAdjustment */
1278 tmp_ulong = 0;
1279 checksum = 0;
1280 for (p = (char *) pdf->fb->data, i = 0; i < (unsigned) save_offset;) {
1281 tmp_ulong = (tmp_ulong << 8) + (TTF_ULONG) * p++;
1282 i++;
1283 if (i % 4 == 0) {
1284 checksum += tmp_ulong;
1285 tmp_ulong = 0;
1288 if (i % 4 != 0) {
1289 formatted_warning("ttf font","font length '%li' is not a multiple of 4", i);
1290 checksum <<= 8 * (4 - i % 4);
1292 k = 0xB1B0AFBA - checksum;
1293 ttf_seek_outbuf((int) checkSumAdjustment_offset);
1294 put_ulong((long) k);
1295 ttf_seek_outbuf(save_offset);
1300 static void ttf_write_glyf(PDF pdf)
1302 long *id, k;
1303 TTF_USHORT idx;
1304 TTF_USHORT flags;
1305 dirtab_entry *tab = ttf_name_lookup("glyf", true);
1306 const long glyf_offset = (long) tab->offset;
1307 const long new_glyf_offset = ttf_offset();
1308 ttf_reset_chksm(pdf, tab);
1309 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1310 glyph_tab[*id].newoffset = ttf_offset() - new_glyf_offset;
1311 if (glyph_tab[*id].offset != glyph_tab[*id + 1].offset) {
1312 ttf_seek_off(glyf_offset + glyph_tab[*id].offset);
1313 k = copy_short();
1314 ttf_ncopy(pdf, 4 * TTF_FWORD_SIZE);
1315 if (k < 0) {
1316 do {
1317 flags = copy_ushort();
1318 idx = get_ushort();
1319 if (glyph_tab[idx].newindex < 0) {
1320 glyph_tab[idx].newindex = (TTF_SHORT) new_glyphs_count;
1321 glyph_index[new_glyphs_count++] = idx;
1323 N.B.: Here we change |new_glyphs_count|,
1324 which appears in the condition of the |for| loop
1327 (void) put_ushort(glyph_tab[idx].newindex);
1328 if (flags & ARG_1_AND_2_ARE_WORDS)
1329 ttf_ncopy(pdf, 2 * TTF_SHORT_SIZE);
1330 else
1331 ttf_ncopy(pdf, TTF_USHORT_SIZE);
1332 if (flags & WE_HAVE_A_SCALE)
1333 ttf_ncopy(pdf, TTF_F2DOT14_SIZE);
1334 else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
1335 ttf_ncopy(pdf, 2 * TTF_F2DOT14_SIZE);
1336 else if (flags & WE_HAVE_A_TWO_BY_TWO)
1337 ttf_ncopy(pdf, 4 * TTF_F2DOT14_SIZE);
1338 } while (flags & MORE_COMPONENTS);
1339 if (flags & WE_HAVE_INSTRUCTIONS)
1340 ttf_ncopy(pdf, copy_ushort());
1341 } else
1342 ttf_ncopy(pdf, (int)
1343 (glyph_tab[*id + 1].offset - glyph_tab[*id].offset -
1344 TTF_USHORT_SIZE - 4 * TTF_FWORD_SIZE));
1347 last_glyf_offset = (TTF_ULONG) ttf_offset() - (TTF_ULONG) new_glyf_offset;
1348 ttf_set_chksm(pdf, tab);
1351 @ Reindexing glyphs: we append index of used glyphs to |glyph_index|
1352 while going through |ttfenc_tab|. After appending a new entry to
1353 |glyph_index| we set field |newindex| of corresponding entries in both
1354 |glyph_tab| and |ttfenc_tab| to the newly created index.
1357 static void ttf_reindex_glyphs(void)
1359 ttfenc_entry *e;
1360 glyph_entry *glyph;
1361 int index;
1362 long *t;
1363 ttf_cmap_entry *cmap = NULL;
1364 boolean cmap_not_found = false;
1366 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) {
1367 e->newindex = 0; /* index of ".notdef" glyph */
1369 /* handle case of subfonts first */
1370 if (is_subfont(fd_cur->fm)) {
1371 if (e->code == -1)
1372 continue;
1373 assert(fd_cur->fm->pid != -1 && fd_cur->fm->eid != -1);
1374 if (cmap == NULL && !cmap_not_found) {
1375 cmap =
1376 ttf_read_cmap(fd_cur->fm->ff_name, fd_cur->fm->pid,
1377 fd_cur->fm->eid, true);
1378 if (cmap == NULL)
1379 cmap_not_found = true;
1381 if (cmap == NULL)
1382 continue;
1383 t = cmap->table;
1384 assert(t != NULL && e->code < 0x10000);
1385 if (t[e->code] < 0) {
1386 formatted_warning("ttf font",
1387 "subfont %s has a wrong mapping, character %li -> 0x%4.4lX -> .notdef",
1388 fd_cur->fm->tfm_name, (long) (e - ttfenc_tab), e->code);
1389 continue;
1391 assert(t[e->code] >= 0 && t[e->code] < glyphs_count); /* t has been read from ttf */
1392 glyph = glyph_tab + t[e->code];
1393 goto append_new_glyph;
1396 /* handle case of reencoded fonts */
1397 if (e->name == notdef)
1398 continue;
1399 /* scan form `index123' */
1400 if (sscanf(e->name, GLYPH_PREFIX_INDEX "%i", &index) == 1) {
1401 if (index >= glyphs_count) {
1402 formatted_warning("ttf font","'%s' out of valid range [0..%i)", e->name, glyphs_count);
1403 continue;
1405 glyph = glyph_tab + index;
1406 goto append_new_glyph;
1408 /* scan form `uniABCD' */
1409 if (sscanf(e->name, GLYPH_PREFIX_UNICODE "%X", &index) == 1) {
1410 if (cmap == NULL && !cmap_not_found) {
1411 /* need to read the unicode mapping, ie (pid,eid) = (3,1) or (0,3) */
1412 cmap = ttf_read_cmap(fd_cur->fm->ff_name, 3, 1, false);
1413 if (cmap == NULL)
1414 cmap = ttf_read_cmap(fd_cur->fm->ff_name, 0, 3, false);
1415 if (cmap == NULL) {
1416 normal_warning("ttf font", "no unicode mapping found, all 'uniXXXX' names will be ignored");
1417 cmap_not_found = true; /* once only */
1420 if (cmap == NULL)
1421 continue;
1422 t = cmap->table;
1423 assert(t != NULL);
1424 if (t[index] != -1) {
1425 if (t[index] >= glyphs_count) {
1426 formatted_warning("ttf font", "'%s' is mapped to index %li which is out of valid range [0..%i)",
1427 e->name, t[index], glyphs_count);
1428 continue;
1430 glyph = glyph_tab + t[index];
1431 goto append_new_glyph;
1432 } else {
1433 formatted_warning("ttf font","unicode %s%.4X is not mapped to any glyph", GLYPH_PREFIX_UNICODE, index);
1434 continue;
1437 /* look up by name */
1438 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++)
1439 if (glyph->name != notdef && strcmp(glyph->name, e->name) == 0)
1440 break;
1441 if (!(glyph - glyph_tab < glyphs_count)) {
1442 formatted_warning("ttf font","glyph '%s' not found", e->name);
1443 continue;
1445 append_new_glyph:
1446 assert(glyph > glyph_tab && glyph - glyph_tab < glyphs_count);
1447 if (glyph->newindex < 0) {
1448 glyph_index[new_glyphs_count] = (short) (glyph - glyph_tab);
1449 glyph->newindex = (TTF_SHORT) new_glyphs_count;
1450 new_glyphs_count++;
1452 e->newindex = glyph->newindex;
1456 @ To calculate the checkSum for the 'head' table which itself includes the
1457 checkSumAdjustment entry for the entire font, do the following:
1459 \item Set the checkSumAdjustment to 0.
1460 \item Calculate the checksum for all the tables including the 'head' table
1461 and enter that value into the table directory.
1462 \item Calculate the checksum for the entire font.
1463 \item Subtract that value from the hex value B1B0AFBA.
1464 \item Store the result in checkSumAdjustment.
1466 The checkSum for the 'head table which includes the checkSumAdjustment
1467 entry for the entire font is now incorrect. That is not a problem. Do not
1468 change it. An application attempting to verify that the 'head' table has
1469 not changed should calculate the checkSum for that table by not including
1470 the checkSumAdjustment value, and compare the result with the entry in the
1471 table directory.
1473 The table directory also includes the offset of the associated tagged
1474 table from the beginning of the font file and the length of that table.
1478 static void ttf_write_head(PDF pdf)
1480 dirtab_entry *tab;
1481 tab = ttf_seek_tab("head", 0);
1482 ttf_reset_chksm(pdf, tab);
1483 ttf_ncopy(pdf, 2 * TTF_FIXED_SIZE);
1484 checkSumAdjustment_offset = (TTF_ULONG) ttf_offset();
1485 put_ulong(0);
1486 ttf_skip(TTF_ULONG_SIZE); /* skip checkSumAdjustment */
1487 ttf_ncopy(pdf, TTF_ULONG_SIZE + 2 * TTF_USHORT_SIZE + 16 +
1488 4 * TTF_FWORD_SIZE + 2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
1489 if (is_subsetted(fd_cur->fm)) {
1490 (void) put_short(loca_format);
1491 (void) put_short(0);
1492 } else
1493 ttf_ncopy(pdf, 2 * TTF_SHORT_SIZE);
1494 ttf_set_chksm(pdf, tab);
1499 static void ttf_write_hhea(PDF pdf)
1501 dirtab_entry *tab;
1502 tab = ttf_seek_tab("hhea", 0);
1503 ttf_reset_chksm(pdf, tab);
1504 ttf_ncopy(pdf, TTF_FIXED_SIZE + 3 * TTF_FWORD_SIZE + TTF_UFWORD_SIZE +
1505 3 * TTF_FWORD_SIZE + 8 * TTF_SHORT_SIZE);
1506 (void) put_ushort(new_glyphs_count);
1507 ttf_set_chksm(pdf, tab);
1512 static void ttf_write_htmx(PDF pdf)
1514 long *id;
1515 dirtab_entry *tab = ttf_seek_tab("hmtx", 0);
1516 ttf_reset_chksm(pdf, tab);
1517 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1518 put_ufword(glyph_tab[*id].advWidth);
1519 put_ufword(glyph_tab[*id].lsb);
1521 ttf_set_chksm(pdf, tab);
1526 static void ttf_write_loca(PDF pdf)
1528 long *id;
1529 dirtab_entry *tab = ttf_seek_tab("loca", 0);
1530 ttf_reset_chksm(pdf, tab);
1531 loca_format = 0;
1532 if (last_glyf_offset >= 0x00020000 || (last_glyf_offset & 1))
1533 loca_format = 1;
1534 else
1535 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
1536 if (glyph_tab[*id].newoffset & 1) {
1537 loca_format = 1;
1538 break;
1540 if (loca_format != 0) {
1541 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
1542 put_ulong(glyph_tab[*id].newoffset);
1543 put_ulong((long) last_glyf_offset);
1544 } else {
1545 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
1546 (void) put_ushort(glyph_tab[*id].newoffset / 2);
1547 (void) put_ushort((long) (last_glyf_offset / 2));
1549 ttf_set_chksm(pdf, tab);
1554 static void ttf_write_mapx(PDF pdf)
1556 dirtab_entry *tab = ttf_seek_tab("maxp", TTF_FIXED_SIZE + TTF_USHORT_SIZE);
1557 ttf_reset_chksm(pdf, tab);
1558 put_fixed(0x00010000);
1559 (void) put_ushort(new_glyphs_count);
1560 ttf_ncopy(pdf, 13 * TTF_USHORT_SIZE);
1561 ttf_set_chksm(pdf, tab);
1566 static void ttf_write_OS2(PDF pdf)
1568 dirtab_entry *tab = ttf_seek_tab("OS/2", 0);
1569 TTF_USHORT version;
1570 ttf_reset_chksm(pdf, tab);
1571 version = get_ushort();
1572 if (version > 3)
1573 formatted_error("ttf font","unknown version '%.4X' of OS/2 table", version);
1574 (void) put_ushort(0x0001); /* fix version to 1 */
1575 ttf_ncopy(pdf,
1576 2 * TTF_USHORT_SIZE + 13 * TTF_SHORT_SIZE + 10 * TTF_BYTE_SIZE);
1577 ttf_skip(4 * TTF_ULONG_SIZE); /* ulUnicodeRange 1--4 */
1578 put_ulong(0x00000003); /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */
1579 put_ulong(0x10000000); /* Private Use (0xE000--0xF8FF) */
1580 put_ulong(0x00000000);
1581 put_ulong(0x00000000);
1582 ttf_ncopy(pdf, 4 * TTF_CHAR_SIZE + TTF_USHORT_SIZE); /* achVendID + fsSelection */
1583 ttf_skip(2 * TTF_USHORT_SIZE);
1584 (void) put_ushort(0x0000); /* usFirstCharIndex */
1585 (void) put_ushort(0xF0FF); /* usLastCharIndex */
1586 ttf_ncopy(pdf, 5 * TTF_USHORT_SIZE);
1587 /* for version 0 the OS/2 table ends here, the rest is for version 1 */
1588 put_ulong(0x80000000); /* Symbol Character Set---don't use any code page */
1589 put_ulong(0x00000000);
1590 ttf_set_chksm(pdf, tab);
1595 static boolean unsafe_name(const char *s)
1597 const char **p;
1598 for (p = ambiguous_names; *p != NULL; p++)
1599 if (strcmp(s, *p) == 0)
1600 return true;
1601 return false;
1604 static void ttf_write_post(PDF pdf)
1606 dirtab_entry *tab = ttf_seek_tab("post", TTF_FIXED_SIZE);
1607 glyph_entry *glyph;
1608 const char *s;
1609 long *id;
1610 int k, l;
1611 ttf_reset_chksm(pdf, tab);
1612 if (!fd_cur->write_ttf_glyph_names || post_format == 0x00030000) {
1613 put_fixed(0x00030000);
1614 ttf_ncopy(pdf,
1615 TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
1616 } else {
1617 put_fixed(0x00020000);
1618 ttf_ncopy(pdf,
1619 TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
1620 (void) put_ushort(new_glyphs_count);
1621 k = 0;
1622 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1623 glyph = glyph_tab + *id;
1624 if (glyph->name_index >= NMACGLYPHS || unsafe_name(glyph->name))
1625 glyph->name_index = (TTF_USHORT) (NMACGLYPHS + k++);
1626 (void) put_ushort(glyph->name_index);
1628 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1629 glyph = glyph_tab + *id;
1630 if (glyph->name_index >= NMACGLYPHS) {
1631 s = glyph->name;
1632 l = (int) strlen(s);
1633 put_byte(l);
1634 while (l-- > 0)
1635 put_char(*s++);
1639 ttf_set_chksm(pdf, tab);
1644 static void ttf_init_font(PDF pdf, int n)
1646 int i, k;
1647 for (i = 1, k = 0; i <= n; i <<= 1, k++);
1648 put_fixed(0x00010000); /* font version */
1649 (void) put_ushort(n); /* number of tables */
1650 (void) put_ushort(i << 3); /* search range */
1651 (void) put_ushort(k - 1); /* entry selector */
1652 (void) put_ushort((n << 4) - (i << 3)); /* range shift */
1653 ttf_seek_outbuf(TABDIR_OFF + n * 4 * TTF_ULONG_SIZE);
1658 static void ttf_subset_font(PDF pdf)
1660 ttf_init_font(pdf, new_ntabs);
1661 if (ttf_name_lookup("PCLT", false) != NULL)
1662 ttf_copytab(pdf, "PCLT");
1663 if (ttf_name_lookup("fpgm", false) != NULL)
1664 ttf_copytab(pdf, "fpgm");
1665 if (ttf_name_lookup("cvt ", false) != NULL)
1666 ttf_copytab(pdf, "cvt ");
1667 if (ttf_name_lookup("prep", false) != NULL)
1668 ttf_copytab(pdf, "prep");
1669 ttf_reindex_glyphs();
1670 ttf_write_glyf(pdf);
1671 ttf_write_loca(pdf);
1672 ttf_write_OS2(pdf);
1673 ttf_write_head(pdf);
1674 ttf_write_hhea(pdf);
1675 ttf_write_htmx(pdf);
1676 ttf_write_mapx(pdf);
1677 ttf_write_name(pdf);
1678 ttf_write_post(pdf);
1679 ttf_write_cmap(pdf);
1680 ttf_write_dirtab(pdf);
1685 static void ttf_copy_font(PDF pdf)
1687 dirtab_entry *tab;
1688 ttf_init_font(pdf, ntabs);
1689 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
1690 if (strncmp(tab->tag, "head", 4) == 0)
1691 ttf_write_head(pdf);
1692 else
1693 ttf_copytab(pdf, tab->tag);
1695 ttf_write_dirtab(pdf);
1700 void writettf(PDF pdf, fd_entry * fd)
1702 int callback_id;
1703 int file_opened = 0;
1704 fd_cur = fd; /* |fd_cur| is global inside \.{writettf.w} */
1705 assert(fd_cur->fm != NULL);
1706 assert(is_truetype(fd_cur->fm));
1707 assert(is_included(fd_cur->fm));
1709 if (is_subsetted(fd_cur->fm) && (fd_cur->fe == NULL) && !is_subfont(fd_cur->fm)) {
1710 normal_error("ttf font","subset must be a reencoded or a subfont");
1712 ttf_curbyte = 0;
1713 ttf_size = 0;
1715 cur_file_name =
1716 luatex_find_file(fd_cur->fm->ff_name, find_truetype_file_callback);
1717 if (cur_file_name == NULL) {
1718 formatted_error("ttf font","cannot find font file for reading '%s'", fd_cur->fm->ff_name);
1720 callback_id = callback_defined(read_truetype_file_callback);
1721 if (callback_id > 0) {
1722 if (run_callback(callback_id, "S->bSd", cur_file_name,
1723 &file_opened, &ttf_buffer, &ttf_size) &&
1724 file_opened && ttf_size > 0) {
1725 } else {
1726 formatted_error("ttf font","cannot open font file for reading '%s'", cur_file_name);
1728 } else {
1729 if (!ttf_open(cur_file_name)) {
1730 formatted_error("ttf font","cannot open font file for reading '%s'", cur_file_name);
1732 ttf_read_file();
1733 ttf_close();
1735 if (tracefilenames) {
1736 if (is_subsetted(fd_cur->fm))
1737 tex_printf("<%s", cur_file_name);
1738 else
1739 tex_printf("<<%s", cur_file_name);
1741 fd_cur->ff_found = true;
1742 new_glyphs_count = 2;
1743 new_ntabs = DEFAULT_NTABS;
1744 dir_tab = NULL;
1745 glyph_tab = NULL;
1746 glyph_index = NULL;
1747 glyph_name_buf = NULL;
1748 name_tab = NULL;
1749 name_buf = NULL;
1750 ttf_read_font();
1752 pdf_save_offset(pdf);
1753 pdf_flush(pdf);
1755 if (is_subsetted(fd_cur->fm)) {
1756 ttf_copy_encoding();
1757 ttf_subset_font(pdf);
1758 } else
1759 ttf_copy_font(pdf);
1760 ttf_length = ttf_offset();
1762 xfree(dir_tab);
1763 xfree(glyph_tab);
1764 xfree(glyph_index);
1765 xfree(glyph_name_buf);
1766 xfree(name_tab);
1767 xfree(name_buf);
1768 if (tracefilenames) {
1769 if (is_subsetted(fd_cur->fm))
1770 tex_printf(">");
1771 else
1772 tex_printf(">>");
1774 xfree(ttf_buffer);
1775 cur_file_name = NULL;
1778 static void do_writeotf(PDF pdf, fd_entry * fd)
1780 long i;
1781 dirtab_entry *tab;
1782 (void) fd;
1783 dir_tab = NULL;
1784 glyph_tab = NULL;
1785 if (tracefilenames)
1786 tex_printf("<<%s", cur_file_name);
1787 ttf_read_tabdir();
1788 /* read font parameters */
1789 if (ttf_name_lookup("head", false) != NULL)
1790 ttf_read_head();
1791 if (ttf_name_lookup("hhea", false) != NULL)
1792 ttf_read_hhea();
1793 if (ttf_name_lookup("PCLT", false) != NULL)
1794 ttf_read_pclt();
1795 if (ttf_name_lookup("post", false) != NULL)
1796 ttf_read_post();
1797 /* copy font file */
1798 tab = ttf_seek_tab("CFF ", 0);
1799 for (i = (long) tab->length; i > 0; i--)
1800 copy_char();
1801 xfree(dir_tab);
1802 if (tracefilenames)
1803 tex_printf(">>");
1808 void writeotf(PDF pdf, fd_entry * fd)
1810 int callback_id;
1811 int file_opened = 0;
1813 fd_cur = fd;
1814 assert(fd_cur->fm != NULL);
1815 assert(is_opentype(fd_cur->fm));
1816 assert(is_included(fd_cur->fm));
1818 ttf_curbyte = 0;
1819 ttf_size = 0;
1820 cur_file_name =
1821 luatex_find_file(fd_cur->fm->ff_name, find_opentype_file_callback);
1822 if (cur_file_name == NULL) {
1823 formatted_error("otf font","cannot find font file for reading '%s'", fd_cur->fm->ff_name);
1825 callback_id = callback_defined(read_opentype_file_callback);
1826 if (callback_id > 0) {
1827 if (run_callback(callback_id, "S->bSd", cur_file_name,
1828 &file_opened, &ttf_buffer, &ttf_size) &&
1829 file_opened && ttf_size > 0) {
1830 } else {
1831 formatted_error("otf font","cannot open font file for reading '%s'", cur_file_name);
1833 } else {
1834 if (!otf_open(cur_file_name)) {
1835 formatted_error("otf font","cannot open font file for reading '%s'", cur_file_name);
1837 ttf_read_file();
1838 ttf_close();
1841 fd_cur->ff_found = true;
1842 do_writeotf(pdf, fd);
1843 xfree(ttf_buffer);
1844 cur_file_name = NULL;