shithub: neatpost

Download patch

ref: ad676d4665a58d390dd9ce06477ad97c5b98fc91
parent: 8f5f11d521897752ff40bad2648c18a970f1536e
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Nov 19 19:01:19 EST 2013

font: new syntax for defining characters and kerning pairs

--- a/font.c
+++ b/font.c
@@ -3,21 +3,13 @@
 #include <string.h>
 #include "post.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,141 +16,69 @@
 
 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;
 }
 
-static int font_idx(struct font *fn, struct glyph *g)
+struct glyph *font_glyphput(struct font *fn, char *id, char *name, int wid, int type)
 {
-	return g ? g - fn->glyphs : -1;
+	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;
 }
 
-/*
- * Given a list of characters in the reverse order, font_lig()
- * returns the number of characters from the beginning of this
- * list that form a ligature in this font.  Zero naturally means
- * no ligature was matched.
- */
-int font_lig(struct font *fn, char **c, int n)
+static int font_readchar(struct font *fn, FILE *fin)
 {
-	int i;
-	/* concatenated characters in c[], in the correct order */
-	char s[GNLEN * 2] = "";
-	/* b[i] is the number of character of c[] in s + i */
-	int b[GNLEN * 2] = {0};
-	int len = 0;
-	for (i = 0; i < n; i++) {
-		char *cur = c[n - i - 1];
-		b[len] = n - i;
-		strcpy(s + len, cur);
-		len += strlen(cur);
-	}
-	for (i = 0; i < fn->nlig; i++) {
-		int l = strlen(fn->lig[i]);
-		if (b[len - l] && !strcmp(s + len - l, fn->lig[i]))
-			if (font_find(fn, fn->lig[i]))
-				return b[len - l];
-	}
-	return 0;
-}
-
-/* return pairwise kerning value between c1 and c2 */
-int font_kern(struct font *fn, char *c1, char *c2)
-{
-	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;
-}
-
-static int font_section(struct font *fn, FILE *fin, char *name);
-
-static void font_charset(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 void skipline(FILE* filp)
 {
-	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++;
-			}
-		}
-	}
+	int c;
+	do {
+		c = getc(filp);
+	} while (c != '\n' && c != EOF);
 }
 
-static int font_section(struct font *fn, FILE *fin, char *name)
-{
-	if (!strcmp("charset", name)) {
-		font_charset(fn, fin);
-		return 0;
-	}
-	if (!strcmp("kernpairs", name)) {
-		font_kernpairs(fn, fin);
-		return 0;
-	}
-	return 1;
-}
-
 struct font *font_open(char *path)
 {
 	struct font *fn;
@@ -169,48 +89,35 @@
 	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->knhead); i++)
-		fn->knhead[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;
 	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("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)) {
-			while (fscanf(fin, "%s", tok) == 1) {
+		} 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);
-			}
-			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/out.c
+++ b/out.c
@@ -1,4 +1,3 @@
-#include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -46,8 +45,7 @@
 
 static void o_queue(struct glyph *g)
 {
-	int type = 1 + !isdigit((g)->id[0]);
-	int num = atoi(g->id);
+	int type = 1 + (g->pos <= 0);
 	if (o_qtype != type || o_qend != o_h || o_qv != o_v) {
 		o_flush();
 		o_qh = o_h;
@@ -56,10 +54,11 @@
 		outf(type == 1 ? "(" : "[");
 	}
 	if (o_qtype == 1) {
-		if (num >= ' ' && num <= '~')
-			outf("%s%c", strchr("()\\", num) ? "\\" : "", num);
+		if (g->pos >= ' ' && g->pos <= '~')
+			outf("%s%c", strchr("()\\", g->pos) ? "\\" : "", g->pos);
 		else
-			outf("\\%d%d%d", (num >> 6) & 7, (num >> 3) & 7, num & 7);
+			outf("\\%d%d%d", (g->pos >> 6) & 7,
+					(g->pos >> 3) & 7, g->pos & 7);
 	} else {
 		outf("/%s", g->id);
 	}
--- a/post.h
+++ b/post.h
@@ -2,13 +2,10 @@
 #define PATHLEN		1024	/* path length */
 #define NFONTS		32	/* number of fonts */
 #define NGLYPHS		1024	/* glyphs in fonts */
-#define NLIGS		32	/* number of font ligatures */
-#define NKERNS		512	/* number of font pairwise kerning pairs */
 #define FNLEN		64	/* font name length */
 #define GNLEN		32	/* glyph name length */
 #define ILNLEN		1000	/* line limit of input files */
 #define LNLEN		4000	/* line buffer length (ren.c/out.c) */
-#define LIGLEN		4	/* length of ligatures */
 
 #define MIN(a, b)	((a) < (b) ? (a) : (b))
 #define MAX(a, b)	((a) < (b) ? (b) : (a))
@@ -21,11 +18,12 @@
 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 */
+	int pos;		/* glyph code */
 };
 
 struct font {
@@ -35,21 +33,17 @@
 	int nglyphs;
 	int spacewid;
 	int special;
-	char c[NGLYPHS][FNLEN];		/* character names in charset */
+	int cs, bd;			/* for .cs and .bd requests */
+	/* glyph list based on the first character of their id fields in glyphs[] */
+	int ghead[256];			/* glyph list head */
+	int gnext[NGLYPHS];		/* next item in glyph list */
+	/* 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 */
-	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 */
+	/* glyph list based on the first character of glyph names in c[] */
+	int chead[256];			/* glyph list head */
+	int cnext[NGLYPHS];		/* next item in glyph list */
 };
 
 /* output device functions */
@@ -67,8 +61,6 @@
 void font_close(struct font *fn);
 struct glyph *font_glyph(struct font *fn, char *id);
 struct glyph *font_find(struct font *fn, char *name);
-int font_lig(struct font *fn, char **c, int n);
-int font_kern(struct font *fn, char *c1, char *c2);
 
 /* output functions */
 void out(char *s, ...);