Back to index

tetex-bin  3.0
writettf.c
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
00003 
00004 This file is part of pdfTeX.
00005 
00006 pdfTeX is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
00010 
00011 pdfTeX is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with pdfTeX; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writettf.c#14 $
00021 */
00022 
00023 #include "ptexlib.h"
00024 #include "writettf.h"
00025 
00026 static const char perforce_id[] = 
00027     "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writettf.c#14 $";
00028 
00029 #define DEFAULT_NTABS       14
00030 #define NEW_CMAP_SIZE       2
00031 
00032 #define ttf_putchar     fb_putchar
00033 #define ttf_offset      fb_offset
00034 #define ttf_seek_outbuf fb_seek
00035 
00036 #define INFILE ttf_file
00037 
00038 #define ttf_open()      \
00039     open_input(&ttf_file, kpse_truetype_format, FOPEN_RBIN_MODE)
00040 #define ttf_close()     xfclose(ttf_file, cur_file_name)
00041 #define ttf_getchar()   xgetc(ttf_file)
00042 #define ttf_eof()       feof(ttf_file)
00043 
00044 typedef struct {
00045     TTF_LONG offset;
00046     TTF_LONG newoffset;
00047     TTF_UFWORD advWidth;
00048     TTF_FWORD lsb;
00049     char *name;              /* name of glyph */
00050     TTF_SHORT newindex;      /* new index of glyph in output file */
00051     TTF_USHORT name_index;   /* index of name as read from font file */
00052 } glyph_entry;
00053 
00054 typedef struct {
00055     char *name;             /* name of glyph */
00056     short newindex;         /* new index of glyph in output file */
00057 } ttfenc_entry;
00058 
00059 typedef struct {
00060     TTF_USHORT platform_id;
00061     TTF_USHORT encoding_id;
00062     TTF_USHORT language_id;
00063     TTF_USHORT name_id;
00064     TTF_USHORT length;
00065     TTF_USHORT offset;
00066     TTF_USHORT new_offset;
00067     TTF_USHORT new_length;
00068 } name_record;
00069 
00070 static TTF_USHORT ntabs;
00071 static TTF_USHORT upem;
00072 static TTF_FIXED post_format;
00073 static TTF_SHORT loca_format;
00074 static TTF_ULONG last_glyf_offset;
00075 static TTF_USHORT glyphs_count;
00076 static TTF_USHORT new_glyphs_count;
00077 static TTF_USHORT nhmtxs;
00078 static TTF_USHORT new_ntabs;
00079 
00080 static glyph_entry *glyph_tab;
00081 static short *glyph_index;
00082 static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE];
00083 static name_record *name_tab;
00084 static int name_record_num;
00085 static char *name_buf;
00086 static int name_buf_size;
00087 static dirtab_entry *dir_tab;
00088 static char *glyph_name_buf;
00089 static TTF_ULONG checksum;
00090 static TTF_ULONG tab_length;
00091 static TTF_ULONG tmp_ulong;
00092 static TTF_ULONG checkSumAdjustment_offset;
00093 static FILE *ttf_file;
00094 static ttfenc_entry ttfenc_tab[MAX_CHAR_CODE + 1];
00095 
00096 static TTF_USHORT unicode_map[0xFFFF];
00097 
00098 
00099 integer ttf_length;
00100 
00101 #include "macnames.c"
00102 
00103 extern char *fb_array;
00104 
00105 static const char *newtabnames[] = {
00106     "OS/2",
00107     "PCLT",
00108     "cmap",
00109     "cvt ",
00110     "fpgm",
00111     "glyf",
00112     "head",
00113     "hhea",
00114     "hmtx",
00115     "loca",
00116     "maxp",
00117     "name",
00118     "post",
00119     "prep"
00120 };
00121 
00122 static unsigned char ttf_addchksm(unsigned char b)
00123 {
00124     tmp_ulong = (tmp_ulong << 8) + b;
00125     tab_length++;
00126     if (tab_length % 4 == 0) {
00127         checksum += tmp_ulong;
00128         tmp_ulong = 0;
00129     }
00130     return b;
00131 }
00132 
00133 static TTF_ULONG ttf_getchksm(void)
00134 {
00135     while (tab_length % 4 != 0)
00136         ttf_putchar(ttf_addchksm(0)); /* ttf_addchksm updates tab_length */
00137     return checksum;
00138 }
00139 
00140 static long ttf_putnum(int s, long n)
00141 {
00142     long i = n;
00143     char buf[TTF_LONG_SIZE + 1], *p = buf;
00144     while (s-- > 0) {
00145         *p++ = i & 0xFF;
00146         i >>= 8;
00147     }
00148     p--;
00149     while (p >= buf)
00150         ttf_putchar(ttf_addchksm(*p--));
00151     return n;
00152 }
00153 
00154 static long ttf_getnum(int s)
00155 {
00156     long i = 0;
00157     int c;
00158     while (s > 0) {
00159         if ((c = ttf_getchar()) < 0)
00160             pdftex_fail("unexpected EOF");
00161         i = (i << 8) + c;
00162         s--;
00163     }
00164     return i;
00165 }
00166 
00167 static long ttf_funit(long n)
00168 {
00169     if (n < 0)
00170         return -((-n/upem)*1000 + ((-n%upem)*1000)/upem);
00171     else
00172         return (n/upem)*1000 + ((n%upem)*1000)/upem;
00173 }
00174 
00175 static void ttf_ncopy(int n)
00176 {
00177     while (n-- > 0)
00178         copy_byte();
00179 }
00180 
00181 static dirtab_entry *ttf_name_lookup(const char *s, boolean required)
00182 {
00183     dirtab_entry *tab;
00184     for (tab = dir_tab; tab - dir_tab < ntabs; tab++)
00185         if (strncmp(tab->tag, s, 4) == 0)
00186             break;
00187     if (tab - dir_tab == ntabs) {
00188         if (required)
00189             pdftex_fail("can't find table `%s'", s);
00190         else
00191             tab = NULL;
00192     }
00193     return tab;
00194 }
00195 
00196 static dirtab_entry *ttf_seek_tab(const char *name, TTF_LONG offset)
00197 {
00198     dirtab_entry *tab = ttf_name_lookup(name, true);
00199     xfseek(INFILE, tab->offset + offset, SEEK_SET, cur_file_name);
00200     return tab;
00201 }
00202 
00203 static void ttf_seek_off(TTF_LONG offset)
00204 {
00205     xfseek(INFILE, offset, SEEK_SET, cur_file_name);
00206 }
00207 
00208 static void ttf_copy_encoding(void)
00209 {
00210     int i;
00211     char **glyph_names = (fm_cur->encoding)->glyph_names;
00212     ttfenc_entry *e = ttfenc_tab;
00213     pdfmarkchar(tex_font, 'a'); /* workaround for a bug of AcroReader 4.0 */
00214     for (i = 0; i <= MAX_CHAR_CODE; i++, e++) {
00215         if (pdfcharmarked(tex_font, i))
00216             e->name = glyph_names[i];
00217         else
00218             e->name = (char*) notdef;
00219     }
00220 }
00221 
00222 #define ttf_append_byte(B)\
00223 do {\
00224     if (name_tab[i].platform_id == 3)\
00225         *q++ = 0;\
00226     *q++ = B;\
00227 } while (0)
00228 
00229 static void ttf_read_name(void)
00230 {
00231     int i, j;
00232     dirtab_entry *tab = ttf_seek_tab("name", TTF_USHORT_SIZE);
00233     char *p;
00234     name_record_num = get_ushort();
00235     name_tab = xtalloc(name_record_num, name_record);
00236     name_buf_size = tab->length - 
00237          (3*TTF_USHORT_SIZE + name_record_num*6*TTF_USHORT_SIZE);
00238     name_buf = xtalloc(name_buf_size, char);
00239     ttf_skip(TTF_USHORT_SIZE);
00240     for (i = 0; i < name_record_num; i++) {
00241         name_tab[i].platform_id = get_ushort();
00242         name_tab[i].encoding_id = get_ushort();
00243         name_tab[i].language_id = get_ushort();
00244         name_tab[i].name_id = get_ushort();
00245         name_tab[i].length = get_ushort();
00246         name_tab[i].offset = get_ushort();
00247     }
00248     for (p = name_buf; p - name_buf < name_buf_size; p++)
00249          *p = get_char();
00250     /* look for PS font name */
00251     for (i = 0; i < name_record_num; i++) {
00252         if (name_tab[i].platform_id == 1 && 
00253             name_tab[i].encoding_id == 0 &&
00254             name_tab[i].name_id == 6) {
00255             strncpy(fontname_buf, name_buf + name_tab[i].offset, name_tab[i].length);
00256             fontname_buf[name_tab[i].length] = 0;
00257             font_keys[FONTNAME_CODE].valid = true;
00258             break;
00259         }
00260     }
00261     if (!font_keys[FONTNAME_CODE].valid) {
00262         for (i = 0; i < name_record_num; i++) {
00263             if (name_tab[i].platform_id == 3 && 
00264                 (name_tab[i].encoding_id == 0 || 
00265                  name_tab[i].encoding_id == 1) &&
00266                 name_tab[i].name_id == 6) {
00267                 for (j = 0, p = fontname_buf; j < name_tab[i].length; j += 2)
00268                     *p++ = name_buf[name_tab[i].offset + j + 1];
00269                 *p = 0;
00270                 font_keys[FONTNAME_CODE].valid = true;
00271                 break;
00272             }
00273         }
00274     }
00275 }
00276 
00277 static void ttf_read_mapx(void)
00278 {
00279     int i;
00280     glyph_entry *glyph;
00281     ttf_seek_tab("maxp", TTF_FIXED_SIZE);
00282     glyph_tab = xtalloc(1 + (glyphs_count = get_ushort()), glyph_entry);
00283     for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) {
00284         glyph->newindex = -1;
00285         glyph->newoffset = 0;
00286         glyph->name_index = 0;
00287         glyph->name = (char*) notdef;
00288     }
00289     glyph_index = xtalloc(glyphs_count, short);
00290     glyph_index[0] = 0; /* index of ".notdef" glyph */
00291     glyph_index[1] = 1; /* index of ".null" glyph */
00292 }
00293 
00294 static void ttf_read_head(void)
00295 {
00296     ttf_seek_tab("head", 2*TTF_FIXED_SIZE + 2*TTF_ULONG_SIZE + TTF_USHORT_SIZE);
00297     upem = get_ushort();
00298     ttf_skip(16);
00299     font_keys[FONTBBOX1_CODE].value = ttf_funit(get_fword());
00300     font_keys[FONTBBOX2_CODE].value = ttf_funit(get_fword());
00301     font_keys[FONTBBOX3_CODE].value = ttf_funit(get_fword());
00302     font_keys[FONTBBOX4_CODE].value = ttf_funit(get_fword());
00303     font_keys[FONTBBOX1_CODE].valid = true;
00304     font_keys[FONTBBOX2_CODE].valid = true;
00305     font_keys[FONTBBOX3_CODE].valid = true;
00306     font_keys[FONTBBOX4_CODE].valid = true;
00307     ttf_skip(2*TTF_USHORT_SIZE + TTF_SHORT_SIZE);
00308     loca_format = get_short();
00309 }
00310 
00311 static void ttf_read_hhea(void)
00312 {
00313     ttf_seek_tab("hhea", TTF_FIXED_SIZE);
00314     font_keys[ASCENT_CODE].value = ttf_funit(get_fword());
00315     font_keys[DESCENT_CODE].value = ttf_funit(get_fword());
00316     font_keys[ASCENT_CODE].valid = true;
00317     font_keys[DESCENT_CODE].valid = true;
00318     ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3*TTF_FWORD_SIZE + 8*TTF_SHORT_SIZE);
00319     nhmtxs = get_ushort();
00320 }
00321 
00322 static void ttf_read_pclt(void)
00323 {
00324     if (ttf_name_lookup("PCLT", false) == NULL)
00325         return;
00326     ttf_seek_tab("PCLT", TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE);
00327     font_keys[XHEIGHT_CODE].value = ttf_funit(get_ushort());
00328     ttf_skip(2*TTF_USHORT_SIZE);
00329     font_keys[CAPHEIGHT_CODE].value = ttf_funit(get_ushort());
00330     font_keys[XHEIGHT_CODE].valid = true;
00331     font_keys[CAPHEIGHT_CODE].valid = true;
00332 }
00333 
00334 static void ttf_read_hmtx(void)
00335 {
00336     glyph_entry *glyph;
00337     TTF_UFWORD last_advWidth;
00338     ttf_seek_tab("hmtx", 0);
00339     for (glyph = glyph_tab; glyph - glyph_tab < nhmtxs; glyph++) {
00340         glyph->advWidth = get_ufword();
00341         glyph->lsb = get_ufword();
00342     }
00343     if (nhmtxs < glyphs_count) {
00344         last_advWidth = glyph[-1].advWidth;
00345         for (;glyph - glyph_tab <  glyphs_count; glyph++) {
00346             glyph->advWidth = last_advWidth;
00347             glyph->lsb = get_ufword();
00348         }
00349     }
00350 }
00351 
00352 static void ttf_read_post(void)
00353 {
00354     int k, nnames;
00355     long length;
00356     long int_part, frac_part;
00357     int sign = 1;
00358     TTF_FIXED italic_angle;
00359     char *p;
00360     glyph_entry *glyph;
00361     dirtab_entry *tab = ttf_seek_tab("post", 0);
00362     post_format = get_fixed();
00363     italic_angle = get_fixed();
00364     int_part = italic_angle >> 16;
00365     if (int_part > 0x7FFF) { /* a negative number */
00366         int_part = 0x10000 - int_part;
00367         sign = -1;
00368     }
00369     frac_part = italic_angle % 0x10000;
00370     font_keys[ITALIC_ANGLE_CODE].value = sign*(int_part + frac_part*1.0/0x10000);
00371     font_keys[ITALIC_ANGLE_CODE].valid = true;
00372     if (glyph_tab == NULL)
00373         return; /* being called from writeotf() */
00374     ttf_skip(2*TTF_FWORD_SIZE + 5*TTF_ULONG_SIZE);
00375     switch (post_format) {
00376     case 0x10000:
00377         for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
00378             glyph->name = (char*)mac_glyph_names[glyph - glyph_tab];
00379             glyph->name_index = glyph - glyph_tab;
00380         }
00381         break;
00382     case 0x20000:
00383         nnames = get_ushort(); /* some fonts have this value different from nglyphs */
00384         for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++)
00385             glyph->name_index = get_ushort();
00386         length = tab->length - (xftell(INFILE, cur_file_name) - tab->offset);
00387         glyph_name_buf = xtalloc(length, char);
00388         for (p = glyph_name_buf; p - glyph_name_buf < length;) {
00389             for (k = get_byte(); k > 0; k--)
00390                 *p++ = get_char();
00391             *p++ = 0;
00392         }
00393         for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) {
00394             if (glyph->name_index < NMACGLYPHS)
00395                 glyph->name = (char*)mac_glyph_names[glyph->name_index];
00396             else {
00397                 p = glyph_name_buf;
00398                 k = glyph->name_index - NMACGLYPHS;
00399                 for (; k > 0; k--)
00400                     p = strend(p) + 1;
00401                 glyph->name = p;
00402             }
00403         }
00404         break;
00405     case 0x00030000:
00406         for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
00407             glyph->name_index = glyph - glyph_tab;
00408         }
00409         break;
00410     default:
00411         pdftex_fail("unsupported format (%.8X) of `post' table", (unsigned int) post_format);
00412     }
00413 }
00414 
00415 static void ttf_read_loca(void)
00416 {
00417     glyph_entry *glyph;
00418     ttf_seek_tab("loca", 0);
00419     if (loca_format != 0)
00420         for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
00421             glyph->offset = get_ulong();
00422     else
00423         for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
00424             glyph->offset = get_ushort() << 1;
00425 }
00426 
00427 static void ttf_read_tabdir()
00428 {
00429     int i;
00430     dirtab_entry *tab;
00431 /*     if ((version= get_fixed()) != 0x00010000) */
00432 /*         pdftex_fail("unsupport version 0x%.8X; can handle only version 1.0", (int)version); */
00433     ttf_skip(TTF_FIXED_SIZE); /* ignore the sfnt number */
00434     dir_tab = xtalloc(ntabs = get_ushort(), dirtab_entry);
00435     ttf_skip(3*TTF_USHORT_SIZE);
00436     for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
00437         for (i = 0; i < 4; i++)
00438             tab->tag[i] = get_char();
00439         tab->checksum = get_ulong();
00440         tab->offset = get_ulong();
00441         tab->length = get_ulong();
00442     }
00443 }
00444 
00445 static void ttf_read_cmap(void)
00446 {
00447     cmap_entry *e;
00448     seg_entry *seg_tab, *s;
00449     TTF_USHORT *glyphId, format, segCount;
00450     TTF_USHORT ncmapsubtabs;
00451     long cmap_offset;
00452     long int n, i, j, k, first_code, length, last_sep, index;
00453     int unicode_map_count = 0;
00454     int select_unicode = 1; /* may be changed later if needed */
00455     ttf_seek_tab("cmap", TTF_USHORT_SIZE); /* skip the table vesrion number (=0) */
00456     ncmapsubtabs = get_ushort();
00457     cmap_offset = xftell(INFILE, cur_file_name) - 2*TTF_USHORT_SIZE;
00458     cmap_tab = xtalloc(ncmapsubtabs, cmap_entry);
00459     for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
00460         e->platform_id = get_ushort();
00461         e->encoding_id = get_ushort();
00462         e->offset = get_ulong();
00463     }
00464     for (i = 0; i < 0xFFFF; ++i)
00465         unicode_map[i] = NOGLYPH_ASSIGNED_YET;
00466     for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
00467         ttf_seek_off(cmap_offset + e->offset);
00468         format = get_ushort();
00469         if (is_unicode_mapping(e) && format == 4) {
00470             ++unicode_map_count;
00471             if (unicode_map_count == select_unicode)
00472                 goto read_unicode_mapping;
00473         }
00474         continue;
00475 read_unicode_mapping:
00476         length = get_ushort(); /* length of subtable */
00477         get_ushort(); /* skip the version number */
00478         segCount = get_ushort()/2;
00479         get_ushort(); /* skip searchRange */
00480         get_ushort(); /* skip entrySelector */
00481         get_ushort(); /* skip rangeShift */
00482         seg_tab = xtalloc(segCount, seg_entry);
00483         for (s = seg_tab; s - seg_tab < segCount; s++)
00484             s->endCode = get_ushort();
00485         get_ushort(); /* skip reversedPad */
00486         for (s = seg_tab; s - seg_tab < segCount; s++)
00487             s->startCode = get_ushort();
00488         for (s = seg_tab; s - seg_tab < segCount; s++)
00489             s->idDelta = get_ushort();
00490         for (s = seg_tab; s - seg_tab < segCount; s++)
00491             s->idRangeOffset = get_ushort();
00492         length -= 8*TTF_USHORT_SIZE + 4*segCount*TTF_USHORT_SIZE;
00493         n = length/TTF_USHORT_SIZE; /* number of glyphID's */
00494         glyphId = xtalloc(n, TTF_USHORT);
00495         for (i = 0; i < n; i++)
00496             glyphId[i] = get_ushort();
00497         for (s = seg_tab; s - seg_tab < segCount; s++) {
00498             for (i = s->startCode; i <= s->endCode; i++) {
00499                 if (i == 0xFFFF)
00500                     break;
00501                 if (s->idRangeOffset != 0xFFFF) {
00502                     if (s->idRangeOffset == 0)
00503                         index = (s->idDelta + i) & 0xFFFF;
00504                     else {
00505                         k = (i - s->startCode) + s->idRangeOffset/2 + 
00506                             (s - seg_tab) - segCount ;
00507                         assert(k >= 0 && k < n);
00508                         index = glyphId[k];
00509                         if (index != 0)
00510                             index = (index + s->idDelta) & 0xFFFF;
00511                     }
00512                     if (index >= glyphs_count)
00513                         pdftex_fail("cmap: glyph index out of range [0..%i)", glyphs_count);
00514                     if (unicode_map[i] != NOGLYPH_ASSIGNED_YET)
00515                         pdftex_fail("cmap: unicode %.4X is mapped to multiple glyphs", i);
00516                     unicode_map[i] = index;
00517                 }
00518             }
00519         }
00520         xfree(seg_tab);
00521         xfree(glyphId);
00522         break;
00523     }
00524     if (e - cmap_tab == ncmapsubtabs)
00525         pdftex_fail("Invalid argument `-m %i': out of range [1..%i]",
00526                  select_unicode, unicode_map_count);
00527     xfree(cmap_tab);
00528 }
00529 
00530 static void ttf_read_font(void)
00531 {
00532     ttf_read_tabdir();
00533     if (ttf_name_lookup("PCLT", false) == NULL)
00534         new_ntabs--;
00535     if (ttf_name_lookup("fpgm", false) == NULL)
00536         new_ntabs--;
00537     if (ttf_name_lookup("cvt ", false) == NULL)
00538         new_ntabs--;
00539     if (ttf_name_lookup("prep", false) == NULL)
00540         new_ntabs--;
00541     ttf_read_mapx();
00542     ttf_read_head();
00543     ttf_read_hhea();
00544     ttf_read_pclt();
00545     ttf_read_hmtx();
00546     ttf_read_post();
00547     ttf_read_loca();
00548     ttf_read_name();
00549     ttf_read_cmap();
00550 }
00551 
00552 static void ttf_reset_chksm(dirtab_entry *tab)
00553 {
00554     checksum = 0;
00555     tab_length = 0;
00556     tmp_ulong = 0;
00557     tab->offset = ttf_offset();
00558     if (tab->offset % 4 != 0)
00559         pdftex_warn("offset of `%4.4s' is not a multiple of 4", tab->tag);
00560 }
00561 
00562 
00563 static void ttf_set_chksm(dirtab_entry *tab)
00564 {
00565     tab->length = ttf_offset() - tab->offset;
00566     tab->checksum = ttf_getchksm();
00567 }
00568 
00569 static void ttf_copytab(const char *name)
00570 {
00571     long i;
00572     dirtab_entry *tab = ttf_seek_tab(name, 0);
00573     ttf_reset_chksm(tab);
00574     for (i = tab->length; i > 0; i--)
00575         copy_char();
00576     ttf_set_chksm(tab);
00577 }
00578 
00579 #define BYTE_ENCODING_LENGTH  \
00580     ((MAX_CHAR_CODE + 1)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE)
00581 
00582 static void ttf_byte_encoding(void)
00583 {
00584     ttfenc_entry *e;
00585     put_ushort(0);  /* format number (0: byte encoding table) */
00586     put_ushort(BYTE_ENCODING_LENGTH); /* length of table */
00587     put_ushort(0);  /* version number */
00588     for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++)
00589         if (e->newindex < 256) {
00590             put_byte(e->newindex);
00591         }
00592         else {
00593             if (e->name != notdef)
00594                 pdftex_warn("glyph `%s' has been mapped to `%s' in `ttf_byte_encoding' cmap table",
00595                             e->name, notdef);
00596             put_byte(0); /* notdef */
00597         }
00598 }
00599 
00600 #define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (MAX_CHAR_CODE + 1)))
00601 
00602 static void ttf_trimmed_table_map(void)
00603 {
00604     ttfenc_entry *e;
00605     put_ushort(6);  /* format number (6): trimmed table mapping */
00606     put_ushort(TRIMMED_TABLE_MAP_LENGTH);
00607     put_ushort(0);  /* version number (0) */
00608     put_ushort(0);  /* first character code */
00609     put_ushort(MAX_CHAR_CODE + 1);  /* number of character code in table */
00610     for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++)
00611         put_ushort(e->newindex);
00612 }
00613 
00614 #define SEG_MAP_DELTA_LENGTH ((16 + (MAX_CHAR_CODE + 1))*TTF_USHORT_SIZE)
00615 
00616 static void ttf_seg_map_delta(void)
00617 {
00618     ttfenc_entry *e;
00619     put_ushort(4);  /* format number (4: segment mapping to delta values) */
00620     put_ushort(SEG_MAP_DELTA_LENGTH);
00621     put_ushort(0);  /* version number */
00622     put_ushort(4);  /* 2*segCount */
00623     put_ushort(4);  /* searchRange */
00624     put_ushort(1);  /* entrySelector */
00625     put_ushort(0);  /* rangeShift */
00626     put_ushort(0xF0FF); /* endCount[0] */
00627     put_ushort(0xFFFF); /* endCount[1] */
00628     put_ushort(0); /* reversedPad */
00629     put_ushort(0xF000); /* startCount[0] */
00630     put_ushort(0xFFFF); /* startCount[1] */
00631     put_ushort(0); /* idDelta[0] */
00632     put_ushort(1); /* idDelta[1] */
00633     put_ushort(2*TTF_USHORT_SIZE); /* idRangeOffset[0] */
00634     put_ushort(0); /* idRangeOffset[1] */
00635     for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++)
00636         put_ushort(e->newindex);
00637 }
00638 
00639 #define CMAP_ENTRY_LENGTH (2*TTF_USHORT_SIZE + TTF_ULONG_SIZE)
00640 
00641 static void ttf_select_cmap(void)
00642 {
00643     assert(sizeof(new_cmap_tab) <= NEW_CMAP_SIZE*sizeof(cmap_entry));
00644     new_cmap_tab[0].platform_id  = 1; /* Macintosh */
00645     new_cmap_tab[0].encoding_id  = 0; /* Symbol; ignore code page */
00646     new_cmap_tab[0].format = new_glyphs_count < 256 ? 0  /* byte encoding */
00647                                                 : 6; /* trimmed table mapping */
00648     new_cmap_tab[1].platform_id  = 3; /* Microsoft */
00649     new_cmap_tab[1].encoding_id  = 0; /* Symbol; ignore code page */
00650     new_cmap_tab[1].format       = 4; /* segment mapping to delta */
00651 }
00652 
00653 static void ttf_write_cmap(void)
00654 {
00655     cmap_entry *ce;
00656     long offset;
00657     dirtab_entry *tab = ttf_name_lookup("cmap", true);
00658     ttf_select_cmap();
00659     ttf_reset_chksm(tab);
00660     put_ushort(0);  /* table version number (0) */
00661     put_ushort(NEW_CMAP_SIZE);  /* number of encoding tables */
00662     offset = 2*TTF_USHORT_SIZE + NEW_CMAP_SIZE*CMAP_ENTRY_LENGTH;
00663     for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
00664         ce->offset = offset;
00665         switch (ce->format) {
00666         case 0: 
00667             offset +=  BYTE_ENCODING_LENGTH;
00668             break;
00669         case 4: 
00670             offset +=  SEG_MAP_DELTA_LENGTH;
00671             break;
00672         case 6: 
00673             offset +=  TRIMMED_TABLE_MAP_LENGTH;
00674             break;
00675         default:
00676             pdftex_fail("invalid format (it should not have happened)");
00677         }
00678         put_ushort(ce->platform_id);
00679         put_ushort(ce->encoding_id);
00680         put_ulong(ce->offset);
00681     }
00682     for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
00683         switch (ce->format) {
00684         case 0: 
00685             ttf_byte_encoding();
00686             break;
00687         case 4: 
00688             ttf_seg_map_delta();
00689             break;
00690         case 6: 
00691             ttf_trimmed_table_map();
00692             break;
00693         }
00694     }
00695     ttf_set_chksm(tab);
00696 }
00697 
00698 static int prepend_subset_tags(int index, char *p)
00699 {
00700     boolean is_unicode = (name_tab[index].platform_id == 3);
00701     int i;
00702     assert(index > 0 && index < name_record_num && fm_cur->subset_tag != NULL);
00703     if (is_unicode) {
00704         for (i = 0; i < 6; ++i) {
00705             *p++ = 0;
00706             *p++ = fm_cur->subset_tag[i];
00707         }
00708         *p++ = 0;
00709         *p++ = '+';
00710         return 14;
00711     } else {
00712         strncpy(p, fm_cur->subset_tag, 6);
00713         p += 6;
00714         *p++ = '+';
00715         return 7;
00716     }
00717 }
00718 
00719 
00720 static void ttf_write_name(void)
00721 {
00722     int i, l;
00723     char *p;
00724     int new_name_buf_size;
00725     char *new_name_buf;
00726     name_record *n;
00727     dirtab_entry *tab = ttf_name_lookup("name", true);
00728     if (is_subsetted(fm_cur)) {
00729         l = 0;
00730         for (i = 0; i < name_record_num; i++)
00731             l += name_tab[i].length + 14; /* maximum lengh of new stogare area */
00732         new_name_buf = xtalloc(l, char);
00733         /* additional space for subset tags */
00734         p = new_name_buf;
00735         for (i = 0; i < name_record_num; i++) {
00736             n = name_tab + i;
00737             n->new_offset = p - new_name_buf;
00738             if ((n->name_id == 1 || n->name_id == 3 ||
00739                  n->name_id == 4 || n->name_id == 6) &&
00740                 ((n->platform_id == 1 && n->encoding_id == 0) ||
00741                  (n->platform_id == 3 && n->encoding_id == 0) ||
00742                  (n->platform_id == 3 && n->encoding_id == 1)))
00743             {
00744                 l = prepend_subset_tags(i, p);
00745                 p += l;
00746             }
00747             else 
00748                 l = 0;
00749             memcpy(p, name_buf + n->offset, n->length);
00750             p += n->length;
00751             n->new_length = n->length + l;
00752         }
00753         new_name_buf_size = p - new_name_buf;
00754     }
00755     else {
00756         new_name_buf = name_buf;
00757         new_name_buf_size = name_buf_size;
00758     }
00759     ttf_reset_chksm(tab);
00760     put_ushort(0); /* Format selector */
00761     put_ushort(name_record_num);
00762     put_ushort(3*TTF_USHORT_SIZE + name_record_num*6*TTF_USHORT_SIZE);
00763     for (i = 0; i < name_record_num; i++) {
00764         put_ushort(name_tab[i].platform_id);
00765         put_ushort(name_tab[i].encoding_id);
00766         put_ushort(name_tab[i].language_id);
00767         put_ushort(name_tab[i].name_id);
00768         put_ushort(name_tab[i].new_length);
00769         put_ushort(name_tab[i].new_offset);
00770     }
00771     for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++)
00772          put_char(*p);
00773     ttf_set_chksm(tab);
00774     if (new_name_buf != name_buf)
00775         xfree(new_name_buf);
00776 }
00777 
00778 static void ttf_write_dirtab(void)
00779 {
00780     dirtab_entry *tab;
00781     TTF_ULONG i, k;
00782     char *p;
00783     integer save_offset = ttf_offset();
00784     ttf_seek_outbuf(TABDIR_OFF);
00785     if (is_subsetted(fm_cur)) {
00786         for (i = 0; i < DEFAULT_NTABS; i++) {
00787             tab = ttf_name_lookup(newtabnames[i], false);
00788             if (tab == NULL)
00789                 continue;
00790             for (k = 0; k < 4; k++)
00791                put_char(tab->tag[k]);
00792             put_ulong(tab->checksum);
00793             put_ulong(tab->offset);
00794             put_ulong(tab->length);
00795         }
00796     }
00797     else {
00798         for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
00799             for (k = 0; k < 4; k++)
00800                put_char(tab->tag[k]);
00801             put_ulong(tab->checksum);
00802             put_ulong(tab->offset);
00803             put_ulong(tab->length);
00804         }
00805     }
00806     /* adjust checkSumAdjustment */
00807     tmp_ulong = 0;
00808     checksum = 0;
00809     for (p = fb_array, i = 0; i < save_offset;) {
00810         tmp_ulong = (tmp_ulong << 8) + *p++;
00811         i++;
00812         if (i % 4 == 0) {
00813             checksum += tmp_ulong;
00814             tmp_ulong = 0;
00815         }
00816     }
00817     if (i % 4 != 0) {
00818         pdftex_warn("font length is not a multiple of 4 (%li)", i);
00819         checksum <<= 8*(4 - i % 4);
00820     }
00821     k = 0xB1B0AFBA - checksum;
00822     ttf_seek_outbuf(checkSumAdjustment_offset);
00823     put_ulong(k);
00824     ttf_seek_outbuf(save_offset);
00825 }
00826 
00827 static void ttf_write_glyf(void)
00828 {
00829     short *id, k;
00830     TTF_USHORT idx;
00831     TTF_USHORT flags;
00832     dirtab_entry *tab = ttf_name_lookup("glyf", true);
00833     long glyf_offset = tab->offset;
00834     long new_glyf_offset = ttf_offset();
00835     ttf_reset_chksm(tab);
00836     for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
00837         glyph_tab[*id].newoffset = ttf_offset() - new_glyf_offset;
00838         if (glyph_tab[*id].offset != glyph_tab[*id + 1].offset) {
00839             ttf_seek_off(glyf_offset + glyph_tab[*id].offset);
00840             k = copy_short();
00841             ttf_ncopy(4*TTF_FWORD_SIZE);
00842             if (k < 0) {
00843                 do {
00844                     flags = copy_ushort();
00845                     idx = get_ushort();
00846                     if (glyph_tab[idx].newindex < 0) {
00847                         glyph_tab[idx].newindex = new_glyphs_count;
00848                         glyph_index[new_glyphs_count++] = idx;
00849                         /* 
00850                             N.B.: Here we change `new_glyphs_count',
00851                             which appears in the condition of the `for' loop
00852                         */
00853                     }
00854                     put_ushort(glyph_tab[idx].newindex);
00855                     if (flags & ARG_1_AND_2_ARE_WORDS)
00856                         ttf_ncopy(2*TTF_SHORT_SIZE);
00857                     else
00858                         ttf_ncopy(TTF_USHORT_SIZE);
00859                     if (flags & WE_HAVE_A_SCALE)
00860                         ttf_ncopy(TTF_F2DOT14_SIZE);
00861                     else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
00862                         ttf_ncopy(2*TTF_F2DOT14_SIZE);
00863                     else if (flags & WE_HAVE_A_TWO_BY_TWO)
00864                         ttf_ncopy(4*TTF_F2DOT14_SIZE);
00865                 } while (flags & MORE_COMPONENTS);
00866                 if (flags & WE_HAVE_INSTRUCTIONS)
00867                     ttf_ncopy(copy_ushort());
00868             }
00869             else
00870                 ttf_ncopy(glyph_tab[*id + 1].offset - glyph_tab[*id].offset - 
00871                     TTF_USHORT_SIZE - 4*TTF_FWORD_SIZE);
00872         }
00873     }
00874     last_glyf_offset = ttf_offset() - new_glyf_offset;
00875     ttf_set_chksm(tab);
00876 }
00877 
00878 static void ttf_reindex_glyphs(void)
00879 {
00880     ttfenc_entry *e;
00881     glyph_entry *glyph;
00882     unsigned int index;
00883     /* 
00884      * reindexing glyphs: we append index of used glyphs to `glyph_index'
00885      * while going through `ttfenc_tab'. After appending a new entry to
00886      * `glyph_index' we set field `newindex' of corresponding entries in both
00887      * `glyph_tab' and `ttfenc_tab' to the newly created index
00888      * 
00889      */
00890     for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++) {
00891         e->newindex = 0; /* index of ".notdef" glyph */
00892         if (e->name == notdef)
00893             continue;
00894         /* scan form `index123' */
00895         if (sscanf(e->name,  GLYPH_PREFIX_INDEX "%i", &index) == 1) {
00896             if (index >= glyphs_count) {
00897                 pdftex_warn("`%s' out of valid range [0..%i)",
00898                             e->name, glyphs_count);
00899                 continue;
00900             }
00901             glyph = glyph_tab + index;
00902             goto append_new_glyph;
00903         }
00904         /* scan form `uniABCD' */
00905         if (sscanf(e->name, GLYPH_PREFIX_UNICODE "%X", &index) == 1) {
00906             assert(index <= 0xFFFF);
00907             if (unicode_map[index] != NOGLYPH_ASSIGNED_YET) {
00908                 if (unicode_map[index] >= glyphs_count) {
00909                     pdftex_warn("`%s' is mapped to index %i which is out of valid range [0..%i)",
00910                                 e->name, unicode_map[index], glyphs_count);
00911                     continue;
00912                 }
00913                 glyph = glyph_tab + unicode_map[index];
00914                 goto append_new_glyph;
00915             }
00916             else {
00917                 pdftex_warn("`unicode %s%.4X' is not mapped to any glyph", 
00918                             GLYPH_PREFIX_UNICODE, index);
00919                 continue;
00920             }
00921         }
00922         /* look up by name */
00923         for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++)
00924             if (glyph->name != notdef && strcmp(glyph->name, e->name) == 0)
00925                 break;
00926         if (!(glyph - glyph_tab < glyphs_count)) {
00927             pdftex_warn("glyph `%s' not found", e->name);
00928             continue;
00929         }
00930 append_new_glyph:
00931         assert(glyph - glyph_tab < glyphs_count);
00932         if (glyph->newindex < 0) {
00933             glyph_index[new_glyphs_count] = glyph - glyph_tab;
00934             glyph->newindex = new_glyphs_count;
00935             new_glyphs_count++;
00936         }
00937         e->newindex = glyph->newindex;
00938     }
00939 }
00940  
00941 static void ttf_write_head()
00942 {
00943     dirtab_entry *tab;
00944     tab = ttf_seek_tab("head", 0);
00945     ttf_reset_chksm(tab);
00946     ttf_ncopy(2*TTF_FIXED_SIZE);
00947     checkSumAdjustment_offset = ttf_offset();
00948     put_ulong(0);
00949     ttf_skip(TTF_ULONG_SIZE); /* skip checkSumAdjustment */
00950     ttf_ncopy(TTF_ULONG_SIZE + 2*TTF_USHORT_SIZE + 16 + 
00951         4*TTF_FWORD_SIZE + 2*TTF_USHORT_SIZE + TTF_SHORT_SIZE);
00952     if (is_subsetted(fm_cur))  {
00953         put_short(loca_format);
00954         put_short(0);
00955     }
00956     else
00957         ttf_ncopy(2*TTF_SHORT_SIZE);
00958     ttf_set_chksm(tab);
00959 }
00960  
00961 static void ttf_write_hhea(void)
00962 {
00963     dirtab_entry *tab;
00964     tab = ttf_seek_tab("hhea", 0);
00965     ttf_reset_chksm(tab);
00966     ttf_ncopy(TTF_FIXED_SIZE + 3*TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3*TTF_FWORD_SIZE + 8*TTF_SHORT_SIZE);
00967     put_ushort(new_glyphs_count);
00968     ttf_set_chksm(tab);
00969 }
00970 
00971 static void ttf_write_htmx(void)
00972 {
00973     short *id;
00974     dirtab_entry *tab = ttf_seek_tab("hmtx", 0);
00975     ttf_reset_chksm(tab);
00976     for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
00977         put_ufword(glyph_tab[*id].advWidth);
00978         put_ufword(glyph_tab[*id].lsb);
00979     }
00980     ttf_set_chksm(tab);
00981 }
00982 
00983 static void ttf_write_loca(void)
00984 {
00985     short *id;
00986     dirtab_entry *tab = ttf_seek_tab("loca", 0);
00987     ttf_reset_chksm(tab);
00988     loca_format = 0;
00989     if (last_glyf_offset >= 0x00020000 || (last_glyf_offset & 1))
00990         loca_format = 1;
00991     else
00992         for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
00993             if (glyph_tab[*id].newoffset & 1) {
00994                 loca_format = 1;
00995                 break;
00996             }
00997     if (loca_format != 0) {
00998         for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
00999             put_ulong(glyph_tab[*id].newoffset);
01000         put_ulong(last_glyf_offset);
01001     }
01002     else {
01003         for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
01004             put_ushort(glyph_tab[*id].newoffset/2);
01005         put_ushort(last_glyf_offset/2);
01006     }
01007     ttf_set_chksm(tab);
01008 }
01009 
01010 static void ttf_write_mapx(void)
01011 {
01012     dirtab_entry *tab = ttf_seek_tab("maxp", TTF_FIXED_SIZE + TTF_USHORT_SIZE);
01013     ttf_reset_chksm(tab);
01014     put_fixed(0x00010000);
01015     put_ushort(new_glyphs_count);
01016     ttf_ncopy(13*TTF_USHORT_SIZE);
01017     ttf_set_chksm(tab);
01018 }
01019 
01020 static void ttf_write_OS2(void)
01021 {
01022     dirtab_entry *tab = ttf_seek_tab("OS/2", 0);
01023     TTF_USHORT version;
01024     ttf_reset_chksm(tab);
01025     version = get_ushort();
01026     if (version != 0x0000 && version != 0x0001 && version != 0x0002)
01027         pdftex_fail("unknown verssion of OS/2 table (%.4X)", version);
01028     put_ushort(0x0001); /* fix version to 1*/
01029     ttf_ncopy(2*TTF_USHORT_SIZE + 13*TTF_SHORT_SIZE + 10*TTF_BYTE_SIZE);
01030     ttf_skip(4*TTF_ULONG_SIZE); /* ulUnicodeRange 1--4 */
01031     put_ulong(0x00000003); /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */
01032     put_ulong(0x10000000); /* Private Use (0xE000--0xF8FF) */
01033     put_ulong(0x00000000);
01034     put_ulong(0x00000000);
01035     ttf_ncopy(4*TTF_CHAR_SIZE + TTF_USHORT_SIZE); /* achVendID + fsSelection */
01036     ttf_skip(2*TTF_USHORT_SIZE);
01037     put_ushort(0x0000); /* usFirstCharIndex */
01038     put_ushort(0xF0FF); /* usLastCharIndex */
01039     ttf_ncopy(5*TTF_USHORT_SIZE);
01040     /* for version 0 the OS/2 table ends here, the rest is for version 1 */ 
01041     put_ulong(0x80000000); /* Symbol Character Set---don't use any code page */
01042     put_ulong(0x00000000);
01043     ttf_set_chksm(tab);
01044 }
01045 
01046 static boolean unsafe_name(char *s)
01047 {
01048     const char **p;
01049     for (p = ambiguous_names; *p != NULL; p++)
01050         if (strcmp(s, *p) == 0)
01051             return true;
01052     return false;
01053 }
01054 
01055 static void ttf_write_post(void)
01056 {
01057     dirtab_entry *tab = ttf_seek_tab("post", TTF_FIXED_SIZE);
01058     glyph_entry *glyph;
01059     char *s;
01060     short *id;
01061     int l;
01062     ttf_reset_chksm(tab);
01063     if (!write_ttf_glyph_names || post_format == 0x00030000) {
01064         put_fixed(0x00030000);
01065         ttf_ncopy(TTF_FIXED_SIZE + 2*TTF_FWORD_SIZE + 5*TTF_ULONG_SIZE);
01066     }
01067     else {
01068         put_fixed(0x00020000);
01069         ttf_ncopy(TTF_FIXED_SIZE + 2*TTF_FWORD_SIZE + 5*TTF_ULONG_SIZE);
01070         put_ushort(new_glyphs_count);
01071         k = 0;
01072         for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
01073             glyph = glyph_tab + *id;
01074             if (glyph->name_index >= NMACGLYPHS || unsafe_name(glyph->name))
01075                 glyph->name_index = NMACGLYPHS + k++;
01076             put_ushort(glyph->name_index);
01077         }
01078         for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
01079             glyph = glyph_tab + *id;
01080             if (glyph->name_index >= NMACGLYPHS) {
01081                 s = glyph->name;
01082                 l = strlen(s);
01083                 put_byte(l);
01084                 while (l-- > 0)
01085                     put_char(*s++);
01086             }
01087         }
01088     }
01089     ttf_set_chksm(tab);
01090 }
01091 
01092 static void ttf_init_font(int n)
01093 {
01094     int i, k;
01095     for (i = 1, k = 0; i <= n; i <<= 1, k++);
01096     put_fixed(0x00010000); /* font version */
01097     put_ushort(n); /* number of tables */
01098     put_ushort(i << 3); /* search range */
01099     put_ushort(k - 1); /* entry selector */
01100     put_ushort((n<<4) - (i<<3)); /* range shift */
01101     ttf_seek_outbuf(TABDIR_OFF + n*4*TTF_ULONG_SIZE);
01102 }
01103 
01104 static void ttf_subset_font(void)
01105 {
01106     ttf_init_font(new_ntabs);
01107     if (ttf_name_lookup("PCLT", false) != NULL)
01108         ttf_copytab("PCLT");
01109     if (ttf_name_lookup("fpgm", false) != NULL)
01110         ttf_copytab("fpgm");
01111     if (ttf_name_lookup("cvt ", false) != NULL)
01112         ttf_copytab("cvt ");
01113     if (ttf_name_lookup("prep", false) != NULL)
01114         ttf_copytab("prep");
01115     ttf_reindex_glyphs();
01116     ttf_write_glyf();
01117     ttf_write_loca();
01118     ttf_write_OS2();
01119     ttf_write_head();
01120     ttf_write_hhea();
01121     ttf_write_htmx();
01122     ttf_write_mapx();
01123     ttf_write_name();
01124     ttf_write_post();
01125     ttf_write_cmap();
01126     ttf_write_dirtab();
01127 }
01128 
01129 static void ttf_copy_font(void)
01130 {
01131     dirtab_entry *tab;
01132     ttf_init_font(ntabs);
01133     for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
01134         if (strncmp(tab->tag, "head", 4) == 0)
01135             ttf_write_head();
01136         else
01137             ttf_copytab(tab->tag);
01138     }
01139     ttf_write_dirtab();
01140 }
01141 
01142 void writettf()
01143 {
01144     set_cur_file_name(fm_cur->ff_name);
01145     if (is_subsetted(fm_cur) && !(is_reencoded(fm_cur))) {
01146         pdftex_warn("encoding vector required for TrueType font subsetting");
01147         cur_file_name = NULL;
01148         return;
01149     }
01150     if (!ttf_open()) {
01151         pdftex_fail("cannot open TrueType font file for reading");
01152     }
01153     cur_file_name = (char*)nameoffile + 1;
01154     if (!is_included(fm_cur))
01155         tex_printf("{%s", cur_file_name);
01156     else if (is_subsetted(fm_cur))
01157         tex_printf("<%s", cur_file_name);
01158     else
01159         tex_printf("<<%s", cur_file_name);
01160     fontfile_found = true;
01161     new_glyphs_count = 2;
01162     new_ntabs = DEFAULT_NTABS;
01163     dir_tab = NULL;
01164     glyph_tab = NULL;
01165     glyph_index = NULL;
01166     glyph_name_buf = NULL;
01167     name_tab = NULL;
01168     name_buf = NULL;
01169     ttf_read_font();
01170     if (is_included(fm_cur)) {
01171         pdfsaveoffset = pdfoffset();
01172         pdfflush();
01173         if (is_subsetted(fm_cur)) {
01174             ttf_copy_encoding();
01175             make_subset_tag(fm_cur, fm_cur->encoding->glyph_names);
01176             ttf_subset_font();
01177         }
01178         else
01179             ttf_copy_font();
01180         ttf_length = ttf_offset();
01181     }
01182     xfree(dir_tab);
01183     xfree(glyph_tab);
01184     xfree(glyph_index);
01185     xfree(glyph_name_buf);
01186     xfree(name_tab);
01187     xfree(name_buf);
01188     ttf_close();
01189     if (!is_included(fm_cur))
01190         tex_printf("}");
01191     else if (is_subsetted(fm_cur))
01192         tex_printf(">");
01193     else
01194         tex_printf(">>");
01195     cur_file_name = NULL;
01196 }
01197 
01198 void writeotf()
01199 {
01200     dirtab_entry *tab;
01201     long i;
01202     set_cur_file_name(fm_cur->ff_name);
01203     if (!open_input(&ttf_file, kpse_type1_format, FOPEN_RBIN_MODE)) {
01204         pdftex_fail("cannot open OpenType font file for reading");
01205     }
01206     cur_file_name = (char*)nameoffile + 1;
01207     tex_printf("<<%s", cur_file_name);
01208     fontfile_found = true;
01209     dir_tab = NULL;
01210     glyph_tab = NULL;
01211     ttf_read_tabdir();
01212     /* read font parameters */
01213     if (ttf_name_lookup("head", false) != NULL)
01214         ttf_read_head();
01215     if (ttf_name_lookup("hhea", false) != NULL)
01216         ttf_read_hhea();
01217     if (ttf_name_lookup("PCLT", false) != NULL)
01218         ttf_read_pclt();
01219     if (ttf_name_lookup("post", false) != NULL)
01220         ttf_read_post();
01221     /* copy font file */
01222     tab = ttf_seek_tab("CFF ", 0);
01223     for (i = tab->length; i > 0; i--)
01224         copy_char();
01225     xfree(dir_tab);
01226     ttf_close();
01227     tex_printf(">>");
01228     cur_file_name = NULL;
01229 }
01230 
01231 /*
01232  To calculate the checkSum for the 'head' table which itself includes the
01233    checkSumAdjustment entry for the entire font, do the following:
01234 
01235      * Set the checkSumAdjustment to 0.
01236      * Calculate the checksum for all the tables including the 'head' table
01237        and enter that value into the table directory.
01238      * Calculate the checksum for the entire font.
01239      * Subtract that value from the hex value B1B0AFBA.
01240      * Store the result in checkSumAdjustment.
01241 
01242    The checkSum for the 'head table which includes the checkSumAdjustment
01243    entry for the entire font is now incorrect. That is not a problem. Do not
01244    change it. An application attempting to verify that the 'head' table has
01245    not changed should calculate the checkSum for that table by not including
01246    the checkSumAdjustment value, and compare the result with the entry in the
01247    table directory.
01248 
01249    The table directory also includes the offset of the associated tagged
01250    table from the beginning of the font file and the length of that table.
01251 
01252 
01253  */