aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/extras/ttf2pt1/ttf.c
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
committerReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
commitf4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch)
tree2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/extras/ttf2pt1/ttf.c
parenta840692edc9c6d19cd7c057f68e39c7d95eb767d (diff)
downloadnx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository
Diffstat (limited to 'nx-X11/extras/ttf2pt1/ttf.c')
-rw-r--r--nx-X11/extras/ttf2pt1/ttf.c1480
1 files changed, 1480 insertions, 0 deletions
diff --git a/nx-X11/extras/ttf2pt1/ttf.c b/nx-X11/extras/ttf2pt1/ttf.c
new file mode 100644
index 000000000..b5cc5bdf8
--- /dev/null
+++ b/nx-X11/extras/ttf2pt1/ttf.c
@@ -0,0 +1,1480 @@
+/*
+ * True Type Font to Adobe Type 1 font converter
+ * By Mark Heath <mheath@netspace.net.au>
+ * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk>
+ * With help from Frank M. Siegert <fms@this.net>
+ *
+ * see COPYRIGHT
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <ctype.h>
+#include <math.h>
+
+#ifndef WINDOWS
+# include <unistd.h>
+# include <netinet/in.h>
+#else
+# include "windows.h"
+#endif
+
+#include "ttf.h"
+#include "pt1.h"
+#include "global.h"
+
+/* prototypes of call entries */
+static void openfont(char *fname, char *arg);
+static void closefont( void);
+static int getnglyphs ( void);
+static int glnames( GLYPH *glyph_list);
+static void glmetrics( GLYPH *glyph_list);
+static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
+static void fnmetrics( struct font_metrics *fm);
+static void glpath( int glyphno, GLYPH *glyph_list);
+static void kerning( GLYPH *glyph_list);
+
+/* globals */
+
+/* front-end descriptor */
+struct frontsw ttf_sw = {
+ /*name*/ "ttf",
+ /*descr*/ "built-in TTF support",
+ /*suffix*/ { "ttf" },
+ /*open*/ openfont,
+ /*close*/ closefont,
+ /*nglyphs*/ getnglyphs,
+ /*glnames*/ glnames,
+ /*glmetrics*/ glmetrics,
+ /*glenc*/ glenc,
+ /*fnmetrics*/ fnmetrics,
+ /*glpath*/ glpath,
+ /*kerning*/ kerning,
+};
+
+/* statics */
+
+static FILE *ttf_file;
+static int ttf_nglyphs, long_offsets;
+
+static TTF_DIRECTORY *directory;
+static TTF_DIR_ENTRY *dir_entry;
+static char *filebuffer;
+static char *filebuffer_end;
+static TTF_NAME *name_table = NULL;
+static TTF_NAME_REC *name_record;
+static TTF_HEAD *head_table = NULL;
+static TTF_HHEA *hhea_table = NULL;
+static TTF_KERN *kern_table = NULL;
+static TTF_CMAP *cmap_table = NULL;
+static LONGHORMETRIC *hmtx_table = NULL;
+static TTF_GLYF *glyf_table;
+static BYTE *glyf_start = NULL;
+static TTF_MAXP *maxp_table = NULL;
+static TTF_POST_HEAD *post_table = NULL;
+static union {
+ USHORT *sp;
+ ULONG *lp;
+} loca_table;
+#define short_loca_table loca_table.sp
+#define long_loca_table loca_table.lp
+
+static short cmap_n_segs;
+static USHORT *cmap_seg_start, *cmap_seg_end;
+static short *cmap_idDelta, *cmap_idRangeOffset;
+static TTF_CMAP_FMT0 *encoding0;
+static int enc_type;
+
+static char name_buffer[2000];
+static char *name_fields[8];
+
+static int enc_found_ms, enc_found_mac;
+
+static char *mac_glyph_names[258] = {
+ ".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",
+ "plusminus", "lessequal", "greaterequal", "yen",
+ "mu", "partialdiff", "summation", "product",
+ "pi", "integral", "ordfeminine", "ordmasculine",
+ "Omega", "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", "guilsinglleft",
+ "guilsinglright", "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", "macron",
+ "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"
+};
+
+/* other prototypes */
+static void draw_composite_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno,
+ double *matrix, int level);
+static void draw_simple_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno,
+ double *matrix);
+static double f2dot14( short x);
+
+/* get the TTF description table address and length for this index */
+
+static void
+get_glyf_table(
+ int glyphno,
+ TTF_GLYF **tab,
+ int *len
+)
+{
+ if(tab!=NULL) {
+ if (long_offsets) {
+ *tab = (TTF_GLYF *) (glyf_start + ntohl(long_loca_table[glyphno]));
+ } else {
+ *tab = (TTF_GLYF *) (glyf_start + (ntohs(short_loca_table[glyphno]) << 1));
+ }
+ }
+ if(len!=NULL) {
+ if (long_offsets) {
+ *len = ntohl(long_loca_table[glyphno + 1]) - ntohl(long_loca_table[glyphno]);
+ } else {
+ *len = (ntohs(short_loca_table[glyphno + 1]) - ntohs(short_loca_table[glyphno])) << 1;
+ }
+ }
+}
+
+static void
+handle_name(void)
+{
+ int j, k, lang, len, platform;
+ char *p, *string_area;
+ char *nbp = name_buffer;
+ int found3 = 0;
+
+ string_area = (char *) name_table + ntohs(name_table->offset);
+ name_record = &(name_table->nameRecords);
+
+ for (j = 0; j < 8; j++) {
+ name_fields[j] = "";
+ }
+
+ for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
+
+ platform = ntohs(name_record->platformID);
+
+ if (platform == 3) {
+
+ found3 = 1;
+ lang = ntohs(name_record->languageID) & 0xff;
+ len = ntohs(name_record->stringLength);
+ if (lang == 0 || lang == 9) {
+ k = ntohs(name_record->nameID);
+ if (k < 8) {
+ name_fields[k] = nbp;
+
+ p = string_area + ntohs(name_record->stringOffset);
+ for (k = 0; k < len; k++) {
+ if (p[k] != '\0') {
+ if (p[k] == '(') {
+ *nbp = '[';
+ } else if (p[k] == ')') {
+ *nbp = ']';
+ } else {
+ *nbp = p[k];
+ }
+ nbp++;
+ }
+ }
+ *nbp = '\0';
+ nbp++;
+ }
+ }
+ }
+ name_record++;
+ }
+
+ string_area = (char *) name_table + ntohs(name_table->offset);
+ name_record = &(name_table->nameRecords);
+
+ if (!found3) {
+ for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
+
+ platform = ntohs(name_record->platformID);
+
+ if (platform == 1) {
+
+ found3 = 1;
+ lang = ntohs(name_record->languageID) & 0xff;
+ len = ntohs(name_record->stringLength);
+ if (lang == 0 || lang == 9) {
+ k = ntohs(name_record->nameID);
+ if (k < 8) {
+ name_fields[k] = nbp;
+
+ p = string_area + ntohs(name_record->stringOffset);
+ for (k = 0; k < len; k++) {
+ if (p[k] != '\0') {
+ if (p[k] == '(') {
+ *nbp = '[';
+ } else if (p[k] == ')') {
+ *nbp = ']';
+ } else {
+ *nbp = p[k];
+ }
+ nbp++;
+ }
+ }
+ *nbp = '\0';
+ nbp++;
+ }
+ }
+ }
+ name_record++;
+ }
+ }
+ if (!found3) {
+ fprintf(stderr, "**** Cannot decode font name fields ****\n");
+ exit(1);
+ }
+ if (name_fields[4][0] == 0) { /* Full Name empty, use Family Name */
+ name_fields[4] = name_fields[1];
+ }
+ if (name_fields[6][0] == 0) { /* Font Name empty, use Full Name */
+ name_fields[6] = name_fields[4];
+ if (name_fields[6][0] == 0) { /* oops, empty again */
+ WARNING_1 fprintf(stderr, "Font name is unknown, setting to \"Unknown\"\n");
+ name_fields[6] = "Unknown";
+ }
+ }
+ p = name_fields[6];
+ /* must not start with a digit */
+ if(isdigit(*p))
+ *p+= 'A'-'0'; /* change to a letter */
+ while (*p != '\0') {
+ if (!isalnum(*p) || *p=='_') {
+ *p = '-';
+ }
+ p++;
+ }
+}
+
+static void
+handle_head(void)
+{
+ long_offsets = ntohs(head_table->indexToLocFormat);
+ if (long_offsets != 0 && long_offsets != 1) {
+ fprintf(stderr, "**** indexToLocFormat wrong ****\n");
+ exit(1);
+ }
+}
+
+/* limit the recursion level to avoid cycles */
+#define MAX_COMPOSITE_LEVEL 20
+
+static void
+draw_composite_glyf(
+ GLYPH *g,
+ GLYPH *glyph_list,
+ int glyphno,
+ double *orgmatrix,
+ int level
+)
+{
+ int len;
+ short ncontours;
+ USHORT flagbyte, glyphindex;
+ double arg1, arg2;
+ BYTE *ptr;
+ char *bptr;
+ SHORT *sptr;
+ double matrix[6], newmatrix[6];
+
+ get_glyf_table(glyphno, &glyf_table, &len);
+
+ if(len<=0) /* nothing to do */
+ return;
+
+ ncontours = ntohs(glyf_table->numberOfContours);
+ if (ncontours >= 0) { /* simple case */
+ draw_simple_glyf(g, glyph_list, glyphno, orgmatrix);
+ return;
+ }
+
+ if(ISDBG(COMPOSITE) && level ==0)
+ fprintf(stderr, "* %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", g->name,
+ orgmatrix[0], orgmatrix[1], orgmatrix[2], orgmatrix[3],
+ orgmatrix[4], orgmatrix[5]);
+
+ /* complex case */
+ if(level >= MAX_COMPOSITE_LEVEL) {
+ WARNING_1 fprintf(stderr,
+ "*** Glyph %s: stopped (possibly infinite) recursion at depth %d\n",
+ g->name, level);
+ return;
+ }
+
+ ptr = ((BYTE *) glyf_table + sizeof(TTF_GLYF));
+ sptr = (SHORT *) ptr;
+ do {
+ flagbyte = ntohs(*sptr);
+ sptr++;
+ glyphindex = ntohs(*sptr);
+ sptr++;
+
+ if (flagbyte & ARG_1_AND_2_ARE_WORDS) {
+ arg1 = (short)ntohs(*sptr);
+ sptr++;
+ arg2 = (short)ntohs(*sptr);
+ sptr++;
+ } else {
+ bptr = (char *) sptr;
+ arg1 = (signed char) bptr[0];
+ arg2 = (signed char) bptr[1];
+ sptr++;
+ }
+ matrix[1] = matrix[2] = 0.0;
+
+ if (flagbyte & WE_HAVE_A_SCALE) {
+ matrix[0] = matrix[3] = f2dot14(*sptr);
+ sptr++;
+ } else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE) {
+ matrix[0] = f2dot14(*sptr);
+ sptr++;
+ matrix[3] = f2dot14(*sptr);
+ sptr++;
+ } else if (flagbyte & WE_HAVE_A_TWO_BY_TWO) {
+ matrix[0] = f2dot14(*sptr);
+ sptr++;
+ matrix[2] = f2dot14(*sptr);
+ sptr++;
+ matrix[1] = f2dot14(*sptr);
+ sptr++;
+ matrix[3] = f2dot14(*sptr);
+ sptr++;
+ } else {
+ matrix[0] = matrix[3] = 1.0;
+ }
+
+ /*
+ * See *
+ * http://fonts.apple.com/TTRefMan/RM06/Chap6g
+ * lyf.html * matrix[0,1,2,3,4,5]=a,b,c,d,m,n
+ */
+
+ if (fabs(matrix[0]) > fabs(matrix[1]))
+ matrix[4] = fabs(matrix[0]);
+ else
+ matrix[4] = fabs(matrix[1]);
+ if (fabs(fabs(matrix[0]) - fabs(matrix[2])) <= 33. / 65536.)
+ matrix[4] *= 2.0;
+
+ if (fabs(matrix[2]) > fabs(matrix[3]))
+ matrix[5] = fabs(matrix[2]);
+ else
+ matrix[5] = fabs(matrix[3]);
+ if (fabs(fabs(matrix[2]) - fabs(matrix[3])) <= 33. / 65536.)
+ matrix[5] *= 2.0;
+
+ /*
+ * fprintf (stderr,"Matrix Opp %hd
+ * %hd\n",arg1,arg2);
+ */
+#if 0
+ fprintf(stderr, "Matrix: %f %f %f %f %f %f\n",
+ matrix[0], matrix[1], matrix[2], matrix[3],
+ matrix[4], matrix[5]);
+ fprintf(stderr, "Offset: %f %f (%s)\n",
+ arg1, arg2,
+ ((flagbyte & ARGS_ARE_XY_VALUES) ? "XY" : "index"));
+#endif
+
+ if (flagbyte & ARGS_ARE_XY_VALUES) {
+ matrix[4] *= arg1;
+ matrix[5] *= arg2;
+ } else {
+ WARNING_1 fprintf(stderr,
+ "*** Glyph %s: reusing scale from another glyph is unsupported\n",
+ g->name);
+ /*
+ * must extract values from a glyph
+ * but it seems to be too much pain
+ * and it's not clear now that it
+ * would be really used in any
+ * interesting font
+ */
+ }
+
+ /* at this point arg1,arg2 contain what logically should be matrix[4,5] */
+
+ /* combine matrices */
+
+ newmatrix[0] = orgmatrix[0]*matrix[0] + orgmatrix[2]*matrix[1];
+ newmatrix[1] = orgmatrix[0]*matrix[2] + orgmatrix[2]*matrix[3];
+
+ newmatrix[2] = orgmatrix[1]*matrix[0] + orgmatrix[3]*matrix[1];
+ newmatrix[3] = orgmatrix[1]*matrix[2] + orgmatrix[3]*matrix[3];
+
+ newmatrix[4] = orgmatrix[0]*matrix[4] + orgmatrix[2]*matrix[5] + orgmatrix[4];
+ newmatrix[5] = orgmatrix[1]*matrix[4] + orgmatrix[3]*matrix[5] + orgmatrix[5];
+
+ if(ISDBG(COMPOSITE)) {
+ fprintf(stderr, "%*c+-> %2d %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
+ level+1, ' ', level, glyph_list[glyphindex].name,
+ matrix[0], matrix[1], matrix[2], matrix[3],
+ matrix[4], matrix[5]);
+ fprintf(stderr, "%*c = [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
+ level+1, ' ',
+ newmatrix[0], newmatrix[1], newmatrix[2], newmatrix[3],
+ newmatrix[4], newmatrix[5]);
+ }
+ draw_composite_glyf(g, glyph_list, glyphindex, newmatrix, level+1);
+
+ } while (flagbyte & MORE_COMPONENTS);
+}
+
+static void
+draw_simple_glyf(
+ GLYPH *g,
+ GLYPH *glyph_list,
+ int glyphno,
+ double *matrix
+)
+{
+ int i, j, k, k1, len, first, cs, ce;
+ /* We assume that hsbw always sets to(0, 0) */
+ double xlast = 0, ylast = 0;
+ int finished, nguide, contour_start, contour_end;
+ short ncontours, n_inst, last_point;
+ USHORT *contour_end_pt;
+ BYTE *ptr;
+#define GLYFSZ 2000
+ short xabs[GLYFSZ], yabs[GLYFSZ], xrel[GLYFSZ], yrel[GLYFSZ];
+ double xcoord[GLYFSZ], ycoord[GLYFSZ];
+ BYTE flags[GLYFSZ];
+ double tx, ty;
+ int needreverse = 0; /* transformation may require
+ * that */
+ GENTRY *lge;
+
+ lge = g->lastentry;
+
+ get_glyf_table(glyphno, &glyf_table, &len);
+
+ if (len <= 0) {
+ WARNING_1 fprintf(stderr,
+ "**** Composite glyph %s refers to non-existent glyph %s, ignored\n",
+ g->name,
+ glyph_list[glyphno].name);
+ return;
+ }
+ ncontours = ntohs(glyf_table->numberOfContours);
+ if (ncontours < 0) {
+ WARNING_1 fprintf(stderr,
+ "**** Composite glyph %s refers to composite glyph %s, ignored\n",
+ g->name,
+ glyph_list[glyphno].name);
+ return;
+ }
+ contour_end_pt = (USHORT *) ((char *) glyf_table + sizeof(TTF_GLYF));
+
+ last_point = ntohs(contour_end_pt[ncontours - 1]);
+ n_inst = ntohs(contour_end_pt[ncontours]);
+
+ ptr = ((BYTE *) contour_end_pt) + (ncontours << 1) + n_inst + 2;
+ j = k = 0;
+ while (k <= last_point) {
+ flags[k] = ptr[j];
+
+ if (ptr[j] & REPEAT) {
+ for (k1 = 0; k1 < ptr[j + 1]; k1++) {
+ k++;
+ flags[k] = ptr[j];
+ }
+ j++;
+ }
+ j++;
+ k++;
+ }
+
+ for (k = 0; k <= last_point; k++) {
+ if (flags[k] & XSHORT) {
+ if (flags[k] & XSAME) {
+ xrel[k] = ptr[j];
+ } else {
+ xrel[k] = -ptr[j];
+ }
+ j++;
+ } else if (flags[k] & XSAME) {
+ xrel[k] = 0.0;
+ } else {
+ xrel[k] = (short)( ptr[j] * 256 + ptr[j + 1] );
+ j += 2;
+ }
+ if (k == 0) {
+ xabs[k] = xrel[k];
+ } else {
+ xabs[k] = xrel[k] + xabs[k - 1];
+ }
+
+ }
+
+ for (k = 0; k <= last_point; k++) {
+ if (flags[k] & YSHORT) {
+ if (flags[k] & YSAME) {
+ yrel[k] = ptr[j];
+ } else {
+ yrel[k] = -ptr[j];
+ }
+ j++;
+ } else if (flags[k] & YSAME) {
+ yrel[k] = 0;
+ } else {
+ yrel[k] = ptr[j] * 256 + ptr[j + 1];
+ j += 2;
+ }
+ if (k == 0) {
+ yabs[k] = yrel[k];
+ } else {
+ yabs[k] = yrel[k] + yabs[k - 1];
+ }
+ }
+
+ if (matrix) {
+ for (i = 0; i <= last_point; i++) {
+ tx = xabs[i];
+ ty = yabs[i];
+ xcoord[i] = fscale(matrix[0] * tx + matrix[2] * ty + matrix[4]);
+ ycoord[i] = fscale(matrix[1] * tx + matrix[3] * ty + matrix[5]);
+ }
+ } else {
+ for (i = 0; i <= last_point; i++) {
+ xcoord[i] = fscale(xabs[i]);
+ ycoord[i] = fscale(yabs[i]);
+ }
+ }
+
+ i = j = 0;
+ first = 1;
+
+ while (i <= ntohs(contour_end_pt[ncontours - 1])) {
+ contour_end = ntohs(contour_end_pt[j]);
+
+ if (first) {
+ fg_rmoveto(g, xcoord[i], ycoord[i]);
+ xlast = xcoord[i];
+ ylast = ycoord[i];
+ contour_start = i;
+ first = 0;
+ } else if (flags[i] & ONOROFF) {
+ fg_rlineto(g, xcoord[i], ycoord[i]);
+ xlast = xcoord[i];
+ ylast = ycoord[i];
+ } else {
+ cs = i - 1;
+ finished = nguide = 0;
+ while (!finished) {
+ if (i == contour_end + 1) {
+ ce = contour_start;
+ finished = 1;
+ } else if (flags[i] & ONOROFF) {
+ ce = i;
+ finished = 1;
+ } else {
+ i++;
+ nguide++;
+ }
+ }
+
+ switch (nguide) {
+ case 0:
+ fg_rlineto(g, xcoord[ce], ycoord[ce]);
+ xlast = xcoord[ce];
+ ylast = ycoord[ce];
+ break;
+
+ case 1:
+ fg_rrcurveto(g,
+ (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
+ (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
+ (2.0 * xcoord[cs + 1] + xcoord[ce]) / 3.0,
+ (2.0 * ycoord[cs + 1] + ycoord[ce]) / 3.0,
+ xcoord[ce],
+ ycoord[ce]
+ );
+ xlast = xcoord[ce];
+ ylast = ycoord[ce];
+
+ break;
+
+ case 2:
+ fg_rrcurveto(g,
+ (-xcoord[cs] + 4.0 * xcoord[cs + 1]) / 3.0,
+ (-ycoord[cs] + 4.0 * ycoord[cs + 1]) / 3.0,
+ (4.0 * xcoord[cs + 2] - xcoord[ce]) / 3.0,
+ (4.0 * ycoord[cs + 2] - ycoord[ce]) / 3.0,
+ xcoord[ce],
+ ycoord[ce]
+ );
+ xlast = xcoord[ce];
+ ylast = ycoord[ce];
+ break;
+
+ case 3:
+ fg_rrcurveto(g,
+ (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
+ (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
+ (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
+ (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
+ (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
+ (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
+ );
+
+ fg_rrcurveto(g,
+ (xcoord[cs + 1] + 5.0 * xcoord[cs + 2]) / 6.0,
+ (ycoord[cs + 1] + 5.0 * ycoord[cs + 2]) / 6.0,
+ (5.0 * xcoord[cs + 2] + xcoord[cs + 3]) / 6.0,
+ (5.0 * ycoord[cs + 2] + ycoord[cs + 3]) / 6.0,
+ (xcoord[cs + 3] + xcoord[cs + 2]) / 2.0,
+ (ycoord[cs + 3] + ycoord[cs + 2]) / 2.0
+ );
+
+ fg_rrcurveto(g,
+ (xcoord[cs + 2] + 5.0 * xcoord[cs + 3]) / 6.0,
+ (ycoord[cs + 2] + 5.0 * ycoord[cs + 3]) / 6.0,
+ (2.0 * xcoord[cs + 3] + xcoord[ce]) / 3.0,
+ (2.0 * ycoord[cs + 3] + ycoord[ce]) / 3.0,
+ xcoord[ce],
+ ycoord[ce]
+ );
+ ylast = ycoord[ce];
+ xlast = xcoord[ce];
+
+ break;
+
+ default:
+ k1 = cs + nguide;
+ fg_rrcurveto(g,
+ (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
+ (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
+ (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
+ (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
+ (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
+ (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
+ );
+
+ for (k = cs + 2; k <= k1 - 1; k++) {
+ fg_rrcurveto(g,
+ (xcoord[k - 1] + 5.0 * xcoord[k]) / 6.0,
+ (ycoord[k - 1] + 5.0 * ycoord[k]) / 6.0,
+ (5.0 * xcoord[k] + xcoord[k + 1]) / 6.0,
+ (5.0 * ycoord[k] + ycoord[k + 1]) / 6.0,
+ (xcoord[k] + xcoord[k + 1]) / 2.0,
+ (ycoord[k] + ycoord[k + 1]) / 2.0
+ );
+
+ }
+
+ fg_rrcurveto(g,
+ (xcoord[k1 - 1] + 5.0 * xcoord[k1]) / 6.0,
+ (ycoord[k1 - 1] + 5.0 * ycoord[k1]) / 6.0,
+ (2.0 * xcoord[k1] + xcoord[ce]) / 3.0,
+ (2.0 * ycoord[k1] + ycoord[ce]) / 3.0,
+ xcoord[ce],
+ ycoord[ce]
+ );
+ xlast = xcoord[ce];
+ ylast = ycoord[ce];
+
+ break;
+ }
+ }
+ if (i >= contour_end) {
+ g_closepath(g);
+ first = 1;
+ i = contour_end + 1;
+ j++;
+ } else {
+ i++;
+ }
+ }
+
+ if (matrix) {
+ /* guess whether do we need to reverse the results */
+
+ double x[3], y[3];
+ int max = 0, from, to;
+
+ /* transform a triangle going in proper direction */
+ /*
+ * the origin of triangle is in (0,0) so we know it in
+ * advance
+ */
+
+ x[0] = y[0] = 0;
+ x[1] = matrix[0] * 0 + matrix[2] * 300;
+ y[1] = matrix[1] * 0 + matrix[3] * 300;
+ x[2] = matrix[0] * 300 + matrix[2] * 0;
+ y[2] = matrix[1] * 300 + matrix[3] * 0;
+
+ /* then find the topmost point */
+ for (i = 0; i < 3; i++)
+ if (y[i] > y[max])
+ max = i;
+ from = (max + 3 - 1) % 3;
+ to = (max + 1) % 3;
+
+ needreverse = 0;
+
+ /* special cases for horizontal lines */
+ if (y[max] == y[from]) {
+ if (x[max] < y[from])
+ needreverse = 1;
+ } else if (y[to] == y[from]) {
+ if (x[to] < x[max])
+ needreverse = 1;
+ } else { /* generic case */
+ if ((x[to] - x[max]) * (y[max] - y[from])
+ > (x[max] - x[from]) * (y[to] - y[max]))
+ needreverse = 1;
+ }
+
+ if (needreverse) {
+ if (lge) {
+ assertpath(lge->next, __FILE__, __LINE__, g->name);
+ reversepathsfromto(lge->next, NULL);
+ } else {
+ assertpath(g->entries, __FILE__, __LINE__, g->name);
+ reversepaths(g);
+ }
+ }
+ }
+}
+
+static double
+f2dot14(
+ short x
+)
+{
+ short y = ntohs(x);
+ return (y >> 14) + ((y & 0x3fff) / 16384.0);
+}
+
+
+/* check that the pointer points within the file */
+/* returns 0 if pointer is good, 1 if bad */
+static int
+badpointer(
+ void *ptr
+)
+{
+ return (ptr < (void *)filebuffer || ptr >= (void *)filebuffer_end);
+}
+
+/*
+ * Externally accessible methods
+ */
+
+/*
+ * Open font and prepare to return information to the main driver.
+ * May print error and warning messages.
+ * Exit on error.
+ */
+
+static void
+openfont(
+ char *fname,
+ char *arg /* unused now */
+)
+{
+ int i, j;
+ struct stat statbuf;
+ static struct {
+ void **tbpp; /* pointer to pointer to the table */
+ char name[5]; /* table name */
+ char optional; /* flag: table may be missing */
+ } tables[] = {
+ { (void **)&name_table, "name", 0 },
+ { (void **)&head_table, "head", 0 },
+ { (void **)&hhea_table, "hhea", 0 },
+ { (void **)&post_table, "post", 0 },
+ { (void **)&glyf_start, "glyf", 0 },
+ { (void **)&cmap_table, "cmap", 0 },
+ { (void **)&kern_table, "kern", 1 },
+ { (void **)&maxp_table, "maxp", 0 },
+ { (void **)&hmtx_table, "hmtx", 0 },
+ { (void **)&long_loca_table, "loca", 0 },
+ { NULL, "", 0 } /* end of table */
+ };
+
+ if (stat(fname, &statbuf) == -1) {
+ fprintf(stderr, "**** Cannot access %s ****\n", fname);
+ exit(1);
+ }
+ if ((filebuffer = malloc(statbuf.st_size)) == NULL) {
+ fprintf(stderr, "**** Cannot malloc space for file ****\n");
+ exit(1);
+ }
+
+ filebuffer_end = filebuffer + statbuf.st_size;
+
+ if ((ttf_file = fopen(fname, "rb")) == NULL) {
+ fprintf(stderr, "**** Cannot open file '%s'\n", fname);
+ exit(1);
+ } else {
+ WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
+ }
+
+ if (fread(filebuffer, 1, statbuf.st_size, ttf_file) != statbuf.st_size) {
+ fprintf(stderr, "**** Could not read whole file \n");
+ exit(1);
+ }
+ fclose(ttf_file);
+
+ directory = (TTF_DIRECTORY *) filebuffer;
+
+ if (ntohl(directory->sfntVersion) != 0x00010000) {
+ fprintf(stderr,
+ "**** Unknown File Version number [%x], or not a TrueType file\n",
+ directory->sfntVersion);
+ exit(1);
+ }
+
+ /* clear the tables */
+ for(j=0; tables[j].tbpp != NULL; j++)
+ *(tables[j].tbpp) = NULL;
+
+ dir_entry = &(directory->list);
+
+ for (i = 0; i < ntohs(directory->numTables); i++) {
+
+ for(j=0; tables[j].tbpp != NULL; j++)
+ if (memcmp(dir_entry->tag, tables[j].name, 4) == 0) {
+ *(tables[j].tbpp) = (void *) (filebuffer + ntohl(dir_entry->offset));
+ break;
+ }
+
+ if (memcmp(dir_entry->tag, "EBDT", 4) == 0 ||
+ memcmp(dir_entry->tag, "EBLC", 4) == 0 ||
+ memcmp(dir_entry->tag, "EBSC", 4) == 0) {
+ WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
+ }
+ dir_entry++;
+ }
+
+ for(j=0; tables[j].tbpp != NULL; j++)
+ if(!tables[j].optional && badpointer( *(tables[j].tbpp) )) {
+ fprintf(stderr, "**** File contains no required table '%s'\n", tables[j].name);
+ exit(1);
+ }
+
+ handle_name();
+
+ handle_head();
+
+ ttf_nglyphs = ntohs(maxp_table->numGlyphs);
+
+ enc_found_ms = enc_found_mac = 0;
+}
+
+/*
+ * Close font.
+ * Exit on error.
+ */
+
+static void
+closefont(
+ void
+)
+{
+ return; /* empty operation */
+}
+
+/*
+ * Get the number of glyphs in font.
+ */
+
+static int
+getnglyphs (
+ void
+)
+{
+ return ttf_nglyphs;
+}
+
+/*
+ * Get the names of the glyphs.
+ * Returns 0 if the names were assigned, non-zero if the font
+ * provides no glyph names.
+ */
+
+static int
+glnames(
+ GLYPH *glyph_list
+)
+{
+ int i, len, n, npost;
+ unsigned int format;
+ USHORT *name_index;
+ char *ptr, *p;
+ char **ps_name_ptr = (char **) malloc(ttf_nglyphs * sizeof(char *));
+ int n_ps_names;
+ int ps_fmt_3 = 0;
+
+ format = ntohl(post_table->formatType);
+
+ if (format == 0x00010000) {
+ for (i = 0; i < 258 && i < ttf_nglyphs; i++) {
+ glyph_list[i].name = mac_glyph_names[i];
+ }
+ } else if (format == 0x00020000) {
+ npost = ntohs(post_table->numGlyphs);
+ if (ttf_nglyphs != npost) {
+ /* This is an error in the font, but we can now cope */
+ WARNING_1 fprintf(stderr, "**** Postscript table size mismatch %d/%d ****\n",
+ npost, ttf_nglyphs);
+ }
+ n_ps_names = 0;
+ name_index = &(post_table->glyphNameIndex);
+
+ /* This checks the integrity of the post table */
+ for (i=0; i<npost; i++) {
+ n = ntohs(name_index[i]);
+ if (n > n_ps_names + 257) {
+ n_ps_names = n - 257;
+ }
+ }
+
+ ptr = (char *) post_table + 34 + (ttf_nglyphs << 1);
+ i = 0;
+ while (*ptr > 0 && i < n_ps_names) {
+ len = *ptr;
+ /* previously the program wrote nulls into the table. If the table
+ was corrupt, this could put zeroes anywhere, leading to obscure bugs,
+ so now I malloc space for the names. Yes it is much less efficient */
+
+ if ((p = malloc(len+1)) == NULL) {
+ fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
+ exit(255);
+ }
+
+ ps_name_ptr[i] = p;
+ strncpy(p, ptr+1, len);
+ p[len] = '\0';
+ i ++;
+ ptr += len + 1;
+ }
+
+ if (i != n_ps_names)
+ {
+ WARNING_2 fprintf (stderr, "** Postscript Name mismatch %d != %d **\n",
+ i, n_ps_names);
+ n_ps_names = i;
+ }
+
+ /*
+ * for (i=0; i<n_ps_names; i++) { fprintf(stderr, "i=%d,
+ * len=%d, name=%s\n", i, ps_name_len[i], ps_name_ptr[i]); }
+ */
+
+ for (i = 0; i < npost; i++) {
+ n = ntohs(name_index[i]);
+ if (n < 258) {
+ glyph_list[i].name = mac_glyph_names[n];
+ } else if (n < 258 + n_ps_names) {
+ glyph_list[i].name = ps_name_ptr[n - 258];
+ } else {
+ glyph_list[i].name = malloc(16);
+ sprintf(glyph_list[i].name, "_g_%d", i);
+ WARNING_2 fprintf(stderr,
+ "Glyph No. %d has no postscript name, becomes %s\n",
+ i, glyph_list[i].name);
+ }
+ }
+ /* Now fake postscript names for all those beyond the end of the table */
+ if (npost < ttf_nglyphs) {
+ for (i=npost; i<ttf_nglyphs; i++) {
+ if ((glyph_list[i].name = malloc(16)) == NULL)
+ {
+ fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
+ exit(255);
+ }
+ sprintf(glyph_list[i].name, "_g_%d", i);
+ WARNING_2 fprintf(stderr,
+ "Glyph No. %d has no postscript name, becomes %s\n",
+ i, glyph_list[i].name);
+ }
+ }
+ } else if (format == 0x00030000) {
+ WARNING_3 fputs("No postscript table, using default\n", stderr);
+ ps_fmt_3 = 1;
+ } else if (format == 0x00028000) {
+ ptr = (char *) &(post_table->numGlyphs);
+ for (i = 0; i < ttf_nglyphs; i++) {
+ glyph_list[i].name = mac_glyph_names[i + ptr[i]];
+ }
+ } else {
+ fprintf(stderr,
+ "**** Postscript table in wrong format %x ****\n",
+ format);
+ exit(1);
+ }
+
+ return ps_fmt_3;
+}
+
+/*
+ * Get the metrics of the glyphs.
+ */
+
+static void
+glmetrics(
+ GLYPH *glyph_list
+)
+{
+ int i;
+ int n_hmetrics = ntohs(hhea_table->numberOfHMetrics);
+ GLYPH *g;
+ LONGHORMETRIC *hmtx_entry = hmtx_table;
+ FWORD *lsblist;
+
+ for (i = 0; i < n_hmetrics; i++) {
+ g = &(glyph_list[i]);
+ g->width = ntohs(hmtx_entry->advanceWidth);
+ g->lsb = ntohs(hmtx_entry->lsb);
+ hmtx_entry++;
+ }
+
+ lsblist = (FWORD *) hmtx_entry;
+ hmtx_entry--;
+
+ for (i = n_hmetrics; i < ttf_nglyphs; i++) {
+ g = &(glyph_list[i]);
+ g->width = ntohs(hmtx_entry->advanceWidth);
+ g->lsb = ntohs(lsblist[i - n_hmetrics]);
+ }
+
+ for (i = 0; i < ttf_nglyphs; i++) {
+ g = &(glyph_list[i]);
+ get_glyf_table(i, &glyf_table, &g->ttf_pathlen);
+
+ g->xMin = (short)ntohs(glyf_table->xMin);
+ g->xMax = (short)ntohs(glyf_table->xMax);
+ g->yMin = (short)ntohs(glyf_table->yMin);
+ g->yMax = (short)ntohs(glyf_table->yMax);
+ }
+
+}
+
+
+static void
+handle_ms_encoding(
+ GLYPH *glyph_list,
+ int *encoding,
+ int *unimap
+)
+{
+ int j, k, kk, set_ok;
+ USHORT start, end, ro;
+ short delta, n;
+
+ for (j = 0; j < cmap_n_segs - 1; j++) {
+ start = ntohs(cmap_seg_start[j]);
+ end = ntohs(cmap_seg_end[j]);
+ delta = ntohs(cmap_idDelta[j]);
+ ro = ntohs(cmap_idRangeOffset[j]);
+
+ for (k = start; k <= end; k++) {
+ if (ro == 0) {
+ n = k + delta;
+ } else {
+ n = ntohs(*((ro >> 1) + (k - start) +
+ &(cmap_idRangeOffset[j])));
+ if (delta != 0)
+ {
+ /* Not exactly sure how to deal with this circumstance,
+ I suspect it never occurs */
+ n += delta;
+ fprintf (stderr,
+ "rangeoffset and delta both non-zero - %d/%d",
+ ro, delta);
+ }
+ }
+ if(n<0 || n>=ttf_nglyphs) {
+ WARNING_1 fprintf(stderr, "Font contains a broken glyph code mapping, ignored\n");
+ continue;
+ }
+ if (glyph_list[n].orig_code != -1) {
+#if 0
+ if (strcmp(glyph_list[n].name, ".notdef") != 0) {
+ WARNING_2 fprintf(stderr,
+ "Glyph %s has >= two encodings (A), %4.4x & %4.4x\n",
+ glyph_list[n].name,
+ glyph_list[n].orig_code,
+ k);
+ }
+#endif
+ set_ok = 0;
+ } else {
+ set_ok = 1;
+ }
+ if (enc_type==1 || forcemap) {
+ kk = unicode_rev_lookup(k);
+ if(ISDBG(UNICODE))
+ fprintf(stderr, "Unicode %s - 0x%04x\n",glyph_list[n].name,k);
+ if (set_ok) {
+ glyph_list[n].orig_code = k;
+ /* glyph_list[n].char_no = kk; */
+ }
+ if (kk >= 0 && kk < ENCTABSZ && encoding[kk] == -1)
+ encoding[kk] = n;
+ } else {
+ if ((k & 0xff00) == 0xf000) {
+ if( encoding[k & 0x00ff] == -1 ) {
+ encoding[k & 0x00ff] = n;
+ if (set_ok) {
+ /* glyph_list[n].char_no = k & 0x00ff; */
+ glyph_list[n].orig_code = k;
+ }
+ }
+ } else {
+ if (set_ok) {
+ /* glyph_list[n].char_no = k; */
+ glyph_list[n].orig_code = k;
+ }
+ WARNING_2 fprintf(stderr,
+ "Glyph %s has non-symbol encoding %4.4x\n",
+ glyph_list[n].name,
+ k & 0xffff);
+ /*
+ * just use the code
+ * as it is
+ */
+ if ((k & ~0xff) == 0 && encoding[k] == -1 )
+ encoding[k] = n;
+ }
+ }
+ }
+ }
+}
+
+static void
+handle_mac_encoding(
+ GLYPH *glyph_list,
+ int *encoding,
+ int *unimap
+)
+{
+ short n;
+ int j, size;
+
+ size = ntohs(encoding0->length) - 6;
+ for (j = 0; j < size; j++) {
+ n = encoding0->glyphIdArray[j];
+ if (glyph_list[n].char_no != -1) {
+ WARNING_2 fprintf(stderr,
+ "Glyph %s has >= two encodings (B), %4.4x & %4.4x\n",
+ glyph_list[n].name,
+ glyph_list[n].char_no,
+ j);
+ } else {
+ if (j < ENCTABSZ) {
+ if(encoding[j] == -1) {
+ glyph_list[n].char_no = j;
+ encoding[j] = n;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Get the original encoding of the font.
+ * Returns 1 for if the original encoding is Unicode, 2 if the
+ * original encoding is other 16-bit, 0 if 8-bit.
+ */
+
+static int
+glenc(
+ GLYPH *glyph_list,
+ int *encoding,
+ int *unimap
+)
+{
+ int num_tables = ntohs(cmap_table->numberOfEncodingTables);
+ BYTE *ptr;
+ int i, format, offset, seg_c2, found;
+ int platform, encoding_id;
+ TTF_CMAP_ENTRY *table_entry;
+ TTF_CMAP_FMT4 *encoding4;
+
+ if(enc_found_ms) {
+ handle_ms_encoding(glyph_list, encoding, unimap);
+ return enc_type;
+ } else if(enc_found_mac) {
+ handle_mac_encoding(glyph_list, encoding, unimap);
+ return 0;
+ }
+
+ if(force_pid != -1 && force_pid != 3) {
+ fputs("*** Only platform ID == 3 is supported\n", stderr);
+ exit(1);
+ }
+
+ enc_type = 0;
+ found = 0;
+
+ for (i = 0; i < num_tables && !found; i++) {
+ table_entry = &(cmap_table->encodingTable[i]);
+ offset = ntohl(table_entry->offset);
+ encoding4 = (TTF_CMAP_FMT4 *) ((BYTE *) cmap_table + offset);
+ format = ntohs(encoding4->format);
+ platform = ntohs(table_entry->platformID);
+ encoding_id = ntohs(table_entry->encodingID);
+
+ if (platform == 3 && format == 4) {
+ if(force_pid == 3) {
+ if(encoding_id != force_eid)
+ continue;
+ WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n",
+ force_pid, force_eid);
+ enc_type = 1;
+ } else {
+ switch (encoding_id) {
+ case 0:
+ WARNING_1 fputs("Found Symbol Encoding\n", stderr);
+ break;
+ case 1:
+ WARNING_1 fputs("Found Unicode Encoding\n", stderr);
+ enc_type = 1;
+ break;
+ default:
+ WARNING_1 {
+ fprintf(stderr,
+ "****MS Encoding ID %d not supported****\n",
+ encoding_id);
+ fputs("Treating it like Symbol encoding\n", stderr);
+ }
+ break;
+ }
+ }
+
+ found = 1;
+ seg_c2 = ntohs(encoding4->segCountX2);
+ cmap_n_segs = seg_c2 >> 1;
+ ptr = (BYTE *) encoding4 + 14;
+ cmap_seg_end = (USHORT *) ptr;
+ cmap_seg_start = (USHORT *) (ptr + seg_c2 + 2);
+ cmap_idDelta = (short *) (ptr + (seg_c2 * 2) + 2);
+ cmap_idRangeOffset = (short *) (ptr + (seg_c2 * 3) + 2);
+ enc_found_ms = 1;
+
+ handle_ms_encoding(glyph_list, encoding, unimap);
+ }
+ }
+
+ if (!found) {
+ if(force_pid != -1) {
+ fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n",
+ force_pid, force_eid);
+ exit(1);
+ }
+
+ WARNING_1 fputs("No Microsoft encoding, looking for MAC encoding\n", stderr);
+ for (i = 0; i < num_tables && !found; i++) {
+ table_entry = &(cmap_table->encodingTable[i]);
+ offset = ntohl(table_entry->offset);
+ encoding0 = (TTF_CMAP_FMT0 *) ((BYTE *) cmap_table + offset);
+ format = ntohs(encoding0->format);
+ platform = ntohs(table_entry->platformID);
+ encoding_id = ntohs(table_entry->encodingID);
+
+ if (format == 0) {
+ found = 1;
+ enc_found_mac = 1;
+
+ handle_mac_encoding(glyph_list, encoding, unimap);
+ }
+ }
+ }
+ if (!found) {
+ fprintf(stderr, "**** No Recognised Encoding Table ****\n");
+ exit(1);
+ }
+
+ return enc_type;
+}
+
+/*
+ * Get the font metrics
+ */
+static void
+fnmetrics(
+ struct font_metrics *fm
+)
+{
+ char *str;
+ static int fieldstocheck[]= {2,4,6};
+ int i, j, len;
+
+ fm->italic_angle = (short) (ntohs(post_table->italicAngle.upper)) +
+ ((short) ntohs(post_table->italicAngle.lower) / 65536.0);
+ fm->underline_position = (short) ntohs(post_table->underlinePosition);
+ fm->underline_thickness = (short) ntohs(post_table->underlineThickness);
+ fm->is_fixed_pitch = ntohl(post_table->isFixedPitch);
+
+ fm->ascender = (short)ntohs(hhea_table->ascender);
+ fm->descender = (short)ntohs(hhea_table->descender);
+
+ fm->units_per_em = ntohs(head_table->unitsPerEm);
+
+ fm->bbox[0] = (short) ntohs(head_table->xMin);
+ fm->bbox[1] = (short) ntohs(head_table->yMin);
+ fm->bbox[2] = (short) ntohs(head_table->xMax);
+ fm->bbox[3] = (short) ntohs(head_table->yMax);
+
+ fm->name_copyright = name_fields[0];
+ fm->name_family = name_fields[1];
+ fm->name_style = name_fields[2];
+ fm->name_full = name_fields[4];
+ fm->name_version = name_fields[5];
+ fm->name_ps = name_fields[6];
+
+ /* guess the boldness from the font names */
+ fm->force_bold=0;
+
+ for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(int); i++) {
+ str = name_fields[fieldstocheck[i]];
+ len = strlen(str);
+ for(j=0; j<len; j++) {
+ if( (str[j]=='B'
+ || str[j]=='b'
+ && ( j==0 || !isalpha(str[j-1]) )
+ )
+ && !strncmp("old",&str[j+1],3)
+ && (j+4 >= len || !islower(str[j+4]))
+ ) {
+ fm->force_bold=1;
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Get the path of contrours for a glyph.
+ */
+
+static void
+glpath(
+ int glyphno,
+ GLYPH *glyf_list
+)
+{
+ double matrix[6];
+ GLYPH *g;
+
+ g = &glyph_list[glyphno];
+
+ matrix[0] = matrix[3] = 1.0;
+ matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0.0;
+ draw_composite_glyf(g, glyf_list, glyphno, matrix, 0 /*level*/);
+}
+
+/*
+ * Get the kerning data.
+ */
+
+static void
+kerning(
+ GLYPH *glyph_list
+)
+{
+ TTF_KERN_SUB *subtable;
+ TTF_KERN_ENTRY *kern_entry;
+ int i, j;
+ int ntables;
+ int npairs;
+ char *ptr;
+
+ if(kern_table == NULL) {
+ WARNING_1 fputs("No Kerning data\n", stderr);
+ return;
+ }
+ if(badpointer(kern_table)) {
+ fputs("**** Defective Kerning table, ignored\n", stderr);
+ return;
+ }
+
+ ntables = ntohs(kern_table->nTables);
+ ptr = (char *) kern_table + 4;
+
+ for (i = 0; i < ntables; i++) {
+ subtable = (TTF_KERN_SUB *) ptr;
+ if ((ntohs(subtable->coverage) & 0xff00) == 0) {
+ npairs = (short) ntohs(subtable->nPairs);
+ kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
+
+ kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
+ for (j = 0; j < npairs; j++) {
+ if( kern_entry->value != 0)
+ addkernpair(ntohs(kern_entry->left),
+ ntohs(kern_entry->right), (short)ntohs(kern_entry->value));
+ kern_entry++;
+ }
+ }
+ ptr += subtable->length;
+ }
+}
+