/* * ttindex.c * * 15 Oct. 1993 by I.Matsuda * 14 Nov. 1993 Slightly modified by I. Matsuda (Ver 0.2) * 19 Jan. 1994 UNIX version for VFlib. * 26 Jan. 1994 Slightly modified by I. Matsuda * 11 Feb. 1994 Slightly modified by I. Matsuda * 9 May 1994 Support for shift-JIS encoding (Special thanks to iW) * 21 Oct. 1995 Support for new .ttc fonts used in WIN95. (Ver.0.4) * 10 Apr. 1996 Support for DynaFont by Shigeru Makino. * 28 Apr. 1996 Support for Dynafont by k-chinen. * (for fonts whose mappingTable.format is 2) */ /* This file is part of VFlib * * Copyright (C) 1995,1996 Hirotsugu KAKUGAWA. All rights reserved. * * VFlib is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY. No author or distributor accepts responsibility * to anyone for the consequences of using it or for whether it serves any * particular purpose or works at all, unless he says so in writing. Refer * to the GNU General Public License for full details. * * Everyone is granted permission to copy, modify and redistribute * VFlib, but only under the conditions described in the GNU * General Public License. A copy of this license is supposed to have been * given to you along with VFlib so you can know your rights and * responsibilities. It should be in a file named COPYING. Among other * things, the copyright notice and this notice must be preserved on all * copies. */ /* * Define `OS2FONT' if you use japanese fonts for OS2. */ /*#define OS2FONT*/ #include #include #include #if __TURBOC__ # include # include /* #else # include */ #endif #include #include "ttindex.h" #ifndef SEEK_SET # define SEEK_SET 0 #endif TTI_HEADER tti_header; CharToIndexFormat4 C2Index; #ifdef PROTOTYPE Int16 fget16(FILE *fp); void fput16(Int16 num, FILE *fp); Int32 fget32(FILE *fp); void fput32(Int32 num, FILE *fp); void FAR *alloc_buff(unsigned int size); void ReadFontheader(Int32 Offset, FILE *fp); void ReadMaxprofile(Int32 Offset, FILE *fp); void ReadCharToIndexMap(Int32 Offset, FILE *fp); UInt16 CharToIndex(UInt16 ch, FILE *fp); void ShowFontname(Int32 Offset, FILE *fp); UInt16 jis2uni(int ku, int ten); UInt16 jis2sjis(int ku, int ten); void usage(void); UInt16 (*codeconv)(int ku, int ten) = jis2uni; UInt16 jis2uni(int, int); UInt16 jis2sjis(int, int); #else UInt16 jis2uni(); UInt16 jis2sjis(); UInt16 (*codeconv)() = jis2uni; #endif /* read 2 bytes */ Int16 fget16(fp) FILE *fp; { Int16 c[2]; Int16 num; c[0] = (Int16)getc(fp); c[1] = (Int16)getc(fp); num = (c[0] << 8) | (c[1] & 0xff); return (num); } /* write 2 bytes */ void fput16(num, fp) Int16 num; FILE *fp; { #if 0 int c[2]; c[0] = (num >> 8) & 0x00ff; c[1] = num & 0x00ff; fputc(c[0], fp); fputc(c[1], fp); return; #else unsigned char z[2]; z[0] = (unsigned char)(((UInt16)num >> 8) & 0x00ff); z[1] = (unsigned char)(((UInt16)num ) & 0x00ff); fwrite(z, 1, 2, fp); #endif } /* read 4 bytes */ Int32 fget32(fp) FILE *fp; { Int32 num; Int32 c[2]; c[0] = (Int32)fget16(fp); c[1] = (Int32)fget16(fp); num = (c[0] << 16) | (c[1] & 0xffff); return (num); } /* write 4 bytes */ void fput32(num, fp) Int32 num; FILE *fp; { UInt16 c[2]; c[0] = (num >> 16) & 0xffff; c[1] = num & 0xffff; fput16(c[0], fp); fput16(c[1], fp); return; } /* memory allocation */ void FAR * alloc_buff(size) unsigned size; { void FAR *p; if ((p = (void FAR *)MALLOC(size)) == NULL) { fprintf(stderr, "Not enough memory.\n"); exit(1); } return (p); } /* read Font Header table */ void ReadFontheader(Offset, fp) Int32 Offset; FILE *fp; { long seekp; sfnt_FontHeader FontHeader; seekp = ftell(fp); fseek(fp, Offset, SEEK_SET); FontHeader.version = fget32(fp); FontHeader.fontRevision = fget32(fp); FontHeader.checkSumAdjustment = fget32(fp); FontHeader.magicNumber = fget32(fp); if (FontHeader.magicNumber != 0x5F0F3CF5L) { fprintf(stderr, "Invalid Magic Number in font header table 'head'.\n"); exit(1); } FontHeader.flags = fget16(fp); FontHeader.unitsPerEm = fget16(fp); FontHeader.created.bc = fget32(fp); FontHeader.created.ad = fget32(fp); FontHeader.modified.bc = fget32(fp); FontHeader.modified.ad = fget32(fp); FontHeader.xMin = fget16(fp); FontHeader.yMin = fget16(fp); FontHeader.xMax = fget16(fp); FontHeader.yMax = fget16(fp); FontHeader.macStyle = fget16(fp); FontHeader.lowestRecPPEM = fget16(fp); FontHeader.fontDirectionHint = fget16(fp); FontHeader.indexToLocFormat = fget16(fp); FontHeader.glyphDataFormat = fget16(fp); tti_header.unitsPerEm = FontHeader.unitsPerEm; tti_header.xMin = FontHeader.xMin; tti_header.yMin = FontHeader.yMin; fseek(fp, seekp, SEEK_SET); return; } /* read Maximum Profile table */ void ReadMaxprofile(Offset, fp) Int32 Offset; FILE *fp; { long seekp; sfnt_maxProfileTable MaxProfile; seekp = ftell(fp); fseek(fp, Offset, SEEK_SET); MaxProfile.version = fget32(fp); MaxProfile.numGlyphs = fget16(fp); MaxProfile.maxPoints = fget16(fp); MaxProfile.maxContours = fget16(fp); MaxProfile.maxCompositePoints = fget16(fp); MaxProfile.maxCompositeContours = fget16(fp); MaxProfile.maxElements = fget16(fp); MaxProfile.maxTwilightPoints = fget16(fp); MaxProfile.maxStorage = fget16(fp); MaxProfile.maxFunctionDefs = fget16(fp); MaxProfile.maxInstructionDefs = fget16(fp); MaxProfile.maxStackElements = fget16(fp); MaxProfile.maxSizeOfInstructions = fget16(fp); MaxProfile.maxComponentElements = fget16(fp); MaxProfile.maxComponentDepth = fget16(fp); #if 0 if (MaxProfile.maxComponentElements > 1) { fprintf(stderr, "Sorry, can't use this font " "(composite glyphs are not supported).\n"); exit(1); } #endif tti_header.maxPoints = MaxProfile.maxPoints; tti_header.maxContours = MaxProfile.maxContours; fseek(fp, seekp, SEEK_SET); return; } /* read cmap table */ void ReadCharToIndexMap(Offset, fp) Int32 Offset; FILE *fp; { int i, j, k; int u, v, s, t; int segCount; long seekp, seekpp; sfnt_char2IndexDirectory char2IndexDirectory; sfnt_platformEntry *platformEntry; sfnt_mappingTable mappingTable; int segno[256]; seekp = ftell(fp); fseek(fp, Offset, SEEK_SET); char2IndexDirectory.version = fget16(fp); char2IndexDirectory.numTables = fget16(fp); platformEntry = char2IndexDirectory.platform; for (i = 0; i < char2IndexDirectory.numTables; i++) { platformEntry->platformID = fget16(fp); platformEntry->specificID = fget16(fp); platformEntry->offset = fget32(fp); seekpp = ftell(fp); fseek(fp, Offset + platformEntry->offset, SEEK_SET); mappingTable.format = fget16(fp); mappingTable.length = fget16(fp); mappingTable.version = fget16(fp); if (mappingTable.format == 4) { if (platformEntry->specificID == 2) codeconv = jis2sjis; C2Index.segCountX2 = fget16(fp); C2Index.searchRange = fget16(fp); C2Index.entrySelector = fget16(fp); C2Index.rangeShift = fget16(fp); C2Index.endCount = (UInt16 FAR *)alloc_buff(C2Index.segCountX2); C2Index.startCount = (UInt16 FAR *)alloc_buff(C2Index.segCountX2); C2Index.idDelta = (UInt16 FAR *)alloc_buff(C2Index.segCountX2); C2Index.idRangeOffset = (UInt16 FAR *)alloc_buff(C2Index.segCountX2); segCount = C2Index.segCountX2 / 2; for (j = 0; j < segCount; j++) { C2Index.endCount[j] = fget16(fp); } fget16(fp); for (j = 0; j < segCount; j++) { C2Index.startCount[j] = fget16(fp); } for (j = 0; j < segCount; j++) { C2Index.idDelta[j] = fget16(fp); } C2Index.idRangeBase = ftell(fp); for (j = 0; j < segCount; j++) { C2Index.idRangeOffset[j] = fget16(fp); } fseek(fp, seekp, SEEK_SET); return; } if (mappingTable.format == 2) { /* * Dynafont use this format. * I(k-chinen) test with 'dfgot_ub.ttf'. */ if (platformEntry->specificID == 1) codeconv = jis2sjis; segCount = 0; for(j = 0; j < 256; j++) { k = fget16(fp)/8; if( k > segCount) { segCount = k; } if(k>0) segno[k] = j; } segCount++; C2Index.segCountX2 = segCount * 2; C2Index.endCount = (UInt16 FAR *)alloc_buff(sizeof(UInt16)*segCount); C2Index.startCount = (UInt16 FAR *)alloc_buff(sizeof(UInt16)*segCount); C2Index.idDelta = (UInt16 FAR *)alloc_buff(sizeof(UInt16)*segCount); C2Index.idRangeOffset = (UInt16 FAR *)alloc_buff(sizeof(UInt16)*segCount); for (j = 0; j < segCount; j++) { u = fget16(fp); v = fget16(fp); s = fget16(fp); t = fget16(fp); C2Index.startCount[j] = ((segno[j] & 0xff) << 8 ) + u; C2Index.endCount[j] = ((segno[j] & 0xff) << 8 ) + u + v; C2Index.idDelta[j] = s; C2Index.idRangeOffset[j] = t + j*6 - (segCount-1)*8 - 2; } C2Index.idRangeBase = ftell(fp); fseek(fp, seekp, SEEK_SET); return; } fseek(fp, seekpp, SEEK_SET); } fprintf(stderr, "Sorry, can't use this font (no Char2Index table of format 2 or 4).\n"); exit(1); } /* character -> index code */ UInt16 CharToIndex(ch, fp) UInt16 ch; FILE *fp; { int i, segCount, segment; UInt16 Index; segment = -1; segCount = C2Index.segCountX2 / 2; for (i = 0; i < segCount; i++) { if (ch <= C2Index.endCount[i]) { if (ch >= C2Index.startCount[i]) { segment = i; } break; } } if (segment < 0) { /* no segment */ Index = 0; } else if (C2Index.idRangeOffset[i] == 0) { Index = (ch + C2Index.idDelta[i]) & 0xffff; } else { Index = (C2Index.idRangeOffset[i] / 2 + ch - C2Index.startCount[i]) & 0xffff; fseek(fp, C2Index.idRangeBase + (i + Index) * 2, SEEK_SET); Index = (fget16(fp) + C2Index.idDelta[i]) & 0xffff; } return Index; } /* get font name */ void ShowFontname(Offset, fp) Int32 Offset; FILE *fp; { #define MAX_STR 256 static char *nameID[] = { "Copyright", "Family", "Subfamily", "UniqueName", "FullName", "Version", "Postscript", "Trademark" }; sfnt_NamingTable NamingTable; sfnt_NameRecord NameRecord; int i, length; long seekp, seekpp, stringOffset; char str[MAX_STR]; seekp = ftell(fp); fseek(fp, Offset, SEEK_SET); NamingTable.format = fget16(fp); NamingTable.count = fget16(fp); NamingTable.stringOffset = fget16(fp); for (i = 0; i < NamingTable.count; i++) { NameRecord.platformID = fget16(fp); NameRecord.specificID = fget16(fp); NameRecord.languageID = fget16(fp); NameRecord.nameID = fget16(fp); NameRecord.length = length = fget16(fp); NameRecord.offset = fget16(fp); if (NameRecord.platformID == plat_Macintosh) { /* ShiftJIS */ #ifndef __MSDOS__ if ((NameRecord.nameID != 0) && (NameRecord.nameID != 6)) break; #endif if (length >= MAX_STR) length = MAX_STR - 1; seekpp = ftell(fp); stringOffset = Offset + NamingTable.stringOffset + NameRecord.offset; fseek(fp, stringOffset, SEEK_SET); fread(str, length, 1, fp); str[length] = '\0'; printf("%-10s : %s\n", nameID[NameRecord.nameID], str); fseek(fp, seekpp, SEEK_SET); } } fseek(fp, seekp, SEEK_SET); return; } /* JIS (ku-ten) -> unicode */ UInt16 jis2uni(ku, ten) int ku; int ten; { if (ku > MAXJIS) return (0); if (ten < 1 || ten > 94) return (0); return (UnicodeTbl[ku - 1][ten - 1]); } /* JIS (ku-ten) -> shift-JIS */ UInt16 ols_jis2sjis(ku, ten) int ku; int ten; { int ch, cl; if (ku > 92) return (0); if (ten < 1 || ten > 94) return (0); if (ku & 1) { cl = ten + 0x3f; if (ten > 63) cl++; } else { cl = ten + 0x9e; } ch = (ku - 1) / 2 + 0x81; if (ku > 62) ch += 0x40; return ((ch << 8) + cl); } UInt16 jis2sjis(jk, jt) int jk; int jt; { UInt16 s1, s2; UInt16 ret; if(jk<1 || jk>94) return 0; if(jk>=1 && jk<=62) s1 = (UInt16)(jk-1)/2 + (UInt16)0x81; else if(jk>=63 && jk<=94) s1 = (UInt16)(jk-1)/2 + (UInt16)0xc1; else { fprintf(stderr, "jis2sjis: ??? strange 1 ku %d\n", jk); exit(1); } if((jk & 1) !=0 ) { if(jt>=1 && jt<=63) s2 = (UInt16)jt + (UInt16)0x3f; else if(jt>=64 && jt<=94) s2 = (UInt16)jt + (UInt16)0x40; else { fprintf(stderr, "jis2sjis: ??? strange 2 ten %d\n", jt); exit(1); } } else { s2 = (UInt16)jt + (UInt16)0x9e; } ret = (s1 << 8) + s2; return ret; } void usage() { fprintf(stderr, "\t<<< ttindex: Make TrueType index file for dviout/dviprt/VFlib >>>\n"); fprintf(stderr, "\t\t\tVer 0.4 written by I.Matsuda, Oct. 21, 1995\n\n"); fprintf(stderr, "Usage: ttindex file.[ttf|ttc]\n"); exit(1); } int main(argc, argv) int argc; char **argv; { FILE *fp_ttf, *fp_tti; int i, ku, ten, len; UInt16 code, index; char *name, *extp; char tmp[5]; sfnt_OffsetTable OffsetTable; sfnt_DirectoryEntry DirectoryEntry; if (argc != 2) usage(); len = strlen(argv[1]); name = (char *)malloc(len + 5); strcpy(name, argv[1]); for (i = len;; i--) { if (name[i] == '/' || name[i] == '\\' || i == 0) { extp = &name[len]; break; } if (name[i] == '.') { extp = &name[i]; break; } } if ((fp_ttf = fopen(name, "rb")) == NULL) { if (*extp == '\0') { strcpy(extp, ".ttf"); fp_ttf = fopen(name, "rb"); } } if (fp_ttf == NULL) { fprintf(stderr, "Can't open TrueType font file %s.\n", name); exit(1); } /* read table directory */ if ((OffsetTable.version = fget32(fp_ttf)) == 0x74746366L) { /* ttcf */ fget32(fp_ttf); /* version of ttcf? */ fget32(fp_ttf); /* num of font? */ fseek(fp_ttf, fget32(fp_ttf), SEEK_SET); /* seek to first font */ OffsetTable.version = fget32(fp_ttf); } OffsetTable.numOffsets = fget16(fp_ttf); OffsetTable.searchRange = fget16(fp_ttf); OffsetTable.entrySelector = fget16(fp_ttf); OffsetTable.rangeShift = fget16(fp_ttf); for (i = 0; i < OffsetTable.numOffsets; i++) { DirectoryEntry.tag = fget32(fp_ttf); DirectoryEntry.checkSum = fget32(fp_ttf); DirectoryEntry.offset = fget32(fp_ttf); DirectoryEntry.length = fget32(fp_ttf); switch (DirectoryEntry.tag) { case (tag_FontHeader): ReadFontheader(DirectoryEntry.offset, fp_ttf); break; case (tag_MaxProfile): ReadMaxprofile(DirectoryEntry.offset, fp_ttf); break; case (tag_IndexToLoc): tti_header.IndexToLocBase = DirectoryEntry.offset; break; case (tag_CharToIndexMap): #ifndef OS2FONT ReadCharToIndexMap(DirectoryEntry.offset, fp_ttf); #endif /*OS2FONT*/ break; case (tag_GlyphData): tti_header.GlyphBase = DirectoryEntry.offset; break; case (tag_NamingTable): ShowFontname(DirectoryEntry.offset, fp_ttf); break; case (tag_ControlValue): case (tag_Editor0): case (tag_Editor1): case (tag_Encryption): case (tag_FontProgram): case (tag_GlyphDirectory): case (tag_HoriDeviceMetrics): case (tag_HoriHeader): case (tag_HorizontalMetrics): case (tag_VertHeader): case (tag_VerticalMetrics): case (tag_Kerning): case (tag_LinearThreeshold): case (tag_OS_2): case (tag_Postscript): case (tag_PreProgram): case (tag_mort): case (tag_WIN): case (tag_VDMX): case (tag_FOCA): case (tag_PCLT): case (tag_BASE): case (tag_EBDT): case (tag_EBLC): case (tag_GSUB): case (tag_gasp): break; default: for (len = 0; len < 4; len ++) { tmp[3 - len] = (DirectoryEntry.tag >> (len << 3)) & 0x00ff; } tmp[4] = '\0'; fprintf(stderr, "Warning! : \'%s\'(%08lX) is unknown table tag.\n", tmp, DirectoryEntry.tag); /* exit(1); */ } } /* header of .tti file */ strcpy(extp, ".tti"); if ((fp_tti = fopen(name, "wb")) == NULL) { fprintf(stderr, "Can't create TrueType index file %s.\n", name); exit(1); } tti_header.CodeTableOffset = SIZE_OF_TTI_HEADER; tti_header.MaxJIS = MAXJIS; fput16(tti_header.CodeTableOffset, fp_tti); fput16(tti_header.MaxJIS, fp_tti); fput16(tti_header.unitsPerEm, fp_tti); fput16(tti_header.xMin, fp_tti); fput16(tti_header.yMin, fp_tti); fput16(tti_header.maxPoints, fp_tti); fput16(tti_header.maxContours, fp_tti); fput32(tti_header.IndexToLocBase, fp_tti); fput32(tti_header.GlyphBase, fp_tti); for (ku = 1; ku <= MAXJIS; ku++) { printf("[%02d]", ku); for (ten = 1; ten <= 94; ten++) { #ifdef OS2FONT index = ku * 94 + ten + 162; #else code = codeconv(ku, ten); index = CharToIndex(code, fp_ttf); #endif fput16(index, fp_tti); } } printf("\ndone!\n"); return 0; }