shithub: neatroff

Download patch

ref: e071b935a6af5f98c9d1fd17e0ab36e7bf9c5335
parent: bd6b4b8bf37c00319dbc17b898c1426594169809
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Jul 30 10:52:02 EDT 2013

font: store kerning pairs in per-glyph lists

--- a/font.c
+++ b/font.c
@@ -31,6 +31,11 @@
 	return NULL;
 }
 
+static int font_idx(struct font *fn, struct glyph *g)
+{
+	return g ? g - fn->glyphs : -1;
+}
+
 static int font_section(struct font *fn, FILE *fin, char *name);
 
 static void font_charset(struct font *fn, FILE *fin)
@@ -75,17 +80,22 @@
 static void font_kernpairs(struct font *fn, FILE *fin)
 {
 	char c1[ILNLEN], c2[ILNLEN];
-	int val;
+	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->nkern < NKERNS) {
-			strcpy(fn->kern_c1[fn->nkern], c1);
-			strcpy(fn->kern_c2[fn->nkern], c2);
-			fn->kern[fn->nkern] = val;
-			fn->nkern++;
+		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++;
+			}
 		}
 	}
 }
@@ -135,10 +145,17 @@
 /* return pairwise kerning value between c1 and c2 */
 int font_kern(struct font *fn, char *c1, char *c2)
 {
-	int i;
-	for (i = 0; i < fn->nkern; i++)
-		if (!strcmp(fn->kern_c1[i], c1) && !strcmp(fn->kern_c2[i], c2))
-			return fn->kern[i];
+	int i1, i2, i;
+	i1 = font_idx(fn, font_find(fn, c1));
+	i2 = font_idx(fn, font_find(fn, c2));
+	if (i1 < 0 || i2 < 0)
+		return 0;
+	i = fn->knhead[i1];
+	while (i >= 0) {
+		if (fn->knpair[i] == i2)
+			return fn->knval[i];
+		i = fn->knnext[i];
+	}
 	return 0;
 }
 
@@ -152,6 +169,8 @@
 	memset(fn, 0, sizeof(*fn));
 	for (i = 0; i < LEN(fn->head); i++)
 		fn->head[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);
--- a/roff.h
+++ b/roff.h
@@ -9,10 +9,10 @@
 #define PATHLEN		1024	/* path length */
 #define NFILES		16	/* number of input files */
 #define NFONTS		32	/* number of fonts */
+#define NGLYPHS		1024	/* glyphs in fonts */
 #define NLIGS		32	/* number of font ligatures */
-#define NKERNS		128	/* number of font pairwise kerning pairs */
+#define NKERNS		512	/* number of font pairwise kerning pairs */
 #define FNLEN		32	/* font name length */
-#define NGLYPHS		512	/* glyphs in fonts */
 #define NMLEN		32	/* macro/register/environment/glyph name length */
 #define GNLEN		NMLEN	/* glyph name length */
 #define RNLEN		NMLEN	/* register/macro name */
@@ -107,15 +107,18 @@
 	char c[NGLYPHS][GNLEN];		/* character names in charset */
 	struct glyph *g[NGLYPHS];	/* character glyphs in charset */
 	int n;				/* number of characters in charset */
-	char lig[NLIGS][GNLEN * 4];	/* font ligatures */
+	/* font ligatures */
+	char lig[NLIGS][LIGLEN * GNLEN];
 	int nlig;
-	int kern[NKERNS];		/* font pairwise kerning */
-	char kern_c1[NKERNS][GNLEN];
-	char kern_c2[NKERNS][GNLEN];
-	int nkern;
 	/* 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 */
+	int knhead[NGLYPHS];		/* kerning pairs of glyphs[] */
+	int knnext[NKERNS];		/* next item in knhead[] list */
+	int knpair[NKERNS];		/* kerning pair 2nd glyphs */
+	int knval[NKERNS];		/* font pairwise kerning value */
+	int knn;			/* number of kerning pairs */
 };
 
 /* output device functions */