ref: c223c57a8b7d86b7e89f74fe3c4b8a5d6af754d1
parent: 8509d0b1f86126dda8af06b928b30d9ca485cc92
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Jul 30 11:19:15 EDT 2013
font: update from neatroff
--- a/font.c
+++ b/font.c
@@ -13,10 +13,12 @@
struct glyph *font_find(struct font *fn, char *name)
{
- int i;
- for (i = 0; i < fn->n; i++)
- if (name[0] == fn->c[i][0] && !strcmp(name, fn->c[i]))
+ int i = fn->head[(unsigned char) name[0]];
+ while (i >= 0) {
+ if (!strcmp(name, fn->c[i]))
return fn->g[i];
+ i = fn->next[i];
+ }
return NULL;
}
@@ -29,6 +31,57 @@
return NULL;
}
+static int font_idx(struct font *fn, struct glyph *g)
+{
+ return g ? g - fn->glyphs : -1;
+}
+
+/*
+ * 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)
+{
+ 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)
@@ -64,6 +117,8 @@
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++;
}
}
@@ -71,17 +126,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++;
+ }
}
}
}
@@ -99,33 +159,18 @@
return 1;
}
-/* return 1 if lig is a ligature */
-int font_lig(struct font *fn, char *lig)
-{
- int i;
- for (i = 0; i < fn->nlig; i++)
- if (!strcmp(lig, fn->lig[i]))
- return font_find(fn, lig) != NULL;
- return 0;
-}
-
-/* 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];
- return 0;
-}
-
struct font *font_open(char *path)
{
struct font *fn = malloc(sizeof(*fn));
char tok[ILNLEN];
FILE *fin;
+ int i;
fin = fopen(path, "r");
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);
@@ -163,6 +208,7 @@
}
if (!font_section(fn, fin, tok))
break;
+ skipline(fin);
}
fclose(fin);
return fn;
--- a/post.h
+++ b/post.h
@@ -1,13 +1,14 @@
/* predefined array limits */
#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 128 /* number of font pairwise kerning pairs */
+#define NKERNS 512 /* number of font pairwise kerning pairs */
#define FNLEN 64 /* font name length */
-#define NGLYPHS 512 /* glyphs in fonts */
#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))
@@ -37,12 +38,18 @@
char c[NGLYPHS][FNLEN]; /* 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 */
@@ -60,7 +67,7 @@
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 font_lig(struct font *fn, char **c, int n);
int font_kern(struct font *fn, char *c1, char *c2);
/* output functions */