shithub: neatroff

Download patch

ref: 33b7ad9aa1c7d555f6fd75030568c1f484121aa7
parent: 4845d662a2115ddae6e03fe550b5940f27d1e08f
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Jan 14 15:59:16 EST 2017

font: specify font script with .ffsc request

Example: .ffsc FN latn

--- a/font.c
+++ b/font.c
@@ -21,7 +21,7 @@
 		short x, y, xadv, yadv;	/* gpos data */
 	} *pats;			/* rule pattern */
 	short len;			/* pats[] length */
-	short feat;			/* feature owning this rule */
+	short feat, scrp;		/* rule's feature and script */
 };
 
 struct font {
@@ -36,10 +36,11 @@
 	struct dict *gl_dict;		/* mapping from gl[i].id to i */
 	struct dict *ch_dict;		/* charset mapping */
 	struct dict *ch_map;		/* characters mapped via font_map() */
-	/* font features */
+	/* font features and scripts */
 	char feat_name[NFEATS][8];	/* feature names */
 	int feat_set[NFEATS];		/* feature enabled */
-	int feat_n;
+	char scrp_name[NSCRPS][8];	/* script names */
+	int scrp;			/* current script */
 	/* glyph substitution and positioning */
 	struct grule *gsub;		/* glyph substitution rules */
 	int gsub_n, gsub_sz;
@@ -138,6 +139,8 @@
 	int ncon = 0;		/* number of initial context glyphs */
 	struct gpat *pats = rule->pats;
 	int j;
+	if (fn->scrp >= 0 && fn->scrp != rule->scrp)
+		return 0;
 	if (!fn->feat_set[rule->feat])
 		return 0;
 	/* the number of initial context glyphs */
@@ -317,19 +320,32 @@
 	return 0;
 }
 
-static int font_findfeat(struct font *fn, char *feat, int mk)
+static int font_findfeat(struct font *fn, char *feat)
 {
 	int i;
-	for (i = 0; i < fn->feat_n; i++)
+	for (i = 0; i < LEN(fn->feat_name) && fn->feat_name[i][0]; i++)
 		if (!strcmp(feat, fn->feat_name[i]))
 			return i;
-	if (mk) {
-		snprintf(fn->feat_name[fn->feat_n],
-			sizeof(fn->feat_name[fn->feat_n]), "%s", feat);
+	if (i < LEN(fn->feat_name)) {
+		snprintf(fn->feat_name[i], sizeof(fn->feat_name[i]), "%s", feat);
+		return i;
 	}
-	return mk ? fn->feat_n++ : -1;
+	return -1;
 }
 
+static int font_findscrp(struct font *fn, char *scrp)
+{
+	int i;
+	for (i = 0; i < LEN(fn->scrp_name) && fn->scrp_name[i][0]; i++)
+		if (!strcmp(scrp, fn->scrp_name[i]))
+			return i;
+	if (i < LEN(fn->scrp_name)) {
+		snprintf(fn->scrp_name[i], sizeof(fn->scrp_name[i]), "%s", scrp);
+		return i;
+	}
+	return -1;
+}
+
 static struct gpat *font_gpat(struct font *fn, int len)
 {
 	struct gpat *pats = xmalloc(len * sizeof(pats[0]));
@@ -337,7 +353,7 @@
 	return pats;
 }
 
-static struct grule *font_gsub(struct font *fn, char *feat, int len)
+static struct grule *font_gsub(struct font *fn, int len, int feat, int scrp)
 {
 	struct grule *rule;
 	struct gpat *pats = font_gpat(fn, len);
@@ -349,11 +365,12 @@
 	rule = &fn->gsub[fn->gsub_n++];
 	rule->pats = pats;
 	rule->len = len;
-	rule->feat = font_findfeat(fn, feat, 1);
+	rule->feat = feat;
+	rule->scrp = scrp;
 	return rule;
 }
 
-static struct grule *font_gpos(struct font *fn, char *feat, int len)
+static struct grule *font_gpos(struct font *fn, int len, int feat, int scrp)
 {
 	struct grule *rule;
 	struct gpat *pats = font_gpat(fn, len);
@@ -365,7 +382,8 @@
 	rule = &fn->gpos[fn->gpos_n++];
 	rule->pats = pats;
 	rule->len = len;
-	rule->feat = font_findfeat(fn, feat, 1);
+	rule->feat = feat;
+	rule->scrp = scrp;
 	return rule;
 }
 
@@ -383,16 +401,28 @@
 	return p->g < 0;
 }
 
