shithub: neatroff

Download patch

ref: 284841844342e3be754905fa9eb6e05fd6d9f74c
parent: daa212b472395ed52524c2d54ffb46749cec774f
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Nov 19 18:43:51 EST 2013

font: new syntax for defining characters and kerning pairs

This patch introduces a new syntax for defining characters or kerning
pairs: characters can be defined with lines starting with the word
"char" followed by the definition of a character similar to character
definitions in the charset section.  The lines starting with "kern"
followed by a triple (first glyph name, second glyph name, kerning
amount) describes a kerning pair.  Note that each kerning pair is
defined using glyph names (the fourth fields in character definitions)
and not character names as in the old, and now unsupported, kernpairs
section.  Note that the charset section is still supported.

--- a/font.c
+++ b/font.c
@@ -3,21 +3,13 @@
 #include <string.h>
 #include "roff.h"
 
-static void skipline(FILE* filp)
-{
-	int c;
-	do {
-		c = getc(filp);
-	} while (c != '\n' && c != EOF);
-}
-
 struct glyph *font_find(struct font *fn, char *name)
 {
-	int i = fn->head[(unsigned char) name[0]];
+	int i = fn->chead[(unsigned char) name[0]];
 	while (i >= 0) {
 		if (!strcmp(name, fn->c[i]))
 			return fn->g[i];
-		i = fn->next[i];
+		i = fn->cnext[i];
 	}
 	return NULL;
 }
@@ -24,13 +16,31 @@
 
 struct glyph *font_glyph(struct font *fn, char *id)
 {
-	int i;
-	for (i = 0; i < fn->nglyphs; i++)
+	int i = fn->ghead[(unsigned char) id[0]];
+	while (i >= 0) {
 		if (!strcmp(fn->glyphs[i].id, id))
 			return &fn->glyphs[i];
+		i = fn->gnext[i];
+	}
 	return NULL;
 }
 
+struct glyph *font_glyphput(struct font *fn, char *id, char *name, int wid, int type)
+{
+	int i = fn->nglyphs++;
+	struct glyph *g;
+	g = &fn->glyphs[i];
+	strcpy(g->id, id);
+	strcpy(g->name, name);
+	g->wid = wid;
+	g->type = type;
+	g->font = fn;
+	fn->gnext[i] = fn->ghead[(unsigned char) id[0]];
+	fn->ghead[(unsigned char) id[0]] = i;
+	return g;
+}
+
+/* glyph index in fn->glyphs[] */
 static int font_idx(struct font *fn, struct glyph *g)
 {
 	return g ? g - fn->glyphs : -1;
@@ -56,10 +66,10 @@
 		strcpy(s + len, cur);
 		len += strlen(cur);
 	}
-	for (i = 0; i < fn->nlig; i++) {
-		int l = strlen(fn->lig[i]);
-		if (b[len - l] > 1 && !strcmp(s + len - l, fn->lig[i]))
-			if (font_find(fn, fn->lig[i]))
+	for (i = 0; i < fn->lgn; i++) {
+		int l = strlen(fn->lg[i]);
+		if (b[len - l] > 1 && !strcmp(s + len - l, fn->lg[i]))
+			if (font_find(fn, fn->lg[i]))
 				return b[len - l];
 	}
 	return 0;
@@ -69,8 +79,8 @@
 int font_islig(struct font *fn, char *s)
 {
 	int i;
-	for (i = 0; i < fn->nlig; i++)
-		if (!strcmp(s, fn->lig[i]))
+	for (i = 0; i < fn->lgn; i++)
+		if (!strcmp(s, fn->lg[i]))
 			return 1;
 	return 0;
 }
@@ -92,81 +102,61 @@
 	return 0;
 }
 
