]> git.donarmstrong.com Git - lilypond.git/commitdiff
add dir
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Sun, 20 Feb 2005 18:07:11 +0000 (18:07 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Sun, 20 Feb 2005 18:07:11 +0000 (18:07 +0000)
ttftool/GNUmakefile [new file with mode: 0644]
ttftool/encodings.c [new file with mode: 0644]
ttftool/parse.c [new file with mode: 0644]
ttftool/ps.c [new file with mode: 0644]
ttftool/ttfps.c [new file with mode: 0644]
ttftool/util.c [new file with mode: 0644]

diff --git a/ttftool/GNUmakefile b/ttftool/GNUmakefile
new file mode 100644 (file)
index 0000000..0c56f8d
--- /dev/null
@@ -0,0 +1,19 @@
+# title           top level makefile for FlowerLib
+# file    flower/Makefile
+
+# should reinstate versioning if shared libs are enabled.
+
+depth = ..
+
+NAME = ttftool
+MODULE_NAME = ttftool
+SUBDIRS = include 
+
+SCRIPTS = 
+README_FILES = NEWS-1.0 NEWS-1.1.46 README TODO
+EXTRA_DIST_FILES= VERSION $(README_FILES) $(SCRIPTS)
+STEPMAKE_TEMPLATES=library c po
+
+include $(depth)/make/stepmake.make 
+
+
diff --git a/ttftool/encodings.c b/ttftool/encodings.c
new file mode 100644 (file)
index 0000000..e0eff36
--- /dev/null
@@ -0,0 +1,132 @@
+/* Copyright (c) 1997-1998 by Juliusz Chroboczek */
+
+#define NULL ((void *)0)
+
+/* char *macEncoding[]={ */
+/*   ".notdef", NULL, NULL, NULL, NULL, NULL, */
+/*   NULL, NULL, NULL, NULL, NULL, NULL, */
+/*   NULL, NULL, NULL, NULL, NULL, NULL, */
+/*   NULL, NULL, NULL, NULL, NULL, NULL, */
+/*   NULL, NULL, NULL, NULL, NULL, NULL, */
+/*   NULL, NULL, "space", "exclam", "quotedbl", "numbersign", */
+/*   "dollar", "percent", "ampersand", "quoteright", "parenleft", */
+/*   "parenright", "asterisk", "plus", "comma", "hyphen", "period", */
+/*   "slash", "zero", "one", "two", "three", "four", "five", "six", */
+/*   "seven", "eight", "nine", "colon", "semicolon", "less", "equal", */
+/*   "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", */
+/*   "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", */
+/*   "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", */
+/*   "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", */
+/*   "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", */
+/*   "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", */
+/*   "tilde", NULL, "Adieresis", "Aring", "Ccedilla", "Eacute", */
+/*   "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", */
+/*   "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", */
+/*   "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", */
+/*   "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", */
+/*   "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger", */
+/*   "degree", "cent", "sterling", "section", "bullet", "paragraph", */
+/*   "germandbls", "registered", "copyright", "trademark", "acute", */
+/*   "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", */
+/*   "lessequal", "greaterequal", "yen", "mu", "partialdiff", "Sigma", */
+/*   "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", */
+/*   "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", */
+/*   "florin", "approxequal", "Delta", "guillemotleft", "guillemotright", */
+/*   "ellipsis", "space", "Agrave", "Atilde", "Otilde", "OE", "oe", */
+/*   "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", */
+/*   "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", */
+/*   "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", */
+/*   "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", */
+/*   "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", */
+/*   "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", */
+/*   "Ocircumflex", NULL, "Ograve", "Uacute", "Ucircumflex", "Ugrave", */
+/*   "dotlessi", "circumflex", "tilde", "macron", "breve", "dotaccent", */
+/*   "ring", "cedilla", "hungarumlaut", "ogonek", "caron"}; */
+
+char *macGlyphEncoding[] = {
+  ".notdef", ".null", "CR", "space", "exclam", "quotedbl", "numbersign",
+  "dollar", "percent", "ampersand", "quotesingle", "parenleft",
+  "parenright", "asterisk", "plus", "comma", "hyphen", "period",
+  "slash", "zero", "one", "two", "three", "four", "five", "six",
+  "seven", "eight", "nine", "colon", "semicolon", "less", "equal",
+  "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H",
+  "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
+  "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright",
+  "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f",
+  "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
+  "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright",
+  "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde",
+  "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex",
+  "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave",
+  "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex",
+  "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
+  "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger",
+  "degree", "cent", "sterling", "section", "bullet", "paragraph",
+  "germandbls", "registered", "copyright", "trademark", "acute",
+  "dieresis", "notequal", "AE", "Oslash", "infinity", "plusinus",
+  "lessequal", "greaterequal", "yen", "mu1", "partialdiff", "summation",
+  "product", "pi", "integral", "ordfeminine", "ordmasculine", "Ohm",
+  "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical",
+  "florin", "approxequal", "increment", "guillemotleft",
+  "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", "Otilde",
+  "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright",
+  "quoteleft", "quoteright", "divide", "lozenge", "ydieresis",
+  "Ydieresis", "fraction", "currency", "guilsingleft", "guilsingright",
+  "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase",
+  "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute",
+  "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave",
+  "Oacute", "Ocircumflex", "applelogo", "Ograve", "Uacute",
+  "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde",
+  "overscore", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut",
+  "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron", "Zcaron",
+  "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn",
+  "thorn", "minus", "multiply", "onesuperior", "twosuperior",
+  "threesuperior", "onehalf", "onequarter", "threequarters", "franc",
+  "Gbreve", "gbreve", "Idot", "Scedilla", "scedilla", "Cacute",
+  "cacute", "Ccaron", "ccaron", "dmacron"
+};
+
+char *adobeStandardEncoding[] = {
+  ".notdef", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  "space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
+    "ampersand", "quoteright",
+  "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period",
+    "slash",
+  "zero", "one", "two", "three", "four", "five", "six", "seven",
+  "eight", "nine", "colon", "semicolon", "less", "equal", "greater",
+    "question",
+  "at", "A", "B", "C", "D", "E", "F", "G",
+  "H", "I", "J", "K", "L", "M", "N", "O",
+  "P", "Q", "R", "S", "T", "U", "V", "W",
+  "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
+    "underscore",
+  "quoteleft", "a", "b", "c", "d", "e", "f", "g",
+  "h", "i", "j", "k", "l", "m", "n", "o",
+  "p", "q", "r", "s", "t", "u", "v", "w",
+  "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, "exclamdown", "cent", "sterling", "fraction", "yen", "florin",
+    "section",
+  "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",
+    "guilsinglright", "fi", "fl",
+  NULL, "endash", "dagger", "daggerdbl", "periodcentered", NULL, "paragraph",
+    "bullet",
+  "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
+    "ellipsis", "perthousand", NULL, "questiondown",
+  NULL, "grave", "acute", "circumflex", "tilde", "macron", "breve",
+    "dotaccent",
+  "dieresis", NULL, "ring", "cedilla", NULL, "hungarumlaut", "ogonek",
+    "caron",
+  "emdash", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, "AE", NULL, "ordfeminine", NULL, NULL, NULL, NULL,
+  "Lslash", "Oslash", "OE", "ordmasculine", NULL, NULL, NULL, NULL,
+  NULL, "ae", NULL, NULL, NULL, "dotlessi", NULL, NULL,
+  "lslash", "oslash", "oe", "germandbls", NULL, NULL, NULL, NULL
+};
diff --git a/ttftool/parse.c b/ttftool/parse.c
new file mode 100644 (file)
index 0000000..e519d81
--- /dev/null
@@ -0,0 +1,335 @@
+/* Copyright (c) 1997-1998 by Juliusz Chroboczek */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <malloc.h>
+#include "types.h"
+#include "proto.h"
+
+struct TableDirectoryEntry *
+readDirectory (int fd, struct OffsetTable *ot)
+{
+  unsigned n;
+  int i;
+
+  struct TableDirectoryEntry *td;
+  surely_read (fd, ot, sizeof (struct OffsetTable));
+  FIX_OffsetTable (*ot);
+  if (verbosity >= 2)
+    fprintf (stderr, "%d tables\n", ot->numTables);
+  n = sizeof (struct TableDirectoryEntry) * ot->numTables;
+  td = mymalloc (n);
+  surely_read (fd, td, n);
+  for (i = 0; i < ot->numTables; i++)
+    FIX_TableDirectoryEntry (td[i]);
+  return td;
+}
+
+char **
+readNamingTable (int fd)
+{
+  USHORT format;
+  USHORT nrecords;
+  off_t position;
+  USHORT offset;
+  int i, index, maxIndex;
+  struct NameRecord *records;
+  char *data;
+  char **strings;
+
+  position = surely_lseek (fd, 0, SEEK_CUR);
+
+  surely_read (fd, &format, sizeof (USHORT));
+  FIX_UH (format);
+  if (format != 0)
+    error ("Bad TTF file\n");
+  surely_read (fd, &nrecords, sizeof (USHORT));
+  FIX_UH (nrecords);
+  surely_read (fd, &offset, sizeof (USHORT));
+  FIX_UH (offset);
+  records = mymalloc (nrecords * sizeof (struct NameRecord));
+  surely_read (fd, records, nrecords * sizeof (struct NameRecord));
+
+  for (i = 0, maxIndex = -1; i < nrecords; i++)
+    {
+      FIX_NameRecord (records[i]);
+      index = records[i].offset + records[i].length;
+      maxIndex = maxIndex > index ? maxIndex : index;
+    }
+  data = mymalloc (maxIndex);
+  surely_lseek (fd, position + offset, SEEK_SET);
+  surely_read (fd, data, maxIndex);
+
+  strings = mymalloc (8 * sizeof (char *));
+  for (i = 0; i < 8; i++)
+    strings[i] = NULL;
+
+  for (i = 0; i < nrecords; i++)
+    {
+      if (records[i].platformID == 3 &&        /* Microsoft */
+         records[i].encodingID == 1 && /* UGL */
+         records[i].languageID == 0x0409 &&    /* US English */
+         records[i].nameID <= 7)
+       {
+         strings[records[i].nameID] = mymalloc (records[i].length / 2 + 1);
+         unistrncpy (strings[records[i].nameID],
+                     data + records[i].offset, records[i].length);
+         if (verbosity >= 2)
+           fprintf (stderr, "%d: %s\n", records[i].nameID,
+                    strings[records[i].nameID]);
+       }
+    }
+  free (records);
+  free (data);
+  return strings;
+}
+
+int
+readMaxpTable (int fd)
+{
+  struct
+  {
+    Fixed version;
+    USHORT nglyphs;
+  } data;
+  surely_read (fd, &data, sizeof (data));
+  FIX_Fixed (data.version);
+  FIX_UH (data.nglyphs);
+  if (verbosity >= 2)
+    fprintf (stderr, "  version %d.%u\n",
+            data.version.mantissa, data.version.fraction);
+  return data.nglyphs;
+}
+
+void
+readHeadTable (int fd, struct HeadTable *ht)
+{
+  surely_read (fd, ht, sizeof (struct HeadTable));
+  FIX_HeadTable (*ht);
+  if (verbosity >= 2)
+    {
+      fprintf (stderr, "  version %d.%d\n",
+              ht->version.mantissa, ht->version.fraction);
+      fprintf (stderr, "  font revision %d.%d\n",
+              ht->fontRevision.mantissa, ht->fontRevision.fraction);
+    }
+  if (ht->magicNumber != 0x5F0F3CF5)
+    error ("Bad magic number in TTF file");
+  if (verbosity >= 2)
+    fprintf (stderr, "  %d units per Em\n", ht->unitsPerEm);
+}
+
+int
+readPostTable (int fd, int nglyphs, struct PostTable *pt,
+              struct GlyphName **gt)
+{
+  USHORT nglyphspost;
+  USHORT *glyphNameIndex;
+  struct GlyphName *glyphNames;
+  char **glyphNamesTemp;
+  int i, maxIndex;
+  CHAR c;
+
+  surely_read (fd, pt, sizeof (struct PostTable));
+  FIX_PostTable (*pt);
+  if (verbosity >= 2)
+    fprintf (stderr, "  format type %d.%u\n",
+            pt->formatType.mantissa, pt->formatType.fraction);
+
+  switch (pt->formatType.mantissa)
+    {
+    case 1:
+      return 1;                        /* MacGlyphEncoding */
+    case 2:
+      if (pt->formatType.fraction != 0)
+       error ("Unsupported `post' table format");
+      surely_read (fd, &nglyphspost, sizeof (USHORT));
+      FIX_UH (nglyphspost);
+      if (nglyphspost != nglyphs)
+       error ("Inconsistency between `maxp' and `nglyphs' tables!");
+      if (verbosity >= 2)
+       fprintf (stderr, "  %d glyphs\n", nglyphs);
+      glyphNameIndex = mymalloc (sizeof (USHORT) * nglyphs);
+      surely_read (fd, glyphNameIndex, sizeof (USHORT) * nglyphs);
+      glyphNames = mymalloc (sizeof (struct GlyphName) * nglyphs);
+      for (i = 0, maxIndex = -1; i < nglyphs; i++)
+       {
+         FIX_UH (glyphNameIndex[i]);
+         if (glyphNameIndex[i] < 258)
+           {
+             glyphNames[i].type = 0;
+             glyphNames[i].name.index = glyphNameIndex[i];
+           }
+         else
+           {
+             int index;
+             glyphNames[i].type = 1;
+             index = glyphNameIndex[i] - 258;
+             glyphNames[i].name.index = index;
+             maxIndex = maxIndex > index ? maxIndex : index;
+           }
+       }
+      free (glyphNameIndex);
+
+      i = 0;
+      glyphNamesTemp = mymalloc (sizeof (char *) * (maxIndex + 1));
+      while (i <= maxIndex)
+       {
+         surely_read (fd, &c, 1);
+         glyphNamesTemp[i] = mymalloc (c + 1);
+         surely_read (fd, glyphNamesTemp[i], c);
+         glyphNamesTemp[i][c] = '\0';
+         if (verbosity >= 3)
+           fprintf (stderr, "    %d: %s\n", i, glyphNamesTemp[i]);
+         i++;
+       }
+      for (i = 0; i < nglyphs; i++)
+       if (glyphNames[i].type == 1)
+         glyphNames[i].name.name = glyphNamesTemp[glyphNames[i].name.index];
+      free (glyphNamesTemp);
+      *gt = glyphNames;
+      return 2;
+    case 3:
+      return 3;                        /* no name table */
+    default:
+      return 0;
+    }
+ /*NOTREACHED*/}
+
+void *
+readLocaTable (int fd, int nglyphs, int format)
+{
+  int i;
+  switch (format)
+    {
+    case 0:
+      {
+       USHORT *offsets;
+       offsets = mymalloc ((nglyphs + 1) * sizeof (USHORT));
+       surely_read (fd, offsets, (nglyphs + 1) * sizeof (USHORT));
+       for (i = 0; i <= nglyphs; i++)
+         FIX_UH (offsets[i]);
+       return offsets;
+      }
+     /*NOTREACHED*/ case 1:
+      {
+       ULONG *offsets;
+       offsets = mymalloc ((nglyphs + 1) * sizeof (ULONG));
+       surely_read (fd, offsets, (nglyphs + 1) * sizeof (ULONG));
+       for (i = 0; i <= nglyphs; i++)
+         FIX_UL (offsets[i]);
+       return offsets;
+      }
+     /*NOTREACHED*/ default:
+      error ("Unknown `loca' table format");
+     /*NOTREACHED*/}
+ /*NOTREACHED*/}
+
+struct Box *
+readGlyfTable (int fd, int nglyphs, int format, void *loca)
+{
+  int i;
+  struct Box *bbox;
+  off_t base, offset;
+
+  base = surely_lseek (fd, 0, SEEK_CUR);
+
+  bbox = mymalloc (nglyphs * sizeof (struct Box));
+  for (i = 0; i < nglyphs; i++)
+    {
+      if (format == 0)
+       offset = 2 * ((USHORT *) loca)[i];
+      else
+       offset = ((ULONG *) loca)[i];
+      surely_lseek (fd, base + offset + sizeof (SHORT), SEEK_SET);
+      surely_read (fd, bbox + i, sizeof (struct Box));
+      FIX_Box (bbox[i]);
+    }
+  return bbox;
+}
+
+longHorMetric *
+readHmtxTable (int fd, int nummetrics)
+{
+  longHorMetric *metrics;
+  int i;
+
+  metrics = mymalloc (nummetrics * sizeof (longHorMetric));
+  surely_read (fd, metrics, nummetrics * sizeof (longHorMetric));
+  for (i = 0; i < nummetrics; i++)
+    {
+      FIX_longHorMetric (metrics[i]);
+    }
+  return metrics;
+}
+
+struct HheaTable *
+readHheaTable (int fd)
+{
+  struct HheaTable *hhea;
+  hhea = mymalloc (sizeof (struct HheaTable));
+  surely_read (fd, hhea, sizeof (struct HheaTable));
+  FIX_HheaTable (*hhea);
+  if (verbosity >= 2)
+    fprintf (stderr, "  version %d.%u\n",
+            hhea->version.mantissa, hhea->version.fraction);
+  if (hhea->metricDataFormat != 0)
+    error ("Unknown metric data format");
+  return hhea;
+}
+
+int
+readKernTable (int fd, int **nkep, struct KernEntry0 ***kep)
+{
+  struct KernTable kt;
+  struct KernSubTableHeader ksth;
+  struct KernSubTable0 kst;
+  int i, j;
+  int *nke;
+  struct KernEntry0 **ke;
+
+  surely_read (fd, &kt, sizeof (struct KernTable));
+  FIX_KernTable (kt);
+  if (verbosity >= 2)
+    {
+      fprintf (stderr, "  version %d\n", kt.version);
+      fprintf (stderr, "  %d subtables\n", kt.nTables);
+    }
+  nke = mymalloc (kt.nTables * sizeof (int));
+  ke = mymalloc (kt.nTables * sizeof (struct KernEntry0 *));
+
+  for (i = 0; i < kt.nTables; i++)
+    {
+      surely_read (fd, &ksth, sizeof (struct KernSubTableHeader));
+      FIX_KernSubTableHeader (ksth);
+      if (verbosity >= 2)
+       fprintf (stderr, "  analyzing subtable %d, version %d... ",
+                i, ksth.version);
+      if ((ksth.coverage & kernHorizontal) &&
+         !(ksth.coverage & kernMinimum) &&
+         !(ksth.coverage & kernCrossStream) &&
+         (kernFormat (ksth.coverage) == 0))
+       {
+         surely_read (fd, &kst, sizeof (struct KernSubTable0));
+         FIX_KernSubTable0 (kst);
+         if (verbosity >= 2)
+           fprintf (stderr, "reading %d entries.\n", kst.nPairs);
+         nke[i] = kst.nPairs;
+         ke[i] = mymalloc (kst.nPairs * sizeof (struct KernEntry0));
+         surely_read (fd, ke[i], kst.nPairs * sizeof (struct KernEntry0));
+         for (j = 0; j < kst.nPairs; j++)
+           FIX_KernEntry0 (ke[i][j]);
+       }
+      else
+       {
+         if (verbosity >= 2)
+           fprintf (stderr, "skipping.\n");
+         surely_lseek (fd, ksth.length - sizeof (struct KernSubTableHeader),
+                       SEEK_CUR);
+       }
+    }
+  *nkep = nke;
+  *kep = ke;
+  return kt.nTables;
+}
diff --git a/ttftool/ps.c b/ttftool/ps.c
new file mode 100644 (file)
index 0000000..ccf4a16
--- /dev/null
@@ -0,0 +1,298 @@
+/* Copyright (c) 1997-1998 by Juliusz Chroboczek */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <malloc.h>
+#include "types.h"
+#include "proto.h"
+
+#define CHUNKSIZE 65534
+
+#define NAMEOF(i) \
+        ((i)==0?\
+         ".notdef":\
+         ((postType==2)?\
+          ((gnt[i].type==0)?\
+           (gnt[i].name.index==0?NULL:macGlyphEncoding[gnt[i].name.index]):\
+           gnt[i].name.name):\
+          ((i)<258?macGlyphEncoding[i]:NULL)))
+
+
+void
+printPSFont (FILE * out, struct HeadTable *ht,
+            char **strings, int nglyphs, int postType,
+            struct PostTable *pt, struct GlyphName *gnt, int fd)
+{
+  printPSHeader (out, ht, strings, pt);
+  printPSData (out, fd);
+  printPSTrailer (out, nglyphs, postType, gnt);
+}
+
+void
+printPSHeader (FILE * out, struct HeadTable *ht,
+              char **strings, struct PostTable *pt)
+{
+  fprintf (out, "%%!PS-TrueTypeFont\n");
+  if (pt->maxMemType42)
+    fprintf (out, "%%%%VMUsage: %ld %ld\n", pt->minMemType42,
+            pt->maxMemType42);
+  fprintf (out, "%d dict begin\n", 11);
+  fprintf (out, "/FontName /%s def\n", strings[6] ? strings[6] : "Unknown");
+  fprintf (out, "/Encoding StandardEncoding def\n");
+  fprintf (out, "/PaintType 0 def\n/FontMatrix [1 0 0 1 0 0] def\n");
+  fprintf (out, "/FontBBox [%ld %ld %ld %ld] def\n",
+          ht->xMin * 1000L / ht->unitsPerEm,
+          ht->yMin * 1000L / ht->unitsPerEm,
+          ht->xMax * 1000L / ht->unitsPerEm,
+          ht->yMax * 1000L / ht->unitsPerEm);
+  fprintf (out, "/FontType 42 def\n");
+  fprintf (out, "/FontInfo 8 dict dup begin\n");
+  fprintf (out, "/version (%d.%d) def\n",
+          ht->fontRevision.mantissa, ht->fontRevision.fraction);
+  if (strings[0])
+    {
+      fprintf (out, "/Notice (");
+      fputpss (strings[0], out);
+      fprintf (out, ") def\n");
+    }
+  if (strings[4])
+    {
+      fprintf (out, "/FullName (");
+      fputpss (strings[4], out);
+      fprintf (out, ") def\n");
+    }
+  if (strings[1])
+    {
+      fprintf (out, "/FamilyName (");
+      fputpss (strings[1], out);
+      fprintf (out, ") def\n");
+    }
+  fprintf (out, "/isFixedPitch %s def\n",
+          pt->isFixedPitch ? "true" : "false");
+  fprintf (out, "/UnderlinePosition %ld def\n",
+          pt->underlinePosition * 1000L / ht->unitsPerEm);
+  fprintf (out, "/UnderlineThickness %ld def\n",
+          pt->underlineThickness * 1000L / ht->unitsPerEm);
+  fprintf (out, "end readonly def\n");
+}
+
+void
+printPSData (FILE * out, int fd)
+{
+  static char xdigits[] = "0123456789ABCDEF";
+
+  unsigned char *buffer;
+  int i, j;
+
+  surely_lseek (fd, 0, SEEK_SET);
+
+  buffer = mymalloc (CHUNKSIZE);
+
+  fprintf (out, "/sfnts [");
+  for (;;)
+    {
+      i = read (fd, buffer, CHUNKSIZE);
+      if (i == 0)
+       break;
+      fprintf (out, "\n<");
+      for (j = 0; j < i; j++)
+       {
+         if (j != 0 && j % 36 == 0)
+           putc ('\n', out);
+         /* fprintf(out,"%02X",(int)buffer[j]) is too slow */
+         putc (xdigits[(buffer[j] & 0xF0) >> 4], out);
+         putc (xdigits[buffer[j] & 0x0F], out);
+       }
+      fprintf (out, "00>");    /* Adobe bug? */
+      if (i < CHUNKSIZE)
+       break;
+    }
+  fprintf (out, "\n] def\n");
+  free (buffer);
+}
+
+void
+printPSTrailer (FILE * out, int nglyphs, int postType, struct GlyphName *gnt)
+{
+  int i, n;
+  char *name;
+
+  fprintf (out, "/CharStrings %d dict dup begin\n", nglyphs);
+  switch (postType)
+    {
+    case 2:
+      for (n = i = 0; i < nglyphs; i++)
+       {
+         if (n != 0 && n % 4 == 0)
+           fprintf (out, "\n");
+         name = NAMEOF (i);
+         if (name)
+           {
+             fprintf (out, "/%s %d def ", name, i);
+             n++;
+           }
+       }
+      break;
+    default:
+      if (postType != 1)
+       {
+         if (verbosity > -2)
+           fprintf (stderr,
+                    "No glyph name table; assuming MacGlyphEncoding\n");
+       }
+      for (i = 0; i < 258 && i < nglyphs; i++)
+       {
+         fprintf (out, "/%s %d def ", macGlyphEncoding[i], i);
+         if (i != 0 && i % 4 == 0)
+           fprintf (out, "\n");
+       }
+      break;
+    }
+  fprintf (out, "end readonly def\n");
+  fprintf (out, "FontName currentdict end definefont pop\n");
+}
+
+void
+printAFM (FILE * afm, struct HeadTable *ht,
+         char **strings, int nglyphs, int postType,
+         struct PostTable *pt, struct GlyphName *gnt,
+         struct Box *bbox, struct HheaTable *hhea, longHorMetric * hmtx,
+         int nkern, int *nke, struct KernEntry0 **ke)
+{
+  fprintf (afm, "StartFontMetrics 3.0\n");
+  fprintf (afm, "Comment Automatically generated by ttfps -- do not edit\n");
+  printAFMHeader (afm, ht, strings, pt);
+  printAFMMetrics (afm, ht, nglyphs, postType, gnt, bbox, hhea, hmtx);
+  printAFMKerning (afm, ht, postType, gnt, nkern, nke, ke);
+  fprintf (afm, "EndFontMetrics\n");
+}
+
+void
+printAFMHeader (FILE * afm, struct HeadTable *ht,
+               char **strings, struct PostTable *pt)
+{
+  fprintf (afm, "FontName %s\n", strings[6] ? strings[6] : "Unknown");
+  if (strings[4])
+    fprintf (afm, "FullName %s\n", strings[4]);
+  if (strings[1])
+    fprintf (afm, "FamilyName %s\n", strings[1]);
+  fprintf (afm, "IsFixedPitch %s\n", pt->isFixedPitch ? "true" : "false");
+  fprintf (afm, "FontBBox %ld %ld %ld %ld\n",
+          ht->xMin * 1000L / ht->unitsPerEm,
+          ht->yMin * 1000L / ht->unitsPerEm,
+          ht->xMax * 1000L / ht->unitsPerEm,
+          ht->yMax * 1000L / ht->unitsPerEm);
+  fprintf (afm, "UnderlinePosition %ld\n",
+          pt->underlinePosition * 1000L / ht->unitsPerEm);
+  fprintf (afm, "UnderlineThickness %ld\n",
+          pt->underlineThickness * 1000L / ht->unitsPerEm);
+  fprintf (afm, "Version %d.%u\n", ht->fontRevision.mantissa,
+          ht->fontRevision.fraction);
+  if (strings[0])
+    fprintf (afm, "Notice %s\n", strings[0]);
+  fprintf (afm, "EncodingScheme AdobeStandardEncoding\n");
+  /*  fprintf(afm,"CapHeight %d\n");
+     fprintf(afm,"XHeight %d\n");
+     fprintf(afm,"Ascender %d\n");
+     fprintf(afm,"Descender %d\n");  */
+}
+
+void
+printAFMMetrics (FILE * afm, struct HeadTable *ht,
+                int nglyphs, int postType, struct GlyphName *gnt,
+                struct Box *bbox,
+                struct HheaTable *hhea, longHorMetric * hmtx)
+{
+  int i, j;
+  char *name;
+  struct hashtable *table;
+  char *already_done;
+
+  /* Hash all the character names */
+  table = make_hashtable (nglyphs / 3 + 1);
+  for (i = 0; i < nglyphs; i++)
+    {
+      name = NAMEOF (i);
+      if (name)
+       puthash (table, name, i);
+    }
+
+  already_done = mycalloc (nglyphs, sizeof (char));
+
+  fprintf (afm, "StartCharMetrics %d\n", nglyphs);
+  /* First, print out the encoded glyphs */
+  for (i = 0; i < 256; i++)
+    {
+      if (adobeStandardEncoding[i])
+       {
+         j = gethash (table, adobeStandardEncoding[i]);
+         if (j >= 0)
+           {
+             printOneAFMMetric (afm, j, i, adobeStandardEncoding[i],
+                                ht, bbox, hhea, hmtx);
+             already_done[j] = 1;
+           }
+       }
+    }
+  /* Now, print out the others */
+  for (j = 0; j < nglyphs; j++)
+    {
+      if (!already_done[j])
+       {
+         name = NAMEOF (j);
+         printOneAFMMetric (afm, j, -1, name, ht, bbox, hhea, hmtx);
+       }
+    }
+  fprintf (afm, "EndCharMetrics\n");
+}
+
+void
+printOneAFMMetric (FILE * afm,
+                  int index, int code, char *name,
+                  struct HeadTable *ht,
+                  struct Box *bbox,
+                  struct HheaTable *hhea, longHorMetric * hmtx)
+{
+  if (name)
+    {
+      fprintf (afm, "C %d ;", code);
+      if (hhea && hmtx)
+       fprintf (afm, " WX %ld ;",
+                index < hhea->numberOfHMetrics ?
+                hmtx[index].advanceWidth * 1000L / ht->unitsPerEm :
+                hmtx[hhea->numberOfHMetrics -
+                     1].advanceWidth * 1000L / ht->unitsPerEm);
+      fprintf (afm, " N %s ;", name);
+      if (bbox)
+       fprintf (afm, " B %ld %ld %ld %ld ;",
+                bbox[index].xMin * 1000L / ht->unitsPerEm,
+                bbox[index].yMin * 1000L / ht->unitsPerEm,
+                bbox[index].xMax * 1000L / ht->unitsPerEm,
+                bbox[index].yMax * 1000L / ht->unitsPerEm);
+      fprintf (afm, "\n");
+    }
+}
+
+void
+printAFMKerning (FILE * afm, struct HeadTable *ht,
+                int postType, struct GlyphName *gnt,
+                int nkern, int *nke, struct KernEntry0 **ke)
+{
+  int i, j, n;
+
+  for (n = i = 0; i < nkern; i++)
+    n += nke[i];
+  if (n == 0)
+    return;
+
+  fprintf (afm, "StartKernData\nStartKernPairs %d\n", n);
+
+  for (i = 0; i < nkern; i++)
+    for (j = 0; j < nke[i]; j++)
+      fprintf (afm, "KPX %s %s %ld\n",
+              NAMEOF (ke[i][j].left),
+              NAMEOF (ke[i][j].right),
+              ke[i][j].value * 1000L / ht->unitsPerEm);
+  fprintf (afm, "EndKernPairs\nEndKernData\n");
+}
diff --git a/ttftool/ttfps.c b/ttftool/ttfps.c
new file mode 100644 (file)
index 0000000..143af5e
--- /dev/null
@@ -0,0 +1,157 @@
+/* Copyright (c) 1997-1998 by Juliusz Chroboczek */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "types.h"
+#include "proto.h"
+
+static void endianness_test (void);
+static void usage (char *);
+
+int verbosity = 0;
+
+void
+create_type42 (const char *infile, FILE * out)
+{
+  int fd, i;
+  FILE *afm = NULL;
+  struct OffsetTable ot;
+  struct HeadTable *ht;
+  struct PostTable *pt;
+  struct TableDirectoryEntry *td;
+  void *loca = NULL;
+  struct HheaTable *hhea = NULL;
+  struct Box *bbox = NULL;
+  longHorMetric *hmtx = NULL;
+  char **strings = NULL;
+  struct GlyphName *gnt = NULL;
+  struct KernEntry0 **ke;
+  int *nke;
+  int nglyphs, postType, nkern;
+  off_t headOff = 0, maxpOff = 0, postOff = 0, nameOff = 0,
+    locaOff = 0, glyfOff = 0, hheaOff = 0, hmtxOff = 0, kernOff = 0;
+
+  extern char *optarg;
+  extern int optind;
+  int c;
+
+  endianness_test ();
+
+  if ((fd = open (infile, O_RDONLY)) < 0)
+    syserror ("Error opening input file");
+
+  td = readDirectory (fd, &ot);
+  if (verbosity >= 2)
+    fprintf (stderr, "True type version %d.%u\n",
+            ot.version.mantissa, ot.version.fraction);
+
+  for (i = 0; i < ot.numTables; i++)
+    {
+      if (verbosity >= 2)
+       fprintf (stderr, "Found `%c%c%c%c' table\n",
+                (char) (td[i].tag >> 24),
+                (char) (td[i].tag >> 16) & 255,
+                (char) (td[i].tag >> 8) & 255, (char) td[i].tag & 255);
+      switch (td[i].tag)
+       {
+       case MAKE_ULONG ('m', 'a', 'x', 'p'):
+         maxpOff = td[i].offset;
+         break;
+       case MAKE_ULONG ('h', 'e', 'a', 'd'):
+         headOff = td[i].offset;
+         break;
+       case MAKE_ULONG ('p', 'o', 's', 't'):
+         postOff = td[i].offset;
+         break;
+       case MAKE_ULONG ('n', 'a', 'm', 'e'):
+         nameOff = td[i].offset;
+         break;
+       case MAKE_ULONG ('l', 'o', 'c', 'a'):
+         locaOff = td[i].offset;
+         break;
+       case MAKE_ULONG ('g', 'l', 'y', 'f'):
+         glyfOff = td[i].offset;
+         break;
+       case MAKE_ULONG ('h', 'h', 'e', 'a'):
+         hheaOff = td[i].offset;
+         break;
+       case MAKE_ULONG ('h', 'm', 't', 'x'):
+         hmtxOff = td[i].offset;
+         break;
+       case MAKE_ULONG ('k', 'e', 'r', 'n'):
+         kernOff = td[i].offset;
+         break;
+       }
+    }
+  if (maxpOff == 0 || headOff == 0 || postOff == 0 || nameOff == 0)
+    error ("Incomplete TTF file\n");
+
+  if (verbosity >= 1)
+    fprintf (stderr, "Processing `maxp' table\n");
+  surely_lseek (fd, maxpOff, SEEK_SET);
+  nglyphs = readMaxpTable (fd);
+  if (verbosity >= 1)
+    fprintf (stderr, "  %d glyphs\n", nglyphs);
+
+  if (verbosity >= 1)
+    fprintf (stderr, "Processing `head' table\n");
+  surely_lseek (fd, headOff, SEEK_SET);
+  ht = mymalloc (sizeof (struct HeadTable));
+  readHeadTable (fd, ht);
+
+  if (verbosity >= 1)
+    fprintf (stderr, "Processing `post' table\n");
+  surely_lseek (fd, postOff, SEEK_SET);
+  pt = mymalloc (sizeof (struct PostTable));
+  postType = readPostTable (fd, nglyphs, pt, &gnt);
+
+  if (verbosity >= 1)
+    fprintf (stderr, "Processing `name' table\n");
+  surely_lseek (fd, nameOff, SEEK_SET);
+  strings = readNamingTable (fd);
+
+  if (verbosity >= 1)
+    fprintf (stderr, "Generating PS file\n");
+  printPSFont (out, ht, strings, nglyphs, postType, pt, gnt, fd);
+  fclose (out);
+  if (afm)
+    {
+      if (verbosity >= 1)
+       fprintf (stderr, "Generating AFM file\n");
+      printAFM (afm, ht, strings, nglyphs, postType, pt, gnt,
+               bbox, hhea, hmtx, nkern, nke, ke);
+      fclose (afm);
+    }
+  if (verbosity >= 1)
+    fprintf (stderr, "Done.\n");
+  close (fd);
+}
+
+
+static void
+endianness_test ()
+{
+  union
+  {
+    BYTE b[4];
+    ULONG l;
+  } x;
+  ULONG v;
+
+  x.b[0] = 1;
+  x.b[1] = 2;
+  x.b[2] = 3;
+  x.b[3] = 4;
+
+  v = UL (x.l);
+
+  if (v != (((((1 << 8) + 2) << 8) + 3) << 8) + 4)
+    {
+      fprintf (stderr, "Code badly compiled for this architecture\n");
+      fprintf (stderr, "Please set SMALLENDIAN and recompile\n");
+      exit (2);
+    }
+}
diff --git a/ttftool/util.c b/ttftool/util.c
new file mode 100644 (file)
index 0000000..4524421
--- /dev/null
@@ -0,0 +1,161 @@
+/* Copyright (c) 1997-1998 by Juliusz Chroboczek */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "types.h"
+#include "proto.h"
+
+void *
+mymalloc (size_t size)
+{
+  void *p;
+  if ((p = malloc (size)) == NULL)
+    error ("Unable to allocate memory\n");
+  return p;
+}
+
+void *
+mycalloc (size_t nelem, size_t elsize)
+{
+  void *p;
+  if ((p = calloc (nelem, elsize)) == NULL)
+    error ("Unable to allocate memory\n");
+  return p;
+}
+
+void *
+myrealloc (void *ptr, size_t size)
+{
+  void *p;
+  if ((p = realloc (ptr, size)) == NULL)
+    error ("Unable to allocate memory\n");
+  return p;
+}
+
+off_t
+surely_lseek (int fildes, off_t offset, int whence)
+{
+  off_t result;
+  if ((result = lseek (fildes, offset, whence)) < 0)
+    error ("Bad TTF file");
+  return result;
+}
+
+void
+error (char *string)
+{
+  fprintf (stderr, "%s\n", string);
+  exit (3);
+ /*NOTREACHED*/}
+
+void
+syserror (char *string)
+{
+  perror (string);
+  exit (3);
+ /*NOTREACHED*/}
+
+ssize_t
+surely_read (int fildes, void *buf, size_t nbyte)
+{
+  ssize_t n;
+  if ((n = read (fildes, buf, nbyte)) < nbyte)
+    error ("Bad TTF file");
+  return n;
+}
+
+char *
+unistrncpy (char *dst, char *str, size_t length)
+{
+  int i, j;
+
+  for (i = j = 0; i < length; i += 2)
+    if (str[i] == 0)
+      dst[j++] = str[i + 1];
+  dst[j] = '\0';
+  return dst;
+}
+
+void
+fputpss (char *s, FILE * stream)
+{
+  while (*s)
+    {
+      if ((*s & 0200) == 0 && *s >= 040 && *s != '(' && *s != ')')
+       putc (*s, stream);
+      else
+       fprintf (stream, "\\%03o", (unsigned char) *s);
+      s++;
+    }
+}
+
+/* Hashtables */
+
+unsigned
+hash (char *string)
+{
+  int i;
+  unsigned u = 0;
+  for (i = 0; string[i] != '\0'; i++)
+    u = (u << 2) + string[i];
+  return u;
+}
+
+struct hashtable *
+make_hashtable (int size)
+{
+  struct hashtable *t;
+
+  t = mymalloc (sizeof (struct hashtable));
+  t->size = size;
+  t->buckets = mycalloc (size, sizeof (struct hashtable_bucket *));
+
+  return t;
+}
+
+int
+puthash (struct hashtable *t, char *key, int value)
+{
+  int i;
+
+  i = hash (key) % t->size;
+
+  if (t->buckets[i] == 0)
+    {
+      t->buckets[i] = mymalloc (sizeof (struct hashtable_bucket));
+      t->buckets[i]->entries = mymalloc (4 * sizeof (struct hashtable_entry));
+      t->buckets[i]->size = 4;
+      t->buckets[i]->nentries = 0;
+    }
+
+  if (t->buckets[i]->nentries >= t->buckets[i]->size)
+    {
+      t->buckets[i]->entries = myrealloc (t->buckets[i]->entries,
+                                         t->buckets[i]->size * 2 *
+                                         sizeof (struct hashtable_entry));
+      t->buckets[i]->size *= 2;
+    }
+
+  t->buckets[i]->entries[t->buckets[i]->nentries].key = key;
+  t->buckets[i]->entries[t->buckets[i]->nentries].value = value;
+  t->buckets[i]->nentries++;
+
+  return value;
+}
+
+int
+gethash (struct hashtable *t, char *key)
+{
+  int i, j;
+
+  i = hash (key) % t->size;
+  if (t->buckets[i])
+    for (j = 0; j < t->buckets[i]->nentries; j++)
+      if (!strcmp (key, t->buckets[i]->entries[j].key))
+       return t->buckets[i]->entries[j].value;
+  return -1;
+}