Logo Search packages:      
Sourcecode: vflib2 version File versions  Download package

ttindex.c

/*
 * 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#if __TURBOC__
#  include <alloc.h>
#  include <io.h>
/*
#else
#  include <malloc.h>
*/
#endif
#include <fcntl.h>
#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;
}

Generated by  Doxygen 1.6.0   Back to index