-static int font_section(struct font *fn, FILE *fin, char *name);
-
-static void font_charset(struct font *fn, FILE *fin)
+static int font_readchar(struct font *fn, FILE *fin)
 {
 	char tok[ILNLEN];
 	char name[ILNLEN];
 	char id[ILNLEN];
 	struct glyph *glyph = NULL;
-	struct glyph *prev = NULL;
 	int wid, type;
-	while (fscanf(fin, "%s", name) == 1) {
-		if (!font_section(fn, fin, name))
-			break;
-		if (fn->n >= NGLYPHS) {
-			skipline(fin);
-			continue;
-		}
-		fscanf(fin, "%s", tok);
-		glyph = prev;
-		if (!strcmp("---", name))
-			sprintf(name, "c%04d", fn->n);
-		if (strcmp("\"", tok)) {
-			wid = atoi(tok);
-			fscanf(fin, "%d %s", &type, id);
-			skipline(fin);
-			glyph = &fn->glyphs[fn->nglyphs++];
-			strcpy(glyph->id, id);
-			strcpy(glyph->name, name);
-			glyph->wid = wid;
-			glyph->type = type;
-			glyph->font = fn;
-		}
-		prev = glyph;
-		strcpy(fn->c[fn->n], name);
-		fn->g[fn->n] = glyph;
-		fn->next[fn->n] = fn->head[(unsigned char) name[0]];
-		fn->head[(unsigned char) name[0]] = fn->n;
-		fn->n++;
+	if (fn->n >= NGLYPHS)
+		return 1;
+	if (fscanf(fin, "%s %s", name, tok) != 2)
+		return 1;
+	if (!strcmp("---", name))
+		sprintf(name, "c%04d", fn->n);
+	if (strcmp("\"", tok)) {
+		wid = atoi(tok);
+		if (fscanf(fin, "%d %s", &type, id) != 2)
+			return 1;
+		glyph = font_glyph(fn, id);
+		if (!glyph)
+			glyph = font_glyphput(fn, id, name, wid, type);
+	} else {
+		glyph = fn->g[fn->n - 1];
 	}
+	strcpy(fn->c[fn->n], name);
+	fn->g[fn->n] = glyph;
+	fn->cnext[fn->n] = fn->chead[(unsigned char) name[0]];
+	fn->chead[(unsigned char) name[0]] = fn->n;
+	fn->n++;
+	return 0;
 }
 
-static void font_kernpairs(struct font *fn, FILE *fin)
+static int font_readkern(struct font *fn, FILE *fin)
 {
 	char c1[ILNLEN], c2[ILNLEN];
 	int i1, i2, val;
-	while (fscanf(fin, "%s", c1) == 1) {
-		if (!font_section(fn, fin, c1))
-			break;
-		if (fscanf(fin, "%s %d", c2, &val) != 2)
-			break;
-		if (fn->knn < NKERNS) {
-			i1 = font_idx(fn, font_find(fn, c1));
-			i2 = font_idx(fn, font_find(fn, c2));
-			if (i1 >= 0 && i2 >= 0) {
-				fn->knnext[fn->knn] = fn->knhead[i1];
-				fn->knhead[i1] = fn->knn;
-				fn->knval[fn->knn] = val;
-				fn->knpair[fn->knn] = i2;
-				fn->knn++;
-			}
-		}
+	if (fscanf(fin, "%s %s %d", c1, c2, &val) != 3)
+		return 1;
+	i1 = font_idx(fn, font_glyph(fn, c1));
+	i2 = font_idx(fn, font_glyph(fn, c2));
+	if (fn->knn < NKERNS && i1 >= 0 && i2 >= 0) {
+		fn->knnext[fn->knn] = fn->knhead[i1];
+		fn->knhead[i1] = fn->knn;
+		fn->knval[fn->knn] = val;
+		fn->knpair[fn->knn] = i2;
+		fn->knn++;
 	}
+	return 0;
 }
 
-static int font_section(struct font *fn, FILE *fin, char *name)
+static void skipline(FILE* filp)
 {
-	if (!strcmp("charset", name)) {
-		font_charset(fn, fin);
-		return 0;
-	}
-	if (!strcmp("kernpairs", name)) {
-		font_kernpairs(fn, fin);
-		return 0;
-	}
-	return 1;
+	int c;
+	do {
+		c = getc(filp);
+	} while (c != '\n' && c != EOF);
 }
 
 struct font *font_open(char *path)
@@ -179,48 +169,42 @@
 	if (!fin)
 		return NULL;
 	fn = malloc(sizeof(*fn));
+	if (!fn) {
+		fclose(fin);
+		return NULL;
+	}
 	memset(fn, 0, sizeof(*fn));
-	for (i = 0; i < LEN(fn->head); i++)
-		fn->head[i] = -1;
+	for (i = 0; i < LEN(fn->ghead); i++)
+		fn->ghead[i] = -1;
+	for (i = 0; i < LEN(fn->chead); i++)
+		fn->chead[i] = -1;
 	for (i = 0; i < LEN(fn->knhead); i++)
 		fn->knhead[i] = -1;
 	while (fscanf(fin, "%s", tok) == 1) {
-		if (tok[0] == '#') {
-			skipline(fin);
-			continue;
-		}
-		if (!strcmp("spacewidth", tok)) {
+		if (!strcmp("char", tok)) {
+			font_readchar(fn, fin);
+		} else if (!strcmp("kern", tok)) {
+			font_readkern(fn, fin);
+		} else if (!strcmp("spacewidth", tok)) {
 			fscanf(fin, "%d", &fn->spacewid);
-			continue;
-		}
-		if (!strcmp("special", tok)) {
+		} else if (!strcmp("special", tok)) {
 			fn->special = 1;
-			continue;
-		}
-		if (!strcmp("name", tok)) {
+		} else if (!strcmp("name", tok)) {
 			fscanf(fin, "%s", fn->name);
-			continue;
-		}
-		if (!strcmp("fontname", tok)) {
+		} else if (!strcmp("fontname", tok)) {
 			fscanf(fin, "%s", fn->fontname);
-			continue;
-		}
-		if (!strcmp("named", tok)) {
-			skipline(fin);
-			continue;
-		}
-		if (!strcmp("ligatures", tok)) {
+		} else if (!strcmp("ligatures", tok)) {
 			while (fscanf(fin, "%s", tok) == 1) {
 				if (!strcmp("0", tok))
 					break;
-				if (fn->nlig < NLIGS)
-					strcpy(fn->lig[fn->nlig++], tok);
+				if (fn->lgn < NLIGS)
+					strcpy(fn->lg[fn->lgn++], tok);
 			}
-			skipline(fin);
-			continue;
-		}
-		if (!font_section(fn, fin, tok))
+		} else if (!strcmp("charset", tok)) {
+			while (!font_readchar(fn, fin))
+				;
 			break;
+		}
 		skipline(fin);
 	}
 	fclose(fin);
--- a/roff.h
+++ b/roff.h
@@ -1,10 +1,3 @@
-/* converting scales */
-#define SC_IN		(dev_res)	/* inch in units */
-#define SC_PT		(SC_IN / 72)	/* point in units */
-#define SC_EM		(n_s * SC_IN / 72)
-#define SC_DW		(SC_EM / 3)	/* default width */
-#define SC_HT		(n_s * SC_PT)	/* character height */
-
 /* predefined array limits */
 #define PATHLEN		1024	/* path length */
 #define NFILES		16	/* number of input files */
@@ -11,7 +4,7 @@
 #define NFONTS		32	/* number of fonts */
 #define NGLYPHS		1024	/* glyphs in fonts */
 #define NLIGS		128	/* number of font ligatures */
-#define NKERNS		1024	/* number of font pairwise kerning pairs */
+#define NKERNS		1024	/* number of font kerning pairs */
 #define FNLEN		32	/* font name length */
 #define NMLEN		32	/* macro/register/environment/glyph name length */
 #define GNLEN		NMLEN	/* glyph name length */
@@ -31,6 +24,13 @@
 #define LIGLEN		4	/* length of ligatures */
 #define NCDEFS		128	/* number of character definitions (.char) */
 
+/* converting scales */
+#define SC_IN		(dev_res)	/* inch in units */
+#define SC_PT		(SC_IN / 72)	/* point in units */
+#define SC_EM		(n_s * SC_IN / 72)
+#define SC_DW		(SC_EM / 3)	/* default width */
+#define SC_HT		(n_s * SC_PT)	/* character height */
+
 /* escape sequences */
 #define ESC_Q	"bCDhHlLNoSvwxX"	/* \X'ccc' quoted escape sequences */
 #define ESC_P	"*fgkmns"		/* \Xc \X(cc \X[ccc] escape sequences */
@@ -92,8 +92,8 @@
 extern int dev_ver;
 
 struct glyph {
-	char name[GNLEN];	/* name of the glyph */
 	char id[GNLEN];		/* device-dependent glyph identifier */
+	char name[GNLEN];	/* the first character mapped to this glyph */
 	struct font *font;	/* glyph font */
 	int wid;		/* character width */
 	int type;		/* character type; ascender/descender */
@@ -107,16 +107,20 @@
 	int spacewid;
 	int special;
 	int cs, bd;			/* for .cs and .bd requests */
+	/* charset section characters */
 	char c[NGLYPHS][GNLEN];		/* character names in charset */
 	struct glyph *g[NGLYPHS];	/* character glyphs in charset */
 	int n;				/* number of characters in charset */
-	/* font ligatures */
-	char lig[NLIGS][LIGLEN * GNLEN];
-	int nlig;
-	/* glyph list based on the first character of glyph names */
-	int head[256];			/* glyph list head */
-	int next[NGLYPHS];		/* next item in glyph list */
-	/* kerning pair list per glyph */
+	/* glyph table based on the first character of their id fields in glyphs[] */
+	int ghead[256];			/* glyph list heads */
+	int gnext[NGLYPHS];		/* next item in glyph lists */
+	/* character table based on the first character of glyph names in c[] */
+	int chead[256];			/* character list heads */
+	int cnext[NGLYPHS];		/* next item in character lists */
+	/* font ligatures (lg*) */
+	char lg[NLIGS][LIGLEN * GNLEN];	/* ligatures */
+	int lgn;			/* number of ligatures in lg[] */
+	/* kerning pair table per glyph (kn*) */
 	int knhead[NGLYPHS];		/* kerning pairs of glyphs[] */
 	int knnext[NKERNS];		/* next item in knhead[] list */
 	int knpair[NKERNS];		/* kerning pair 2nd glyphs */