summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/pdftexdir/writettf.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/web2c/pdftexdir/writettf.c
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/pdftexdir/writettf.c')
-rw-r--r--Build/source/texk/web2c/pdftexdir/writettf.c1257
1 files changed, 1257 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/pdftexdir/writettf.c b/Build/source/texk/web2c/pdftexdir/writettf.c
new file mode 100644
index 00000000000..e2d0d1641d6
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writettf.c
@@ -0,0 +1,1257 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$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 $";
+
+#define DEFAULT_NTABS 14
+#define NEW_CMAP_SIZE 2
+
+#define ttf_putchar fb_putchar
+#define ttf_offset fb_offset
+#define ttf_seek_outbuf fb_seek
+
+#define INFILE ttf_file
+
+#define ttf_open() \
+ open_input(&ttf_file, kpse_truetype_format, FOPEN_RBIN_MODE)
+#define ttf_close() xfclose(ttf_file, cur_file_name)
+#define ttf_getchar() xgetc(ttf_file)
+#define ttf_eof() feof(ttf_file)
+
+typedef struct {
+ TTF_LONG offset;
+ 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 */
+} glyph_entry;
+
+typedef struct {
+ char *name; /* name of glyph */
+ short newindex; /* new index of glyph in output file */
+} ttfenc_entry;
+
+typedef struct {
+ TTF_USHORT platform_id;
+ TTF_USHORT encoding_id;
+ TTF_USHORT language_id;
+ TTF_USHORT name_id;
+ TTF_USHORT length;
+ TTF_USHORT offset;
+ TTF_USHORT new_offset;
+ TTF_USHORT new_length;
+} name_record;
+
+static TTF_USHORT ntabs;
+static TTF_USHORT upem;
+static TTF_FIXED post_format;
+static TTF_SHORT loca_format;
+static TTF_ULONG last_glyf_offset;
+static TTF_USHORT glyphs_count;
+static TTF_USHORT new_glyphs_count;
+static TTF_USHORT nhmtxs;
+static TTF_USHORT new_ntabs;
+
+static glyph_entry *glyph_tab;
+static short *glyph_index;
+static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE];
+static name_record *name_tab;
+static int name_record_num;
+static char *name_buf;
+static int name_buf_size;
+static dirtab_entry *dir_tab;
+static char *glyph_name_buf;
+static TTF_ULONG checksum;
+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 TTF_USHORT unicode_map[0xFFFF];
+
+
+integer ttf_length;
+
+#include "macnames.c"
+
+extern char *fb_array;
+
+static const char *newtabnames[] = {
+ "OS/2",
+ "PCLT",
+ "cmap",
+ "cvt ",
+ "fpgm",
+ "glyf",
+ "head",
+ "hhea",
+ "hmtx",
+ "loca",
+ "maxp",
+ "name",
+ "post",
+ "prep"
+};
+
+static unsigned char ttf_addchksm(unsigned char b)
+{
+ tmp_ulong = (tmp_ulong << 8) + b;
+ tab_length++;
+ if (tab_length % 4 == 0) {
+ checksum += tmp_ulong;
+ tmp_ulong = 0;
+ }
+ return b;
+}
+
+static TTF_ULONG ttf_getchksm(void)
+{
+ while (tab_length % 4 != 0)
+ ttf_putchar(ttf_addchksm(0)); /* ttf_addchksm updates tab_length */
+ return checksum;
+}
+
+static long ttf_putnum(int s, long n)
+{
+ long i = n;
+ char buf[TTF_LONG_SIZE + 1], *p = buf;
+ while (s-- > 0) {
+ *p++ = i & 0xFF;
+ i >>= 8;
+ }
+ p--;
+ while (p >= buf)
+ ttf_putchar(ttf_addchksm(*p--));
+ return n;
+}
+
+static long ttf_getnum(int s)
+{
+ long i = 0;
+ int c;
+ while (s > 0) {
+ if ((c = ttf_getchar()) < 0)
+ pdftex_fail("unexpected EOF");
+ i = (i << 8) + c;
+ s--;
+ }
+ return i;
+}
+
+static long ttf_funit(long n)
+{
+ if (n < 0)
+ return -((-n/upem)*1000 + ((-n%upem)*1000)/upem);
+ else
+ return (n/upem)*1000 + ((n%upem)*1000)/upem;
+}
+
+static void ttf_ncopy(int n)
+{
+ while (n-- > 0)
+ copy_byte();
+}
+
+static dirtab_entry *ttf_name_lookup(const char *s, boolean required)
+{
+ dirtab_entry *tab;
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++)
+ if (strncmp(tab->tag, s, 4) == 0)
+ break;
+ if (tab - dir_tab == ntabs) {
+ if (required)
+ pdftex_fail("can't find table `%s'", s);
+ else
+ tab = NULL;
+ }
+ return tab;
+}
+
+static dirtab_entry *ttf_seek_tab(const char *name, TTF_LONG offset)
+{
+ dirtab_entry *tab = ttf_name_lookup(name, true);
+ xfseek(INFILE, tab->offset + offset, SEEK_SET, cur_file_name);
+ return tab;
+}
+
+static void ttf_seek_off(TTF_LONG offset)
+{
+ xfseek(INFILE, offset, SEEK_SET, cur_file_name);
+}
+
+static void ttf_copy_encoding(void)
+{
+ int i;
+ char **glyph_names = (fm_cur->encoding)->glyph_names;
+ 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;
+ }
+}
+
+#define ttf_append_byte(B)\
+do {\
+ if (name_tab[i].platform_id == 3)\
+ *q++ = 0;\
+ *q++ = B;\
+} while (0)
+
+static void ttf_read_name(void)
+{
+ int i, j;
+ dirtab_entry *tab = ttf_seek_tab("name", TTF_USHORT_SIZE);
+ 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 = xtalloc(name_buf_size, char);
+ ttf_skip(TTF_USHORT_SIZE);
+ for (i = 0; i < name_record_num; i++) {
+ name_tab[i].platform_id = get_ushort();
+ name_tab[i].encoding_id = get_ushort();
+ name_tab[i].language_id = get_ushort();
+ name_tab[i].name_id = get_ushort();
+ name_tab[i].length = get_ushort();
+ name_tab[i].offset = get_ushort();
+ }
+ for (p = name_buf; p - name_buf < name_buf_size; p++)
+ *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;
+ break;
+ }
+ }
+ if (!font_keys[FONTNAME_CODE].valid) {
+ 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)
+ *p++ = name_buf[name_tab[i].offset + j + 1];
+ *p = 0;
+ font_keys[FONTNAME_CODE].valid = true;
+ break;
+ }
+ }
+ }
+}
+
+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);
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) {
+ glyph->newindex = -1;
+ glyph->newoffset = 0;
+ glyph->name_index = 0;
+ 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 */
+}
+
+static void ttf_read_head(void)
+{
+ 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);
+ 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);
+ nhmtxs = get_ushort();
+}
+
+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;
+}
+
+static void ttf_read_hmtx(void)
+{
+ glyph_entry *glyph;
+ TTF_UFWORD last_advWidth;
+ ttf_seek_tab("hmtx", 0);
+ for (glyph = glyph_tab; glyph - glyph_tab < nhmtxs; glyph++) {
+ glyph->advWidth = get_ufword();
+ glyph->lsb = get_ufword();
+ }
+ if (nhmtxs < glyphs_count) {
+ last_advWidth = glyph[-1].advWidth;
+ for (;glyph - glyph_tab < glyphs_count; glyph++) {
+ glyph->advWidth = last_advWidth;
+ glyph->lsb = get_ufword();
+ }
+ }
+}
+
+static void ttf_read_post(void)
+{
+ int k, nnames;
+ long length;
+ long int_part, frac_part;
+ int sign = 1;
+ TTF_FIXED italic_angle;
+ char *p;
+ glyph_entry *glyph;
+ 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 */
+ 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;
+ if (glyph_tab == NULL)
+ 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_index = glyph - glyph_tab;
+ }
+ break;
+ case 0x20000:
+ 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);
+ glyph_name_buf = xtalloc(length, char);
+ for (p = glyph_name_buf; p - glyph_name_buf < length;) {
+ for (k = get_byte(); k > 0; k--)
+ *p++ = get_char();
+ *p++ = 0;
+ }
+ for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) {
+ if (glyph->name_index < NMACGLYPHS)
+ glyph->name = (char*)mac_glyph_names[glyph->name_index];
+ else {
+ p = glyph_name_buf;
+ k = glyph->name_index - NMACGLYPHS;
+ for (; k > 0; k--)
+ p = strend(p) + 1;
+ glyph->name = p;
+ }
+ }
+ break;
+ case 0x00030000:
+ for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
+ glyph->name_index = glyph - glyph_tab;
+ }
+ break;
+ default:
+ pdftex_fail("unsupported format (%.8X) of `post' table", (unsigned int) post_format);
+ }
+}
+
+static void ttf_read_loca(void)
+{
+ glyph_entry *glyph;
+ ttf_seek_tab("loca", 0);
+ if (loca_format != 0)
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
+ glyph->offset = get_ulong();
+ else
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
+ glyph->offset = get_ushort() << 1;
+}
+
+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 */
+ dir_tab = xtalloc(ntabs = get_ushort(), dirtab_entry);
+ 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();
+ tab->checksum = get_ulong();
+ tab->offset = get_ulong();
+ tab->length = get_ulong();
+ }
+}
+
+static void ttf_read_cmap(void)
+{
+ 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) */
+ ncmapsubtabs = get_ushort();
+ 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;
+ }
+ 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;
+ }
+ }
+ }
+ 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);
+}
+
+static void ttf_read_font(void)
+{
+ ttf_read_tabdir();
+ if (ttf_name_lookup("PCLT", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup("fpgm", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup("cvt ", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup("prep", false) == NULL)
+ new_ntabs--;
+ ttf_read_mapx();
+ ttf_read_head();
+ ttf_read_hhea();
+ ttf_read_pclt();
+ ttf_read_hmtx();
+ ttf_read_post();
+ ttf_read_loca();
+ ttf_read_name();
+ ttf_read_cmap();
+}
+
+static void ttf_reset_chksm(dirtab_entry *tab)
+{
+ checksum = 0;
+ tab_length = 0;
+ tmp_ulong = 0;
+ tab->offset = ttf_offset();
+ if (tab->offset % 4 != 0)
+ pdftex_warn("offset of `%4.4s' is not a multiple of 4", tab->tag);
+}
+
+
+static void ttf_set_chksm(dirtab_entry *tab)
+{
+ tab->length = ttf_offset() - tab->offset;
+ tab->checksum = ttf_getchksm();
+}
+
+static void ttf_copytab(const char *name)
+{
+ long i;
+ dirtab_entry *tab = ttf_seek_tab(name, 0);
+ ttf_reset_chksm(tab);
+ for (i = tab->length; i > 0; i--)
+ copy_char();
+ ttf_set_chksm(tab);
+}
+
+#define BYTE_ENCODING_LENGTH \
+ ((MAX_CHAR_CODE + 1)*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++)
+ if (e->newindex < 256) {
+ put_byte(e->newindex);
+ }
+ 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 */
+ }
+}
+
+#define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (MAX_CHAR_CODE + 1)))
+
+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);
+}
+
+#define SEG_MAP_DELTA_LENGTH ((16 + (MAX_CHAR_CODE + 1))*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);
+}
+
+#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 */
+}
+
+static void ttf_write_cmap(void)
+{
+ cmap_entry *ce;
+ long offset;
+ 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;
+ 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;
+ break;
+ case 4:
+ offset += SEG_MAP_DELTA_LENGTH;
+ break;
+ 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);
+ put_ulong(ce->offset);
+ }
+ for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
+ switch (ce->format) {
+ case 0:
+ ttf_byte_encoding();
+ break;
+ case 4:
+ ttf_seg_map_delta();
+ break;
+ case 6:
+ ttf_trimmed_table_map();
+ break;
+ }
+ }
+ ttf_set_chksm(tab);
+}
+
+static int prepend_subset_tags(int index, char *p)
+{
+ boolean is_unicode = (name_tab[index].platform_id == 3);
+ int i;
+ assert(index > 0 && index < name_record_num && fm_cur->subset_tag != NULL);
+ if (is_unicode) {
+ for (i = 0; i < 6; ++i) {
+ *p++ = 0;
+ *p++ = fm_cur->subset_tag[i];
+ }
+ *p++ = 0;
+ *p++ = '+';
+ return 14;
+ } else {
+ strncpy(p, fm_cur->subset_tag, 6);
+ p += 6;
+ *p++ = '+';
+ return 7;
+ }
+}
+
+
+static void ttf_write_name(void)
+{
+ int i, l;
+ char *p;
+ int new_name_buf_size;
+ char *new_name_buf;
+ name_record *n;
+ dirtab_entry *tab = ttf_name_lookup("name", true);
+ if (is_subsetted(fm_cur)) {
+ l = 0;
+ for (i = 0; i < name_record_num; i++)
+ 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;
+ for (i = 0; i < name_record_num; i++) {
+ n = name_tab + i;
+ n->new_offset = p - new_name_buf;
+ if ((n->name_id == 1 || n->name_id == 3 ||
+ 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)))
+ {
+ l = prepend_subset_tags(i, p);
+ p += l;
+ }
+ 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 {
+ 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);
+ 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);
+ }
+ for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++)
+ put_char(*p);
+ ttf_set_chksm(tab);
+ if (new_name_buf != name_buf)
+ xfree(new_name_buf);
+}
+
+static void ttf_write_dirtab(void)
+{
+ dirtab_entry *tab;
+ TTF_ULONG i, k;
+ char *p;
+ integer save_offset = ttf_offset();
+ ttf_seek_outbuf(TABDIR_OFF);
+ if (is_subsetted(fm_cur)) {
+ 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_ulong(tab->checksum);
+ put_ulong(tab->offset);
+ put_ulong(tab->length);
+ }
+ }
+ else {
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ for (k = 0; k < 4; k++)
+ put_char(tab->tag[k]);
+ put_ulong(tab->checksum);
+ put_ulong(tab->offset);
+ put_ulong(tab->length);
+ }
+ }
+ /* adjust checkSumAdjustment */
+ tmp_ulong = 0;
+ checksum = 0;
+ for (p = fb_array, i = 0; i < save_offset;) {
+ tmp_ulong = (tmp_ulong << 8) + *p++;
+ i++;
+ if (i % 4 == 0) {
+ checksum += tmp_ulong;
+ tmp_ulong = 0;
+ }
+ }
+ if (i % 4 != 0) {
+ pdftex_warn("font length is not a multiple of 4 (%li)", i);
+ checksum <<= 8*(4 - i % 4);
+ }
+ k = 0xB1B0AFBA - checksum;
+ ttf_seek_outbuf(checkSumAdjustment_offset);
+ put_ulong(k);
+ ttf_seek_outbuf(save_offset);
+}
+
+static void ttf_write_glyf(void)
+{
+ short *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();
+ 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);
+ if (k < 0) {
+ do {
+ flags = copy_ushort();
+ idx = get_ushort();
+ 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
+ */
+ }
+ put_ushort(glyph_tab[idx].newindex);
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ 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);
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ 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);
+ }
+ }
+ last_glyf_offset = ttf_offset() - new_glyf_offset;
+ ttf_set_chksm(tab);
+}
+
+static void ttf_reindex_glyphs(void)
+{
+ ttfenc_entry *e;
+ glyph_entry *glyph;
+ unsigned int index;
+ /*
+ * 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 */
+ if (e->name == notdef)
+ continue;
+ /* scan form `index123' */
+ 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);
+ continue;
+ }
+ glyph = glyph_tab + index;
+ goto append_new_glyph;
+ }
+ /* 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);
+ continue;
+ }
+ glyph = glyph_tab + unicode_map[index];
+ goto append_new_glyph;
+ }
+ else {
+ pdftex_warn("`unicode %s%.4X' is not mapped to any glyph",
+ GLYPH_PREFIX_UNICODE, index);
+ continue;
+ }
+ }
+ /* look up by name */
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++)
+ if (glyph->name != notdef && strcmp(glyph->name, e->name) == 0)
+ break;
+ if (!(glyph - glyph_tab < glyphs_count)) {
+ pdftex_warn("glyph `%s' not found", e->name);
+ continue;
+ }
+append_new_glyph:
+ assert(glyph - glyph_tab < glyphs_count);
+ if (glyph->newindex < 0) {
+ glyph_index[new_glyphs_count] = glyph - glyph_tab;
+ glyph->newindex = new_glyphs_count;
+ new_glyphs_count++;
+ }
+ 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);
+ 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_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_set_chksm(tab);
+}
+
+static void ttf_write_htmx(void)
+{
+ short *id;
+ dirtab_entry *tab = ttf_seek_tab("hmtx", 0);
+ ttf_reset_chksm(tab);
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ put_ufword(glyph_tab[*id].advWidth);
+ put_ufword(glyph_tab[*id].lsb);
+ }
+ ttf_set_chksm(tab);
+}
+
+static void ttf_write_loca(void)
+{
+ short *id;
+ dirtab_entry *tab = ttf_seek_tab("loca", 0);
+ ttf_reset_chksm(tab);
+ loca_format = 0;
+ if (last_glyf_offset >= 0x00020000 || (last_glyf_offset & 1))
+ loca_format = 1;
+ else
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ if (glyph_tab[*id].newoffset & 1) {
+ loca_format = 1;
+ break;
+ }
+ if (loca_format != 0) {
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ put_ulong(glyph_tab[*id].newoffset);
+ put_ulong(last_glyf_offset);
+ }
+ 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);
+ }
+ ttf_set_chksm(tab);
+}
+
+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);
+ ttf_set_chksm(tab);
+}
+
+static void ttf_write_OS2(void)
+{
+ dirtab_entry *tab = ttf_seek_tab("OS/2", 0);
+ 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) */
+ 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 */
+ put_ulong(0x00000000);
+ ttf_set_chksm(tab);
+}
+
+static boolean unsafe_name(char *s)
+{
+ const char **p;
+ for (p = ambiguous_names; *p != NULL; p++)
+ if (strcmp(s, *p) == 0)
+ return true;
+ return false;
+}
+
+static void ttf_write_post(void)
+{
+ dirtab_entry *tab = ttf_seek_tab("post", TTF_FIXED_SIZE);
+ glyph_entry *glyph;
+ char *s;
+ short *id;
+ int l;
+ ttf_reset_chksm(tab);
+ if (!write_ttf_glyph_names || post_format == 0x00030000) {
+ put_fixed(0x00030000);
+ 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);
+ 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);
+ }
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph = glyph_tab + *id;
+ if (glyph->name_index >= NMACGLYPHS) {
+ s = glyph->name;
+ l = strlen(s);
+ put_byte(l);
+ while (l-- > 0)
+ put_char(*s++);
+ }
+ }
+ }
+ ttf_set_chksm(tab);
+}
+
+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);
+}
+
+static void ttf_subset_font(void)
+{
+ ttf_init_font(new_ntabs);
+ if (ttf_name_lookup("PCLT", false) != NULL)
+ ttf_copytab("PCLT");
+ if (ttf_name_lookup("fpgm", false) != NULL)
+ ttf_copytab("fpgm");
+ if (ttf_name_lookup("cvt ", false) != NULL)
+ ttf_copytab("cvt ");
+ if (ttf_name_lookup("prep", false) != NULL)
+ ttf_copytab("prep");
+ ttf_reindex_glyphs();
+ ttf_write_glyf();
+ ttf_write_loca();
+ ttf_write_OS2();
+ ttf_write_head();
+ ttf_write_hhea();
+ ttf_write_htmx();
+ ttf_write_mapx();
+ ttf_write_name();
+ ttf_write_post();
+ ttf_write_cmap();
+ ttf_write_dirtab();
+}
+
+static void ttf_copy_font(void)
+{
+ dirtab_entry *tab;
+ ttf_init_font(ntabs);
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ if (strncmp(tab->tag, "head", 4) == 0)
+ ttf_write_head();
+ else
+ ttf_copytab(tab->tag);
+ }
+ ttf_write_dirtab();
+}
+
+void writettf()
+{
+ 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");
+ 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))
+ tex_printf("<%s", cur_file_name);
+ else
+ tex_printf("<<%s", cur_file_name);
+ fontfile_found = true;
+ new_glyphs_count = 2;
+ new_ntabs = DEFAULT_NTABS;
+ dir_tab = NULL;
+ glyph_tab = NULL;
+ glyph_index = NULL;
+ glyph_name_buf = NULL;
+ 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();
+ }
+ xfree(dir_tab);
+ xfree(glyph_tab);
+ xfree(glyph_index);
+ xfree(glyph_name_buf);
+ xfree(name_tab);
+ xfree(name_buf);
+ ttf_close();
+ if (!is_included(fm_cur))
+ tex_printf("}");
+ else if (is_subsetted(fm_cur))
+ tex_printf(">");
+ else
+ tex_printf(">>");
+ cur_file_name = NULL;
+}
+
+void writeotf()
+{
+ dirtab_entry *tab;
+ long i;
+ set_cur_file_name(fm_cur->ff_name);
+ if (!open_input(&ttf_file, kpse_type1_format, FOPEN_RBIN_MODE)) {
+ pdftex_fail("cannot open OpenType font file for reading");
+ }
+ cur_file_name = (char*)nameoffile + 1;
+ tex_printf("<<%s", cur_file_name);
+ fontfile_found = true;
+ dir_tab = NULL;
+ glyph_tab = NULL;
+ ttf_read_tabdir();
+ /* read font parameters */
+ if (ttf_name_lookup("head", false) != NULL)
+ ttf_read_head();
+ if (ttf_name_lookup("hhea", false) != NULL)
+ ttf_read_hhea();
+ if (ttf_name_lookup("PCLT", false) != NULL)
+ ttf_read_pclt();
+ if (ttf_name_lookup("post", false) != NULL)
+ ttf_read_post();
+ /* copy font file */
+ tab = ttf_seek_tab("CFF ", 0);
+ for (i = tab->length; i > 0; i--)
+ copy_char();
+ xfree(dir_tab);
+ ttf_close();
+ tex_printf(">>");
+ cur_file_name = NULL;
+}
+
+/*
+ To calculate the checkSum for the 'head' table which itself includes the
+ checkSumAdjustment entry for the entire font, do the following:
+
+ * Set the checkSumAdjustment to 0.
+ * Calculate the checksum for all the tables including the 'head' table
+ and enter that value into the table directory.
+ * Calculate the checksum for the entire font.
+ * Subtract that value from the hex value B1B0AFBA.
+ * Store the result in checkSumAdjustment.
+
+ The checkSum for the 'head table which includes the checkSumAdjustment
+ entry for the entire font is now incorrect. That is not a problem. Do not
+ change it. An application attempting to verify that the 'head' table has
+ not changed should calculate the checkSum for that table by not including
+ the checkSumAdjustment value, and compare the result with the entry in the
+ table directory.
+
+ 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.
+
+
+ */