diff options
Diffstat (limited to 'Build/source/texk/web2c/pdftexdir/writettf.c')
-rw-r--r-- | Build/source/texk/web2c/pdftexdir/writettf.c | 913 |
1 files changed, 550 insertions, 363 deletions
diff --git a/Build/source/texk/web2c/pdftexdir/writettf.c b/Build/source/texk/web2c/pdftexdir/writettf.c index e2d0d1641d6..4c33f568434 100644 --- a/Build/source/texk/web2c/pdftexdir/writettf.c +++ b/Build/source/texk/web2c/pdftexdir/writettf.c @@ -1,5 +1,5 @@ /* -Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org> +Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org> This file is part of pdfTeX. @@ -22,9 +22,7 @@ $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writettf.c#16 $ #include "ptexlib.h" #include "writettf.h" - -static const char perforce_id[] = - "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writettf.c#16 $"; +#include <string.h> #define DEFAULT_NTABS 14 #define NEW_CMAP_SIZE 2 @@ -46,14 +44,16 @@ typedef struct { TTF_LONG newoffset; TTF_UFWORD advWidth; TTF_FWORD lsb; - char *name; /* name of glyph */ - TTF_SHORT newindex; /* new index of glyph in output file */ - TTF_USHORT name_index; /* index of name as read from font file */ + char *name; /* name of glyph */ + TTF_SHORT newindex; /* new index of glyph in output file */ + TTF_USHORT name_index; /* index of name as read from font file */ } glyph_entry; typedef struct { - char *name; /* name of glyph */ - short newindex; /* new index of glyph in output file */ + char *name; /* name of glyph */ + long code; /* charcode in case of subfonts */ + short newindex; /* new index of glyph in output file */ + } ttfenc_entry; typedef struct { @@ -67,6 +67,13 @@ typedef struct { TTF_USHORT new_length; } name_record; +typedef struct { + char *ttf_name; + TTF_USHORT pid; + TTF_USHORT eid; + short *table; +} ttf_cmap_entry; + static TTF_USHORT ntabs; static TTF_USHORT upem; static TTF_FIXED post_format; @@ -78,7 +85,7 @@ static TTF_USHORT nhmtxs; static TTF_USHORT new_ntabs; static glyph_entry *glyph_tab; -static short *glyph_index; +static long *glyph_index; static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE]; static name_record *name_tab; static int name_record_num; @@ -91,16 +98,18 @@ static TTF_ULONG tab_length; static TTF_ULONG tmp_ulong; static TTF_ULONG checkSumAdjustment_offset; static FILE *ttf_file; -static ttfenc_entry ttfenc_tab[MAX_CHAR_CODE + 1]; +static ttfenc_entry ttfenc_tab[256]; -static TTF_USHORT unicode_map[0xFFFF]; +static fd_entry *fd_cur; /* pointer to the current font descriptor */ +static struct avl_table *ttf_cmap_tree = NULL; integer ttf_length; #include "macnames.c" extern char *fb_array; +extern char charsetstr[]; static const char *newtabnames[] = { "OS/2", @@ -119,6 +128,43 @@ static const char *newtabnames[] = { "prep" }; +ttf_cmap_entry *new_ttf_cmap_entry(void) +{ + ttf_cmap_entry *e; + e = xtalloc(1, ttf_cmap_entry); + e->ttf_name = NULL; + e->table = NULL; + return e; +} + +static void destroy_ttf_cmap_entry(void *pa, void *pb) +{ + ttf_cmap_entry *p; + p = (ttf_cmap_entry *) pa; + xfree(p->ttf_name); + xfree(p->table); + xfree(p); +} + +void ttf_free(void) +{ + if (ttf_cmap_tree != NULL) + avl_destroy(ttf_cmap_tree, destroy_ttf_cmap_entry); +} + +static int comp_ttf_cmap_entry(const void *pa, const void *pb, void *p) +{ + const ttf_cmap_entry *p1 = (const ttf_cmap_entry *) pa, + *p2 = (const ttf_cmap_entry *) pb; + int i; + assert(p1->ttf_name != NULL && p2->ttf_name != NULL); + if ((i = strcmp(p1->ttf_name, p2->ttf_name)) != 0) + return i; + cmp_return(p1->pid, p2->pid); + cmp_return(p1->eid, p2->eid); + return 0; +} + static unsigned char ttf_addchksm(unsigned char b) { tmp_ulong = (tmp_ulong << 8) + b; @@ -133,7 +179,7 @@ static unsigned char ttf_addchksm(unsigned char b) static TTF_ULONG ttf_getchksm(void) { while (tab_length % 4 != 0) - ttf_putchar(ttf_addchksm(0)); /* ttf_addchksm updates tab_length */ + ttf_putchar(ttf_addchksm(0)); /* ttf_addchksm updates tab_length */ return checksum; } @@ -167,9 +213,9 @@ static long ttf_getnum(int s) static long ttf_funit(long n) { if (n < 0) - return -((-n/upem)*1000 + ((-n%upem)*1000)/upem); + return -((-n / upem) * 1000 + ((-n % upem) * 1000) / upem); else - return (n/upem)*1000 + ((n%upem)*1000)/upem; + return (n / upem) * 1000 + ((n % upem) * 1000) / upem; } static void ttf_ncopy(int n) @@ -207,16 +253,66 @@ static void ttf_seek_off(TTF_LONG offset) static void ttf_copy_encoding(void) { - int i; - char **glyph_names = (fm_cur->encoding)->glyph_names; + int i, *q; + void **aa; + char **glyph_names; + long *charcodes; + static char buf[SMALL_BUF_SIZE]; + struct avl_traverser t; ttfenc_entry *e = ttfenc_tab; - pdfmarkchar(tex_font, 'a'); /* workaround for a bug of AcroReader 4.0 */ - for (i = 0; i <= MAX_CHAR_CODE; i++, e++) { - if (pdfcharmarked(tex_font, i)) - e->name = glyph_names[i]; - else - e->name = (char*) notdef; - } + + assert(fd_cur->tx_tree != NULL); /* this must be set in create_fontdictionary */ + + if (fd_cur->fe != NULL) { + glyph_names = fd_cur->fe->glyph_names; + assert(glyph_names != NULL); + + for (i = 0; i < 256; i++) + ttfenc_tab[i].name = (char *) notdef; + + /* a workaround for a bug of AcroReader 4.0 */ + if (strcmp(glyph_names[97], "a") == 0) { + q = xtalloc(1, int); + *q = 'a'; + aa = avl_probe(fd_cur->tx_tree, q); + assert(aa != NULL); + } + /* end of workaround */ + + /* take over collected characters from TeX, reencode them */ + avl_t_init(&t, fd_cur->tx_tree); + for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL; + q = (int *) avl_t_next(&t)) { + assert(*q >= 0 && *q < 256); + ttfenc_tab[*q].name = glyph_names[*q]; + } + make_subset_tag(fd_cur); + } else if (is_subfont(fd_cur->fm)) { + charcodes = fd_cur->fm->subfont->charcodes; + assert(charcodes != NULL); + + for (i = 0; i < 256; i++) + ttfenc_tab[i].code = -1; + + /* take over collected characters from TeX */ + avl_t_init(&t, fd_cur->tx_tree); + for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL; + q = (int *) avl_t_next(&t)) { + assert(*q >= 0 && *q < 256); + e = ttfenc_tab + *q; + e->code = charcodes[*q]; + if (e->code == -1) + pdftex_warn("character %i is not mapped to any charcode", *q); + else { + assert(e->code < 0x10000); + sprintf(buf, "/c%4.4X", (int) e->code); + aa = avl_probe(fd_cur->gl_tree, xstrdup(buf)); + assert(aa != NULL); + } + } + make_subset_tag(fd_cur); + } else + assert(0); } #define ttf_append_byte(B)\ @@ -226,6 +322,24 @@ do {\ *q++ = B;\ } while (0) +static char *strip_spaces_and_delims(char *s, int l) +{ + static char buf[SMALL_BUF_SIZE]; + assert(l >= 0 && l < (int) sizeof(buf)); + char *p = buf; + int i; + + for (i = 0; i < l; s++, i++) { + if (*s == '(' || *s == ')' || *s == '<' || *s == '>' || + *s == '[' || *s == ']' || *s == '{' || *s == '}' || + *s == '/' || *s == '%' || isspace(*s)) + continue; + *p++ = *s; + } + *p = 0; + return buf; +} + static void ttf_read_name(void) { int i, j; @@ -233,8 +347,8 @@ static void ttf_read_name(void) char *p; name_record_num = get_ushort(); name_tab = xtalloc(name_record_num, name_record); - name_buf_size = tab->length - - (3*TTF_USHORT_SIZE + name_record_num*6*TTF_USHORT_SIZE); + name_buf_size = tab->length - + (3 * TTF_USHORT_SIZE + name_record_num * 6 * TTF_USHORT_SIZE); name_buf = xtalloc(name_buf_size, char); ttf_skip(TTF_USHORT_SIZE); for (i = 0; i < name_record_num; i++) { @@ -246,28 +360,29 @@ static void ttf_read_name(void) name_tab[i].offset = get_ushort(); } for (p = name_buf; p - name_buf < name_buf_size; p++) - *p = get_char(); + *p = get_char(); /* look for PS font name */ for (i = 0; i < name_record_num; i++) { - if (name_tab[i].platform_id == 1 && - name_tab[i].encoding_id == 0 && - name_tab[i].name_id == 6) { - strncpy(fontname_buf, name_buf + name_tab[i].offset, name_tab[i].length); - fontname_buf[name_tab[i].length] = 0; - font_keys[FONTNAME_CODE].valid = true; + if (name_tab[i].platform_id == 1 && + name_tab[i].encoding_id == 0 && name_tab[i].name_id == 6) { + xfree(fd_cur->fontname); + fd_cur->fontname = + xstrdup(strip_spaces_and_delims(name_buf + name_tab[i].offset, + name_tab[i].length)); + fd_cur->font_dim[FONTNAME_CODE].set = true; break; } } - if (!font_keys[FONTNAME_CODE].valid) { + if (!fd_cur->font_dim[FONTNAME_CODE].set) { for (i = 0; i < name_record_num; i++) { - if (name_tab[i].platform_id == 3 && - (name_tab[i].encoding_id == 0 || - name_tab[i].encoding_id == 1) && - name_tab[i].name_id == 6) { - for (j = 0, p = fontname_buf; j < name_tab[i].length; j += 2) + if (name_tab[i].platform_id == 3 && + (name_tab[i].encoding_id == 0 || + name_tab[i].encoding_id == 1) && name_tab[i].name_id == 6) { + for (j = 0, p = fd_cur->fontname; j < name_tab[i].length; + j += 2) *p++ = name_buf[name_tab[i].offset + j + 1]; *p = 0; - font_keys[FONTNAME_CODE].valid = true; + fd_cur->font_dim[FONTNAME_CODE].set = true; break; } } @@ -276,7 +391,6 @@ static void ttf_read_name(void) static void ttf_read_mapx(void) { - int i; glyph_entry *glyph; ttf_seek_tab("maxp", TTF_FIXED_SIZE); glyph_tab = xtalloc(1 + (glyphs_count = get_ushort()), glyph_entry); @@ -284,38 +398,40 @@ static void ttf_read_mapx(void) glyph->newindex = -1; glyph->newoffset = 0; glyph->name_index = 0; - glyph->name = (char*) notdef; + glyph->name = (char *) notdef; } - glyph_index = xtalloc(glyphs_count, short); - glyph_index[0] = 0; /* index of ".notdef" glyph */ - glyph_index[1] = 1; /* index of ".null" glyph */ + glyph_index = xtalloc(glyphs_count, long); + glyph_index[0] = 0; /* index of ".notdef" glyph */ + glyph_index[1] = 1; /* index of ".null" glyph */ } static void ttf_read_head(void) { - ttf_seek_tab("head", 2*TTF_FIXED_SIZE + 2*TTF_ULONG_SIZE + TTF_USHORT_SIZE); + ttf_seek_tab("head", + 2 * TTF_FIXED_SIZE + 2 * TTF_ULONG_SIZE + TTF_USHORT_SIZE); upem = get_ushort(); ttf_skip(16); - font_keys[FONTBBOX1_CODE].value = ttf_funit(get_fword()); - font_keys[FONTBBOX2_CODE].value = ttf_funit(get_fword()); - font_keys[FONTBBOX3_CODE].value = ttf_funit(get_fword()); - font_keys[FONTBBOX4_CODE].value = ttf_funit(get_fword()); - font_keys[FONTBBOX1_CODE].valid = true; - font_keys[FONTBBOX2_CODE].valid = true; - font_keys[FONTBBOX3_CODE].valid = true; - font_keys[FONTBBOX4_CODE].valid = true; - ttf_skip(2*TTF_USHORT_SIZE + TTF_SHORT_SIZE); + fd_cur->font_dim[FONTBBOX1_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[FONTBBOX2_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[FONTBBOX3_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[FONTBBOX4_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[FONTBBOX1_CODE].set = true; + fd_cur->font_dim[FONTBBOX2_CODE].set = true; + fd_cur->font_dim[FONTBBOX3_CODE].set = true; + fd_cur->font_dim[FONTBBOX4_CODE].set = true; + ttf_skip(2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE); loca_format = get_short(); } static void ttf_read_hhea(void) { ttf_seek_tab("hhea", TTF_FIXED_SIZE); - font_keys[ASCENT_CODE].value = ttf_funit(get_fword()); - font_keys[DESCENT_CODE].value = ttf_funit(get_fword()); - font_keys[ASCENT_CODE].valid = true; - font_keys[DESCENT_CODE].valid = true; - ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3*TTF_FWORD_SIZE + 8*TTF_SHORT_SIZE); + fd_cur->font_dim[ASCENT_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[DESCENT_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[ASCENT_CODE].set = true; + fd_cur->font_dim[DESCENT_CODE].set = true; + ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3 * TTF_FWORD_SIZE + + 8 * TTF_SHORT_SIZE); nhmtxs = get_ushort(); } @@ -324,11 +440,11 @@ static void ttf_read_pclt(void) if (ttf_name_lookup("PCLT", false) == NULL) return; ttf_seek_tab("PCLT", TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE); - font_keys[XHEIGHT_CODE].value = ttf_funit(get_ushort()); - ttf_skip(2*TTF_USHORT_SIZE); - font_keys[CAPHEIGHT_CODE].value = ttf_funit(get_ushort()); - font_keys[XHEIGHT_CODE].valid = true; - font_keys[CAPHEIGHT_CODE].valid = true; + fd_cur->font_dim[XHEIGHT_CODE].val = ttf_funit(get_ushort()); + ttf_skip(2 * TTF_USHORT_SIZE); + fd_cur->font_dim[CAPHEIGHT_CODE].val = ttf_funit(get_ushort()); + fd_cur->font_dim[XHEIGHT_CODE].set = true; + fd_cur->font_dim[CAPHEIGHT_CODE].set = true; } static void ttf_read_hmtx(void) @@ -342,7 +458,7 @@ static void ttf_read_hmtx(void) } if (nhmtxs < glyphs_count) { last_advWidth = glyph[-1].advWidth; - for (;glyph - glyph_tab < glyphs_count; glyph++) { + for (; glyph - glyph_tab < glyphs_count; glyph++) { glyph->advWidth = last_advWidth; glyph->lsb = get_ufword(); } @@ -358,29 +474,30 @@ static void ttf_read_post(void) TTF_FIXED italic_angle; char *p; glyph_entry *glyph; - dirtab_entry *tab = ttf_seek_tab("post", 0); + const dirtab_entry *tab = ttf_seek_tab("post", 0); post_format = get_fixed(); italic_angle = get_fixed(); int_part = italic_angle >> 16; - if (int_part > 0x7FFF) { /* a negative number */ + if (int_part > 0x7FFF) { /* a negative number */ int_part = 0x10000 - int_part; sign = -1; } frac_part = italic_angle % 0x10000; - font_keys[ITALIC_ANGLE_CODE].value = sign*(int_part + frac_part*1.0/0x10000); - font_keys[ITALIC_ANGLE_CODE].valid = true; + fd_cur->font_dim[ITALIC_ANGLE_CODE].val = + sign * (int_part + frac_part * 1.0 / 0x10000); + fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true; if (glyph_tab == NULL) - return; /* being called from writeotf() */ - ttf_skip(2*TTF_FWORD_SIZE + 5*TTF_ULONG_SIZE); + return; /* being called from writeotf() */ + ttf_skip(2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE); switch (post_format) { case 0x10000: for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) { - glyph->name = (char*)mac_glyph_names[glyph - glyph_tab]; + glyph->name = (char *) mac_glyph_names[glyph - glyph_tab]; glyph->name_index = glyph - glyph_tab; } break; case 0x20000: - nnames = get_ushort(); /* some fonts have this value different from nglyphs */ + nnames = get_ushort(); /* some fonts have this value different from nglyphs */ for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) glyph->name_index = get_ushort(); length = tab->length - (xftell(INFILE, cur_file_name) - tab->offset); @@ -392,7 +509,7 @@ static void ttf_read_post(void) } for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) { if (glyph->name_index < NMACGLYPHS) - glyph->name = (char*)mac_glyph_names[glyph->name_index]; + glyph->name = (char *) mac_glyph_names[glyph->name_index]; else { p = glyph_name_buf; k = glyph->name_index - NMACGLYPHS; @@ -408,7 +525,8 @@ static void ttf_read_post(void) } break; default: - pdftex_fail("unsupported format (%.8X) of `post' table", (unsigned int) post_format); + pdftex_fail("unsupported format (%.8X) of `post' table", + (unsigned int) post_format); } } @@ -428,11 +546,9 @@ static void ttf_read_tabdir() { int i; dirtab_entry *tab; -/* if ((version= get_fixed()) != 0x00010000) */ -/* pdftex_fail("unsupport version 0x%.8X; can handle only version 1.0", (int)version); */ - ttf_skip(TTF_FIXED_SIZE); /* ignore the sfnt number */ + ttf_skip(TTF_FIXED_SIZE); /* ignore the sfnt number */ dir_tab = xtalloc(ntabs = get_ushort(), dirtab_entry); - ttf_skip(3*TTF_USHORT_SIZE); + ttf_skip(3 * TTF_USHORT_SIZE); for (tab = dir_tab; tab - dir_tab < ntabs; tab++) { for (i = 0; i < 4; i++) tab->tag[i] = get_char(); @@ -442,93 +558,119 @@ static void ttf_read_tabdir() } } -static void ttf_read_cmap(void) +static ttf_cmap_entry *ttf_read_cmap(char *ttf_name, int pid, int eid, + boolean warn) { - cmap_entry *e; seg_entry *seg_tab, *s; TTF_USHORT *glyphId, format, segCount; - TTF_USHORT ncmapsubtabs; - long cmap_offset; - long int n, i, j, k, first_code, length, last_sep, index; - int unicode_map_count = 0; - int select_unicode = 1; /* may be changed later if needed */ - ttf_seek_tab("cmap", TTF_USHORT_SIZE); /* skip the table vesrion number (=0) */ + TTF_USHORT ncmapsubtabs, tmp_pid, tmp_eid; + TTF_ULONG cmap_offset, tmp_offset; + long n, i, k, length, index; + ttf_cmap_entry tmp_e, *p; + void **aa; + + /* loop up in ttf_cmap_tree first, return if found */ + tmp_e.ttf_name = ttf_name; + tmp_e.pid = pid; + tmp_e.eid = eid; + if (ttf_cmap_tree == NULL) { + ttf_cmap_tree = avl_create(comp_ttf_cmap_entry, NULL, &avl_xallocator); + assert(ttf_cmap_tree != NULL); + } + p = (ttf_cmap_entry *) avl_find(ttf_cmap_tree, &tmp_e); + if (p != NULL) + return p; + + /* not found, have to read it */ + ttf_seek_tab("cmap", TTF_USHORT_SIZE); /* skip the table vesrion number (=0) */ ncmapsubtabs = get_ushort(); - cmap_offset = xftell(INFILE, cur_file_name) - 2*TTF_USHORT_SIZE; + cmap_offset = xftell(INFILE, cur_file_name) - 2 * TTF_USHORT_SIZE; cmap_tab = xtalloc(ncmapsubtabs, cmap_entry); - for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) { - e->platform_id = get_ushort(); - e->encoding_id = get_ushort(); - e->offset = get_ulong(); - } - for (i = 0; i < 0xFFFF; ++i) - unicode_map[i] = NOGLYPH_ASSIGNED_YET; - for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) { - ttf_seek_off(cmap_offset + e->offset); - format = get_ushort(); - if (is_unicode_mapping(e) && format == 4) { - ++unicode_map_count; - if (unicode_map_count == select_unicode) - goto read_unicode_mapping; + for (i = 0; i < ncmapsubtabs; ++i) { + tmp_pid = get_ushort(); + tmp_eid = get_ushort(); + tmp_offset = get_ulong(); + if (tmp_pid == pid && tmp_eid == eid) { + ttf_seek_off(cmap_offset + tmp_offset); + format = get_ushort(); + if (format == 4) + goto read_cmap_format_4; + else { + if (warn) + pdftex_warn("cmap format %i unsupported", format); + return NULL; + } } - continue; -read_unicode_mapping: - length = get_ushort(); /* length of subtable */ - get_ushort(); /* skip the version number */ - segCount = get_ushort()/2; - get_ushort(); /* skip searchRange */ - get_ushort(); /* skip entrySelector */ - get_ushort(); /* skip rangeShift */ - seg_tab = xtalloc(segCount, seg_entry); - for (s = seg_tab; s - seg_tab < segCount; s++) - s->endCode = get_ushort(); - get_ushort(); /* skip reversedPad */ - for (s = seg_tab; s - seg_tab < segCount; s++) - s->startCode = get_ushort(); - for (s = seg_tab; s - seg_tab < segCount; s++) - s->idDelta = get_ushort(); - for (s = seg_tab; s - seg_tab < segCount; s++) - s->idRangeOffset = get_ushort(); - length -= 8*TTF_USHORT_SIZE + 4*segCount*TTF_USHORT_SIZE; - n = length/TTF_USHORT_SIZE; /* number of glyphID's */ - glyphId = xtalloc(n, TTF_USHORT); - for (i = 0; i < n; i++) - glyphId[i] = get_ushort(); - for (s = seg_tab; s - seg_tab < segCount; s++) { - for (i = s->startCode; i <= s->endCode; i++) { - if (i == 0xFFFF) - break; - if (s->idRangeOffset != 0xFFFF) { - if (s->idRangeOffset == 0) - index = (s->idDelta + i) & 0xFFFF; - else { - k = (i - s->startCode) + s->idRangeOffset/2 + - (s - seg_tab) - segCount ; - assert(k >= 0 && k < n); - index = glyphId[k]; - if (index != 0) - index = (index + s->idDelta) & 0xFFFF; - } - if (index >= glyphs_count) - pdftex_fail("cmap: glyph index %i out of range [0..%i)", - index, glyphs_count); - if (unicode_map[i] != NOGLYPH_ASSIGNED_YET) - pdftex_warn("cmap: multiple glyphs are mapped to unicode %.4X, " - "only %i will be used (glyph %i being ignored)", - i, unicode_map[i], index); - else - unicode_map[i] = index; + } + if (warn) + pdftex_warn("cannot find cmap subtable for (pid,eid) = (%i, %i)", + pid, eid); + return NULL; + read_cmap_format_4: + /* initialize the new entry */ + p = new_ttf_cmap_entry(); + p->ttf_name = xstrdup(ttf_name); + p->pid = pid; + p->eid = eid; + p->table = xtalloc(0x10000, short); + for (i = 0; i < 0x10000; ++i) + p->table[i] = -1; /* unassigned yet */ + + /* read the subtable */ + length = get_ushort(); /* length of subtable */ + (void) get_ushort(); /* skip the version number */ + segCount = get_ushort() / 2; + (void) get_ushort(); /* skip searchRange */ + (void) get_ushort(); /* skip entrySelector */ + (void) get_ushort(); /* skip rangeShift */ + seg_tab = xtalloc(segCount, seg_entry); + for (s = seg_tab; s - seg_tab < segCount; s++) + s->endCode = get_ushort(); + (void) get_ushort(); /* skip reversedPad */ + for (s = seg_tab; s - seg_tab < segCount; s++) + s->startCode = get_ushort(); + for (s = seg_tab; s - seg_tab < segCount; s++) + s->idDelta = get_ushort(); + for (s = seg_tab; s - seg_tab < segCount; s++) + s->idRangeOffset = get_ushort(); + length -= 8 * TTF_USHORT_SIZE + 4 * segCount * TTF_USHORT_SIZE; + n = length / TTF_USHORT_SIZE; /* number of glyphID's */ + glyphId = xtalloc(n, TTF_USHORT); + for (i = 0; i < n; i++) + glyphId[i] = get_ushort(); + for (s = seg_tab; s - seg_tab < segCount; s++) { + for (i = s->startCode; i <= s->endCode; i++) { + if (i == 0xFFFF) + break; + if (s->idRangeOffset != 0xFFFF) { + if (s->idRangeOffset == 0) + index = (s->idDelta + i) & 0xFFFF; + else { + k = (i - s->startCode) + s->idRangeOffset / 2 + + (s - seg_tab) - segCount; + assert(k >= 0 && k < n); + index = glyphId[k]; + if (index != 0) + index = (index + s->idDelta) & 0xFFFF; } + if (index >= glyphs_count) + pdftex_fail("cmap: glyph index %li out of range [0..%i)", + index, glyphs_count); + if (p->table[i] != -1) + pdftex_warn + ("cmap: multiple glyphs are mapped to unicode %.4lX, " + "only %i will be used (glyph %li being ignored)", i, + p->table[i], index); + else + p->table[i] = index; } } - xfree(seg_tab); - xfree(glyphId); - break; } - if (e - cmap_tab == ncmapsubtabs) - pdftex_fail("Invalid argument `-m %i': out of range [1..%i]", - select_unicode, unicode_map_count); - xfree(cmap_tab); + xfree(seg_tab); + xfree(glyphId); + aa = avl_probe(ttf_cmap_tree, p); + assert(aa != NULL); + return p; } static void ttf_read_font(void) @@ -550,10 +692,9 @@ static void ttf_read_font(void) ttf_read_post(); ttf_read_loca(); ttf_read_name(); - ttf_read_cmap(); } -static void ttf_reset_chksm(dirtab_entry *tab) +static void ttf_reset_chksm(dirtab_entry * tab) { checksum = 0; tab_length = 0; @@ -564,7 +705,7 @@ static void ttf_reset_chksm(dirtab_entry *tab) } -static void ttf_set_chksm(dirtab_entry *tab) +static void ttf_set_chksm(dirtab_entry * tab) { tab->length = ttf_offset() - tab->offset; tab->checksum = ttf_getchksm(); @@ -581,77 +722,77 @@ static void ttf_copytab(const char *name) } #define BYTE_ENCODING_LENGTH \ - ((MAX_CHAR_CODE + 1)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE) + ((256)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE) static void ttf_byte_encoding(void) { ttfenc_entry *e; - put_ushort(0); /* format number (0: byte encoding table) */ - put_ushort(BYTE_ENCODING_LENGTH); /* length of table */ - put_ushort(0); /* version number */ - for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++) + (void) put_ushort(0); /* format number (0: byte encoding table) */ + (void) put_ushort(BYTE_ENCODING_LENGTH); /* length of table */ + (void) put_ushort(0); /* version number */ + for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) if (e->newindex < 256) { put_byte(e->newindex); - } - else { + } else { if (e->name != notdef) - pdftex_warn("glyph `%s' has been mapped to `%s' in `ttf_byte_encoding' cmap table", - e->name, notdef); - put_byte(0); /* notdef */ + pdftex_warn + ("glyph `%s' has been mapped to `%s' in `ttf_byte_encoding' cmap table", + e->name, notdef); + put_byte(0); /* notdef */ } } -#define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (MAX_CHAR_CODE + 1))) +#define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (256))) static void ttf_trimmed_table_map(void) { ttfenc_entry *e; - put_ushort(6); /* format number (6): trimmed table mapping */ - put_ushort(TRIMMED_TABLE_MAP_LENGTH); - put_ushort(0); /* version number (0) */ - put_ushort(0); /* first character code */ - put_ushort(MAX_CHAR_CODE + 1); /* number of character code in table */ - for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++) - put_ushort(e->newindex); + (void) put_ushort(6); /* format number (6): trimmed table mapping */ + (void) put_ushort(TRIMMED_TABLE_MAP_LENGTH); + (void) put_ushort(0); /* version number (0) */ + (void) put_ushort(0); /* first character code */ + (void) put_ushort(256); /* number of character code in table */ + for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) + (void) put_ushort(e->newindex); } -#define SEG_MAP_DELTA_LENGTH ((16 + (MAX_CHAR_CODE + 1))*TTF_USHORT_SIZE) +#define SEG_MAP_DELTA_LENGTH ((16 + (256))*TTF_USHORT_SIZE) static void ttf_seg_map_delta(void) { ttfenc_entry *e; - put_ushort(4); /* format number (4: segment mapping to delta values) */ - put_ushort(SEG_MAP_DELTA_LENGTH); - put_ushort(0); /* version number */ - put_ushort(4); /* 2*segCount */ - put_ushort(4); /* searchRange */ - put_ushort(1); /* entrySelector */ - put_ushort(0); /* rangeShift */ - put_ushort(0xF0FF); /* endCount[0] */ - put_ushort(0xFFFF); /* endCount[1] */ - put_ushort(0); /* reversedPad */ - put_ushort(0xF000); /* startCount[0] */ - put_ushort(0xFFFF); /* startCount[1] */ - put_ushort(0); /* idDelta[0] */ - put_ushort(1); /* idDelta[1] */ - put_ushort(2*TTF_USHORT_SIZE); /* idRangeOffset[0] */ - put_ushort(0); /* idRangeOffset[1] */ - for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++) - put_ushort(e->newindex); + (void) put_ushort(4); /* format number (4: segment mapping to delta values) */ + (void) put_ushort(SEG_MAP_DELTA_LENGTH); + (void) put_ushort(0); /* version number */ + (void) put_ushort(4); /* 2*segCount */ + (void) put_ushort(4); /* searchRange */ + (void) put_ushort(1); /* entrySelector */ + (void) put_ushort(0); /* rangeShift */ + (void) put_ushort(0xF0FF); /* endCount[0] */ + (void) put_ushort(0xFFFF); /* endCount[1] */ + (void) put_ushort(0); /* reversedPad */ + (void) put_ushort(0xF000); /* startCount[0] */ + (void) put_ushort(0xFFFF); /* startCount[1] */ + (void) put_ushort(0); /* idDelta[0] */ + (void) put_ushort(1); /* idDelta[1] */ + (void) put_ushort(2 * TTF_USHORT_SIZE); /* idRangeOffset[0] */ + (void) put_ushort(0); /* idRangeOffset[1] */ + for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) + (void) put_ushort(e->newindex); } #define CMAP_ENTRY_LENGTH (2*TTF_USHORT_SIZE + TTF_ULONG_SIZE) static void ttf_select_cmap(void) { - assert(sizeof(new_cmap_tab) <= NEW_CMAP_SIZE*sizeof(cmap_entry)); - new_cmap_tab[0].platform_id = 1; /* Macintosh */ - new_cmap_tab[0].encoding_id = 0; /* Symbol; ignore code page */ - new_cmap_tab[0].format = new_glyphs_count < 256 ? 0 /* byte encoding */ - : 6; /* trimmed table mapping */ - new_cmap_tab[1].platform_id = 3; /* Microsoft */ - new_cmap_tab[1].encoding_id = 0; /* Symbol; ignore code page */ - new_cmap_tab[1].format = 4; /* segment mapping to delta */ + assert(sizeof(new_cmap_tab) <= NEW_CMAP_SIZE * sizeof(cmap_entry)); + new_cmap_tab[0].platform_id = 1; /* Macintosh */ + new_cmap_tab[0].encoding_id = 0; /* Symbol; ignore code page */ + new_cmap_tab[0].format = new_glyphs_count < 256 ? 0 /* byte encoding */ + : 6; /* trimmed table mapping */ + new_cmap_tab[1].platform_id = 3; /* Microsoft */ + new_cmap_tab[1].encoding_id = 0; /* Symbol; ignore code page */ + new_cmap_tab[1].format = 4; /* segment mapping to delta */ } static void ttf_write_cmap(void) @@ -661,37 +802,37 @@ static void ttf_write_cmap(void) dirtab_entry *tab = ttf_name_lookup("cmap", true); ttf_select_cmap(); ttf_reset_chksm(tab); - put_ushort(0); /* table version number (0) */ - put_ushort(NEW_CMAP_SIZE); /* number of encoding tables */ - offset = 2*TTF_USHORT_SIZE + NEW_CMAP_SIZE*CMAP_ENTRY_LENGTH; + (void) put_ushort(0); /* table version number (0) */ + (void) put_ushort(NEW_CMAP_SIZE); /* number of encoding tables */ + offset = 2 * TTF_USHORT_SIZE + NEW_CMAP_SIZE * CMAP_ENTRY_LENGTH; for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) { ce->offset = offset; switch (ce->format) { - case 0: - offset += BYTE_ENCODING_LENGTH; + case 0: + offset += BYTE_ENCODING_LENGTH; break; - case 4: - offset += SEG_MAP_DELTA_LENGTH; + case 4: + offset += SEG_MAP_DELTA_LENGTH; break; - case 6: - offset += TRIMMED_TABLE_MAP_LENGTH; + case 6: + offset += TRIMMED_TABLE_MAP_LENGTH; break; default: pdftex_fail("invalid format (it should not have happened)"); } - put_ushort(ce->platform_id); - put_ushort(ce->encoding_id); + (void) put_ushort(ce->platform_id); + (void) put_ushort(ce->encoding_id); put_ulong(ce->offset); } for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) { switch (ce->format) { - case 0: + case 0: ttf_byte_encoding(); break; - case 4: + case 4: ttf_seg_map_delta(); break; - case 6: + case 6: ttf_trimmed_table_map(); break; } @@ -701,19 +842,19 @@ static void ttf_write_cmap(void) static int prepend_subset_tags(int index, char *p) { - boolean is_unicode = (name_tab[index].platform_id == 3); + const boolean is_unicode = (name_tab[index].platform_id == 3); int i; - assert(index > 0 && index < name_record_num && fm_cur->subset_tag != NULL); + assert(index > 0 && index < name_record_num && fd_cur->subset_tag != NULL); if (is_unicode) { for (i = 0; i < 6; ++i) { *p++ = 0; - *p++ = fm_cur->subset_tag[i]; + *p++ = fd_cur->subset_tag[i]; } *p++ = 0; *p++ = '+'; return 14; } else { - strncpy(p, fm_cur->subset_tag, 6); + strncpy(p, fd_cur->subset_tag, 6); p += 6; *p++ = '+'; return 7; @@ -729,10 +870,10 @@ static void ttf_write_name(void) char *new_name_buf; name_record *n; dirtab_entry *tab = ttf_name_lookup("name", true); - if (is_subsetted(fm_cur)) { + if (is_subsetted(fd_cur->fm)) { l = 0; for (i = 0; i < name_record_num; i++) - l += name_tab[i].length + 14; /* maximum lengh of new stogare area */ + l += name_tab[i].length + 14; /* maximum lengh of new stogare area */ new_name_buf = xtalloc(l, char); /* additional space for subset tags */ p = new_name_buf; @@ -743,37 +884,35 @@ static void ttf_write_name(void) n->name_id == 4 || n->name_id == 6) && ((n->platform_id == 1 && n->encoding_id == 0) || (n->platform_id == 3 && n->encoding_id == 0) || - (n->platform_id == 3 && n->encoding_id == 1))) - { + (n->platform_id == 3 && n->encoding_id == 1))) { l = prepend_subset_tags(i, p); p += l; - } - else + } else l = 0; memcpy(p, name_buf + n->offset, n->length); p += n->length; n->new_length = n->length + l; } new_name_buf_size = p - new_name_buf; - } - else { + } else { new_name_buf = name_buf; new_name_buf_size = name_buf_size; } ttf_reset_chksm(tab); - put_ushort(0); /* Format selector */ - put_ushort(name_record_num); - put_ushort(3*TTF_USHORT_SIZE + name_record_num*6*TTF_USHORT_SIZE); + (void) put_ushort(0); /* Format selector */ + (void) put_ushort(name_record_num); + (void) put_ushort(3 * TTF_USHORT_SIZE + + name_record_num * 6 * TTF_USHORT_SIZE); for (i = 0; i < name_record_num; i++) { - put_ushort(name_tab[i].platform_id); - put_ushort(name_tab[i].encoding_id); - put_ushort(name_tab[i].language_id); - put_ushort(name_tab[i].name_id); - put_ushort(name_tab[i].new_length); - put_ushort(name_tab[i].new_offset); + (void) put_ushort(name_tab[i].platform_id); + (void) put_ushort(name_tab[i].encoding_id); + (void) put_ushort(name_tab[i].language_id); + (void) put_ushort(name_tab[i].name_id); + (void) put_ushort(name_tab[i].new_length); + (void) put_ushort(name_tab[i].new_offset); } for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++) - put_char(*p); + put_char(*p); ttf_set_chksm(tab); if (new_name_buf != name_buf) xfree(new_name_buf); @@ -784,24 +923,23 @@ static void ttf_write_dirtab(void) dirtab_entry *tab; TTF_ULONG i, k; char *p; - integer save_offset = ttf_offset(); + const integer save_offset = ttf_offset(); ttf_seek_outbuf(TABDIR_OFF); - if (is_subsetted(fm_cur)) { + if (is_subsetted(fd_cur->fm)) { for (i = 0; i < DEFAULT_NTABS; i++) { tab = ttf_name_lookup(newtabnames[i], false); if (tab == NULL) continue; for (k = 0; k < 4; k++) - put_char(tab->tag[k]); + put_char(tab->tag[k]); put_ulong(tab->checksum); put_ulong(tab->offset); put_ulong(tab->length); } - } - else { + } else { for (tab = dir_tab; tab - dir_tab < ntabs; tab++) { for (k = 0; k < 4; k++) - put_char(tab->tag[k]); + put_char(tab->tag[k]); put_ulong(tab->checksum); put_ulong(tab->offset); put_ulong(tab->length); @@ -810,7 +948,7 @@ static void ttf_write_dirtab(void) /* adjust checkSumAdjustment */ tmp_ulong = 0; checksum = 0; - for (p = fb_array, i = 0; i < save_offset;) { + for (p = fb_array, i = 0; i < (unsigned) save_offset;) { tmp_ulong = (tmp_ulong << 8) + *p++; i++; if (i % 4 == 0) { @@ -820,7 +958,7 @@ static void ttf_write_dirtab(void) } if (i % 4 != 0) { pdftex_warn("font length is not a multiple of 4 (%li)", i); - checksum <<= 8*(4 - i % 4); + checksum <<= 8 * (4 - i % 4); } k = 0xB1B0AFBA - checksum; ttf_seek_outbuf(checkSumAdjustment_offset); @@ -830,19 +968,19 @@ static void ttf_write_dirtab(void) static void ttf_write_glyf(void) { - short *id, k; + long *id, k; TTF_USHORT idx; TTF_USHORT flags; dirtab_entry *tab = ttf_name_lookup("glyf", true); - long glyf_offset = tab->offset; - long new_glyf_offset = ttf_offset(); + const long glyf_offset = tab->offset; + const long new_glyf_offset = ttf_offset(); ttf_reset_chksm(tab); for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) { glyph_tab[*id].newoffset = ttf_offset() - new_glyf_offset; if (glyph_tab[*id].offset != glyph_tab[*id + 1].offset) { ttf_seek_off(glyf_offset + glyph_tab[*id].offset); k = copy_short(); - ttf_ncopy(4*TTF_FWORD_SIZE); + ttf_ncopy(4 * TTF_FWORD_SIZE); if (k < 0) { do { flags = copy_ushort(); @@ -850,29 +988,28 @@ static void ttf_write_glyf(void) if (glyph_tab[idx].newindex < 0) { glyph_tab[idx].newindex = new_glyphs_count; glyph_index[new_glyphs_count++] = idx; - /* - N.B.: Here we change `new_glyphs_count', - which appears in the condition of the `for' loop - */ + /* + N.B.: Here we change `new_glyphs_count', + which appears in the condition of the `for' loop + */ } - put_ushort(glyph_tab[idx].newindex); + (void) put_ushort(glyph_tab[idx].newindex); if (flags & ARG_1_AND_2_ARE_WORDS) - ttf_ncopy(2*TTF_SHORT_SIZE); + ttf_ncopy(2 * TTF_SHORT_SIZE); else ttf_ncopy(TTF_USHORT_SIZE); if (flags & WE_HAVE_A_SCALE) ttf_ncopy(TTF_F2DOT14_SIZE); else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) - ttf_ncopy(2*TTF_F2DOT14_SIZE); + ttf_ncopy(2 * TTF_F2DOT14_SIZE); else if (flags & WE_HAVE_A_TWO_BY_TWO) - ttf_ncopy(4*TTF_F2DOT14_SIZE); + ttf_ncopy(4 * TTF_F2DOT14_SIZE); } while (flags & MORE_COMPONENTS); if (flags & WE_HAVE_INSTRUCTIONS) ttf_ncopy(copy_ushort()); - } - else - ttf_ncopy(glyph_tab[*id + 1].offset - glyph_tab[*id].offset - - TTF_USHORT_SIZE - 4*TTF_FWORD_SIZE); + } else + ttf_ncopy(glyph_tab[*id + 1].offset - glyph_tab[*id].offset - + TTF_USHORT_SIZE - 4 * TTF_FWORD_SIZE); } } last_glyf_offset = ttf_offset() - new_glyf_offset; @@ -883,20 +1020,52 @@ static void ttf_reindex_glyphs(void) { ttfenc_entry *e; glyph_entry *glyph; - unsigned int index; - /* + int index; + short *t; + ttf_cmap_entry *cmap = NULL; + boolean cmap_not_found = false; + + /* * reindexing glyphs: we append index of used glyphs to `glyph_index' * while going through `ttfenc_tab'. After appending a new entry to * `glyph_index' we set field `newindex' of corresponding entries in both * `glyph_tab' and `ttfenc_tab' to the newly created index - * */ - for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++) { - e->newindex = 0; /* index of ".notdef" glyph */ + for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) { + e->newindex = 0; /* index of ".notdef" glyph */ + + /* handle case of subfonts first */ + if (is_subfont(fd_cur->fm)) { + if (e->code == -1) + continue; + assert(fd_cur->fm->pid != -1 && fd_cur->fm->eid != -1); + if (cmap == NULL && !cmap_not_found) { + cmap = + ttf_read_cmap(fd_cur->fm->ff_name, fd_cur->fm->pid, + fd_cur->fm->eid, true); + if (cmap == NULL) + cmap_not_found = true; + } + if (cmap == NULL) + continue; + t = cmap->table; + assert(t != NULL && e->code < 0x10000); + if (t[e->code] < 0) { + pdftex_warn + ("subfont %s: wrong mapping: character %li --> 0x%4.4lX --> .notdef", + fd_cur->fm->tfm_name, (long) (e - ttfenc_tab), e->code); + continue; + } + assert(t[e->code] >= 0 && t[e->code] < glyphs_count); /* t has been read from ttf */ + glyph = glyph_tab + t[e->code]; + goto append_new_glyph; + } + + /* handle case of reencoded fonts */ if (e->name == notdef) continue; /* scan form `index123' */ - if (sscanf(e->name, GLYPH_PREFIX_INDEX "%i", &index) == 1) { + if (sscanf(e->name, GLYPH_PREFIX_INDEX "%i", &index) == 1) { if (index >= glyphs_count) { pdftex_warn("`%s' out of valid range [0..%i)", e->name, glyphs_count); @@ -907,18 +1076,32 @@ static void ttf_reindex_glyphs(void) } /* scan form `uniABCD' */ if (sscanf(e->name, GLYPH_PREFIX_UNICODE "%X", &index) == 1) { - assert(index <= 0xFFFF); - if (unicode_map[index] != NOGLYPH_ASSIGNED_YET) { - if (unicode_map[index] >= glyphs_count) { - pdftex_warn("`%s' is mapped to index %i which is out of valid range [0..%i)", - e->name, unicode_map[index], glyphs_count); + if (cmap == NULL && !cmap_not_found) { + /* need to read the unicode mapping, ie (pid,eid) = (3,1) or (0,3) */ + cmap = ttf_read_cmap(fd_cur->fm->ff_name, 3, 1, false); + if (cmap == NULL) + cmap = ttf_read_cmap(fd_cur->fm->ff_name, 0, 3, false); + if (cmap == NULL) { + pdftex_warn + ("no unicode mapping found, all `uniXXXX' names will be ignored"); + cmap_not_found = true; /* once only */ + } + } + if (cmap == NULL) + continue; + t = cmap->table; + assert(t != NULL); + if (t[index] != -1) { + if (t[index] >= glyphs_count) { + pdftex_warn + ("`%s' is mapped to index %i which is out of valid range [0..%i)", + e->name, t[index], glyphs_count); continue; } - glyph = glyph_tab + unicode_map[index]; + glyph = glyph_tab + t[index]; goto append_new_glyph; - } - else { - pdftex_warn("`unicode %s%.4X' is not mapped to any glyph", + } else { + pdftex_warn("`unicode %s%.4X' is not mapped to any glyph", GLYPH_PREFIX_UNICODE, index); continue; } @@ -931,8 +1114,8 @@ static void ttf_reindex_glyphs(void) pdftex_warn("glyph `%s' not found", e->name); continue; } -append_new_glyph: - assert(glyph - glyph_tab < glyphs_count); + append_new_glyph: + assert(glyph > glyph_tab && glyph - glyph_tab < glyphs_count); if (glyph->newindex < 0) { glyph_index[new_glyphs_count] = glyph - glyph_tab; glyph->newindex = new_glyphs_count; @@ -941,40 +1124,40 @@ append_new_glyph: e->newindex = glyph->newindex; } } - + static void ttf_write_head() { dirtab_entry *tab; tab = ttf_seek_tab("head", 0); ttf_reset_chksm(tab); - ttf_ncopy(2*TTF_FIXED_SIZE); + ttf_ncopy(2 * TTF_FIXED_SIZE); checkSumAdjustment_offset = ttf_offset(); put_ulong(0); - ttf_skip(TTF_ULONG_SIZE); /* skip checkSumAdjustment */ - ttf_ncopy(TTF_ULONG_SIZE + 2*TTF_USHORT_SIZE + 16 + - 4*TTF_FWORD_SIZE + 2*TTF_USHORT_SIZE + TTF_SHORT_SIZE); - if (is_subsetted(fm_cur)) { - put_short(loca_format); - put_short(0); - } - else - ttf_ncopy(2*TTF_SHORT_SIZE); + ttf_skip(TTF_ULONG_SIZE); /* skip checkSumAdjustment */ + ttf_ncopy(TTF_ULONG_SIZE + 2 * TTF_USHORT_SIZE + 16 + + 4 * TTF_FWORD_SIZE + 2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE); + if (is_subsetted(fd_cur->fm)) { + (void) put_short(loca_format); + (void) put_short(0); + } else + ttf_ncopy(2 * TTF_SHORT_SIZE); ttf_set_chksm(tab); } - + static void ttf_write_hhea(void) { dirtab_entry *tab; tab = ttf_seek_tab("hhea", 0); ttf_reset_chksm(tab); - ttf_ncopy(TTF_FIXED_SIZE + 3*TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3*TTF_FWORD_SIZE + 8*TTF_SHORT_SIZE); - put_ushort(new_glyphs_count); + ttf_ncopy(TTF_FIXED_SIZE + 3 * TTF_FWORD_SIZE + TTF_UFWORD_SIZE + + 3 * TTF_FWORD_SIZE + 8 * TTF_SHORT_SIZE); + (void) put_ushort(new_glyphs_count); ttf_set_chksm(tab); } static void ttf_write_htmx(void) { - short *id; + long *id; dirtab_entry *tab = ttf_seek_tab("hmtx", 0); ttf_reset_chksm(tab); for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) { @@ -986,7 +1169,7 @@ static void ttf_write_htmx(void) static void ttf_write_loca(void) { - short *id; + long *id; dirtab_entry *tab = ttf_seek_tab("loca", 0); ttf_reset_chksm(tab); loca_format = 0; @@ -1002,11 +1185,10 @@ static void ttf_write_loca(void) for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) put_ulong(glyph_tab[*id].newoffset); put_ulong(last_glyf_offset); - } - else { + } else { for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) - put_ushort(glyph_tab[*id].newoffset/2); - put_ushort(last_glyf_offset/2); + (void) put_ushort(glyph_tab[*id].newoffset / 2); + (void) put_ushort(last_glyf_offset / 2); } ttf_set_chksm(tab); } @@ -1016,8 +1198,8 @@ static void ttf_write_mapx(void) dirtab_entry *tab = ttf_seek_tab("maxp", TTF_FIXED_SIZE + TTF_USHORT_SIZE); ttf_reset_chksm(tab); put_fixed(0x00010000); - put_ushort(new_glyphs_count); - ttf_ncopy(13*TTF_USHORT_SIZE); + (void) put_ushort(new_glyphs_count); + ttf_ncopy(13 * TTF_USHORT_SIZE); ttf_set_chksm(tab); } @@ -1027,22 +1209,22 @@ static void ttf_write_OS2(void) TTF_USHORT version; ttf_reset_chksm(tab); version = get_ushort(); - if (version != 0x0000 && version != 0x0001 && version != 0x0002) - pdftex_fail("unknown verssion of OS/2 table (%.4X)", version); - put_ushort(0x0001); /* fix version to 1*/ - ttf_ncopy(2*TTF_USHORT_SIZE + 13*TTF_SHORT_SIZE + 10*TTF_BYTE_SIZE); - ttf_skip(4*TTF_ULONG_SIZE); /* ulUnicodeRange 1--4 */ - put_ulong(0x00000003); /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */ - put_ulong(0x10000000); /* Private Use (0xE000--0xF8FF) */ + if (version > 3) + pdftex_fail("unknown version of OS/2 table (%.4X)", version); + (void) put_ushort(0x0001); /* fix version to 1 */ + ttf_ncopy(2 * TTF_USHORT_SIZE + 13 * TTF_SHORT_SIZE + 10 * TTF_BYTE_SIZE); + ttf_skip(4 * TTF_ULONG_SIZE); /* ulUnicodeRange 1--4 */ + put_ulong(0x00000003); /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */ + put_ulong(0x10000000); /* Private Use (0xE000--0xF8FF) */ put_ulong(0x00000000); put_ulong(0x00000000); - ttf_ncopy(4*TTF_CHAR_SIZE + TTF_USHORT_SIZE); /* achVendID + fsSelection */ - ttf_skip(2*TTF_USHORT_SIZE); - put_ushort(0x0000); /* usFirstCharIndex */ - put_ushort(0xF0FF); /* usLastCharIndex */ - ttf_ncopy(5*TTF_USHORT_SIZE); - /* for version 0 the OS/2 table ends here, the rest is for version 1 */ - put_ulong(0x80000000); /* Symbol Character Set---don't use any code page */ + ttf_ncopy(4 * TTF_CHAR_SIZE + TTF_USHORT_SIZE); /* achVendID + fsSelection */ + ttf_skip(2 * TTF_USHORT_SIZE); + (void) put_ushort(0x0000); /* usFirstCharIndex */ + (void) put_ushort(0xF0FF); /* usLastCharIndex */ + ttf_ncopy(5 * TTF_USHORT_SIZE); + /* for version 0 the OS/2 table ends here, the rest is for version 1 */ + put_ulong(0x80000000); /* Symbol Character Set---don't use any code page */ put_ulong(0x00000000); ttf_set_chksm(tab); } @@ -1061,23 +1243,22 @@ static void ttf_write_post(void) dirtab_entry *tab = ttf_seek_tab("post", TTF_FIXED_SIZE); glyph_entry *glyph; char *s; - short *id; + long *id; int l; ttf_reset_chksm(tab); - if (!write_ttf_glyph_names || post_format == 0x00030000) { + if (!fd_cur->write_ttf_glyph_names || post_format == 0x00030000) { put_fixed(0x00030000); - ttf_ncopy(TTF_FIXED_SIZE + 2*TTF_FWORD_SIZE + 5*TTF_ULONG_SIZE); - } - else { + ttf_ncopy(TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE); + } else { put_fixed(0x00020000); - ttf_ncopy(TTF_FIXED_SIZE + 2*TTF_FWORD_SIZE + 5*TTF_ULONG_SIZE); - put_ushort(new_glyphs_count); + ttf_ncopy(TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE); + (void) put_ushort(new_glyphs_count); k = 0; for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) { glyph = glyph_tab + *id; if (glyph->name_index >= NMACGLYPHS || unsafe_name(glyph->name)) glyph->name_index = NMACGLYPHS + k++; - put_ushort(glyph->name_index); + (void) put_ushort(glyph->name_index); } for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) { glyph = glyph_tab + *id; @@ -1097,12 +1278,12 @@ static void ttf_init_font(int n) { int i, k; for (i = 1, k = 0; i <= n; i <<= 1, k++); - put_fixed(0x00010000); /* font version */ - put_ushort(n); /* number of tables */ - put_ushort(i << 3); /* search range */ - put_ushort(k - 1); /* entry selector */ - put_ushort((n<<4) - (i<<3)); /* range shift */ - ttf_seek_outbuf(TABDIR_OFF + n*4*TTF_ULONG_SIZE); + put_fixed(0x00010000); /* font version */ + (void) put_ushort(n); /* number of tables */ + (void) put_ushort(i << 3); /* search range */ + (void) put_ushort(k - 1); /* entry selector */ + (void) put_ushort((n << 4) - (i << 3)); /* range shift */ + ttf_seek_outbuf(TABDIR_OFF + n * 4 * TTF_ULONG_SIZE); } static void ttf_subset_font(void) @@ -1143,25 +1324,29 @@ static void ttf_copy_font(void) ttf_write_dirtab(); } -void writettf() +void writettf(fd_entry * fd) { - set_cur_file_name(fm_cur->ff_name); - if (is_subsetted(fm_cur) && !(is_reencoded(fm_cur))) { - pdftex_warn("encoding vector required for TrueType font subsetting"); + fd_cur = fd; /* fd_cur is global inside writettf.c */ + assert(fd_cur->fm != NULL); + assert(is_truetype(fd_cur->fm)); + assert(is_included(fd_cur->fm)); + + set_cur_file_name(fd_cur->fm->ff_name); + if (is_subsetted(fd_cur->fm) && (fd_cur->fe == NULL) + && !is_subfont(fd_cur->fm)) { + pdftex_warn("Subset TrueType must be a reencoded or a subfont"); cur_file_name = NULL; return; } if (!ttf_open()) { pdftex_fail("cannot open TrueType font file for reading"); } - cur_file_name = (char*)nameoffile + 1; - if (!is_included(fm_cur)) - tex_printf("{%s", cur_file_name); - else if (is_subsetted(fm_cur)) + cur_file_name = (char *) nameoffile + 1; + if (is_subsetted(fd_cur->fm)) tex_printf("<%s", cur_file_name); else tex_printf("<<%s", cur_file_name); - fontfile_found = true; + fd_cur->ff_found = true; new_glyphs_count = 2; new_ntabs = DEFAULT_NTABS; dir_tab = NULL; @@ -1171,18 +1356,16 @@ void writettf() name_tab = NULL; name_buf = NULL; ttf_read_font(); - if (is_included(fm_cur)) { - pdfsaveoffset = pdfoffset(); - pdfflush(); - if (is_subsetted(fm_cur)) { - ttf_copy_encoding(); - make_subset_tag(fm_cur, fm_cur->encoding->glyph_names); - ttf_subset_font(); - } - else - ttf_copy_font(); - ttf_length = ttf_offset(); - } + + pdfsaveoffset = pdfoffset(); + pdfflush(); + if (is_subsetted(fd_cur->fm)) { + ttf_copy_encoding(); + ttf_subset_font(); + } else + ttf_copy_font(); + ttf_length = ttf_offset(); + xfree(dir_tab); xfree(glyph_tab); xfree(glyph_index); @@ -1190,26 +1373,32 @@ void writettf() xfree(name_tab); xfree(name_buf); ttf_close(); - if (!is_included(fm_cur)) - tex_printf("}"); - else if (is_subsetted(fm_cur)) + if (is_subsetted(fd_cur->fm)) tex_printf(">"); else tex_printf(">>"); cur_file_name = NULL; } -void writeotf() +void writeotf(fd_entry * fd) { dirtab_entry *tab; long i; - set_cur_file_name(fm_cur->ff_name); - if (!open_input(&ttf_file, kpse_type1_format, FOPEN_RBIN_MODE)) { + + fd_cur = fd; /* fd_cur is global inside writettf.c */ + assert(fd_cur->fm != NULL); + assert(is_opentype(fd_cur->fm)); + assert(is_included(fd_cur->fm)); + + set_cur_file_name(fd_cur->fm->ff_name); + if (is_subsetted(fd_cur->fm)) + pdftex_fail("OTF fonts must be included entirely"); + if (!open_input(&ttf_file, kpse_opentype_format, FOPEN_RBIN_MODE)) { pdftex_fail("cannot open OpenType font file for reading"); } - cur_file_name = (char*)nameoffile + 1; + cur_file_name = (char *) nameoffile + 1; tex_printf("<<%s", cur_file_name); - fontfile_found = true; + fd_cur->ff_found = true; dir_tab = NULL; glyph_tab = NULL; ttf_read_tabdir(); @@ -1252,6 +1441,4 @@ void writeotf() The table directory also includes the offset of the associated tagged table from the beginning of the font file and the length of that table. - - */ |