+static void font_readfeat(struct font *fn, char *tok, int *feat, int *scrp)
+{
+	*scrp = -1;
+	if (strchr(tok, ':')) {
+		*scrp = font_findscrp(fn, strchr(tok, ':') + 1);
+		strchr(tok, ':')[0] = '\0';
+	}
+	*feat = font_findfeat(fn, tok);
+}
+
 static int font_readgsub(struct font *fn, FILE *fin)
 {
 	char tok[128];
 	struct grule *rule;
+	int feat, scrp;
 	int i, n;
 	if (fscanf(fin, "%s %d", tok, &n) != 2)
 		return 1;
 	if (strchr(tok, ':'))		/* "feature:script" */
 		strchr(tok, ':')[0] = '\0';
-	rule = font_gsub(fn, tok, n);
+	font_readfeat(fn, tok, &feat, &scrp);
+	rule = font_gpos(fn, n, feat, scrp);
 	for (i = 0; i < n; i++) {
 		if (fscanf(fin, "%s", tok) != 1)
 			return 1;
@@ -413,12 +443,12 @@
 	char tok[128];
 	char *col;
 	struct grule *rule;
+	int feat, scrp;
 	int i, n;
 	if (fscanf(fin, "%s %d", tok, &n) != 2)
 		return 1;
-	if (strchr(tok, ':'))		/* "feature:script" */
-		strchr(tok, ':')[0] = '\0';
-	rule = font_gpos(fn, tok, n);
+	font_readfeat(fn, tok, &feat, &scrp);
+	rule = font_gpos(fn, n, feat, scrp);
 	for (i = 0; i < n; i++) {
 		if (fscanf(fin, "%s", tok) != 1)
 			return 1;
@@ -459,7 +489,7 @@
 	int val;
 	if (fscanf(fin, "%s %s %d", c1, c2, &val) != 3)
 		return 1;
-	rule = font_gpos(fn, "kern", 2);
+	rule = font_gpos(fn, 2, font_findfeat(fn, "kern"), -1);
 	rule->pats[0].g = font_idx(fn, font_glyph(fn, c1));
 	rule->pats[1].g = font_idx(fn, font_glyph(fn, c2));
 	rule->pats[0].xadv = val;
@@ -477,7 +507,7 @@
 	int j, n = 0;
 	while (utf8read(&s, c) > 0)
 		g[n++] = font_idx(fn, font_find(fn, c));
-	rule = font_gsub(fn, "liga", n + 1);
+	rule = font_gsub(fn, n + 1, font_findfeat(fn, "liga"), -1);
 	for (j = 0; j < n; j++) {
 		rule->pats[j].g = g[j];
 		rule->pats[j].flg = GF_PAT;
@@ -582,6 +612,7 @@
 	for (i = 0; i < fn->gpos_n; i++)
 		font_isetinsert(fn, fn->gpos0, i,
 			font_rulefirstpat(fn, &fn->gpos[i]));
+	fn->scrp = -1;
 	return fn;
 }
 
@@ -688,9 +719,15 @@
 /* enable/disable font features; returns the previous value */
 int font_feat(struct font *fn, char *name, int val)
 {
-	int idx = font_findfeat(fn, name, 0);
+	int idx = font_findfeat(fn, name);
 	int old = idx >= 0 ? fn->feat_set[idx] : 0;
 	if (idx >= 0)
 		fn->feat_set[idx] = val != 0;
 	return old;
+}
+
+/* set font script */
+void font_scrp(struct font *fn, char *name)
+{
+	fn->scrp = name ? font_findscrp(fn, name) : -1;
 }
--- a/roff.h
+++ b/roff.h
@@ -48,6 +48,7 @@
 #define NHCODES		512	/* number of .hcode characters */
 #define WORDLEN		256	/* word length (for hyph.c) */
 #define NFEATS		128	/* number of features per font */
+#define NSCRPS		128	/* number of scripts per font */
 
 /* converting scales */
 #define SC_IN		(dev_res)	/* inch in units */
@@ -173,6 +174,7 @@
 void font_setzoom(struct font *fn, int zoom);
 int font_zoom(struct font *fn, int sz);
 int font_feat(struct font *fn, char *name, int val);
+void font_scrp(struct font *fn, char *name);
 int font_layout(struct font *fn, struct glyph **src, int nsrc, int sz,
 		struct glyph **dst, int *dmap,
 		int *x, int *y, int *xadv, int *yadv, int lg, int kn);
--- a/tr.c
+++ b/tr.c
@@ -612,6 +612,13 @@
 			font_feat(fn, args[i] + 1, args[i][0] == '+');
 }
 
+static void tr_ffsc(char **args)
+{
+	struct font *fn = args[1] ? dev_font(dev_pos(args[1])) : NULL;
+	if (fn && args[2])
+		font_scrp(fn, args[2] ? args[2] : NULL);
+}
+
 static void tr_nm(char **args)
 {
 	if (!args[1]) {
@@ -1039,6 +1046,7 @@
 	{"fl", tr_br},
 	{"fmap", tr_fmap},
 	{"fp", tr_fp},
+	{"ffsc", tr_ffsc},
 	{"fspecial", tr_fspecial},
 	{"ft", tr_ft},
 	{"fzoom", tr_fzoom},