--- /dev/null
+# 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
+
+
--- /dev/null
+/* 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
+};
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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");
+}
--- /dev/null
+/* 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);
+ }
+}
--- /dev/null
+/* 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;
+}