shithub: neatmkfn

Download patch

ref: 62cf866e11a041bad7607801f4f323dae8c23938
parent: c665634e1e8cc937426c71e98fcc9d2a13543d1c
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Dec 17 15:42:25 EST 2016

otf: for each rule report its script

--- a/mkfn.c
+++ b/mkfn.c
@@ -24,7 +24,6 @@
 
 static char *trfn_scripts;	/* filtered scripts */
 static char *trfn_langs;	/* filtered languages */
-static char *trfn_order;	/* feature ordering */
 
 /* OpenType specifies a specific feature order for different scripts */
 static char *scriptorder[][2] = {
@@ -63,11 +62,6 @@
 /* return 1 if the given script is to be included */
 int trfn_script(char *script, int nscripts)
 {
-	int i;
-	trfn_order = NULL;
-	for (i = 0; i < LEN(scriptorder); i++)
-		if (script && !strcmp(script, scriptorder[i][0]))
-			trfn_order = scriptorder[i][1];
 	/* fill trfn_scripts (if unspecified) in the first call */
 	if (!trfn_scripts) {
 		if (nscripts == 1 || !script)
@@ -99,10 +93,19 @@
 }
 
 /* return the rank of the given feature, for the current script */
-int trfn_featrank(char *feat)
+int trfn_featrank(char *scrp, char *feat)
 {
-	char *s = trfn_order ? strstr(trfn_order, feat) : NULL;
-	return s ? s - trfn_order : 1000;
+	static char **order;
+	int i;
+	if (!order || strcmp(scrp, order[0])) {
+		order = NULL;
+		for (i = 0; i < LEN(scriptorder); i++)
+			if (!strcmp(scrp, scriptorder[i][0]))
+				order = scriptorder[i];
+	}
+	if (order && strstr(order[1], feat))
+		return strstr(order[1], feat) - order[1];
+	return 1000;
 }
 
 int otf_read(void);
--- a/otf.c
+++ b/otf.c
@@ -35,7 +35,7 @@
 static int upm;			/* units per em */
 static int res;			/* device resolution */
 static int kmin;		/* minimum kerning value */
-static int warn;
+static int warn;		/* report unsupported tables */
 
 static char *macset[];
 
@@ -50,6 +50,13 @@
 	return (w < 0 ? owid(w) - d / 2 : owid(w) + d / 2) / d;
 }
 
+/* weather the script is right-to-left */
+static int otf_r2l(char *feat)
+{
+	char *scrp = strchr(feat, ':') + 1;
+	return !strcmp("arab", scrp) || !strcmp("hebr", scrp);
+}
+
 /* report unsupported otf tables */
 static void otf_unsupported(char *sub, int type, int fmt)
 {
@@ -494,15 +501,23 @@
 	for (i = 0; i < mcnt; i++) {
 		void *mark = marks + U16(marks, 2 + 4 * i + 2);	/* mark anchor */
 		int dx = -uwid(S16(mark, 2));
-		int dy = uwid(S16(mark, 4));
-		printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
+		int dy = -uwid(S16(mark, 4));
+		if (otf_r2l(feat)) {
+			dx += uwid(glyph_wid[mcov[i]]);
+			dy = -dy;
+		}
+		printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
 			feat, bgrp, glyph_name[mcov[i]], dx, dy, 0, 0);
 	}
 	for (i = 0; i < bcnt; i++) {
 		for (j = 0; j < ccnt; j++) {
 			void *base = bases + U16(bases, 2 + ccnt * 2 * i + 2 * j);
-			int dx = uwid(S16(base, 2));
-			int dy = -uwid(S16(base, 4));
+			int dx = uwid(S16(base, 2)) - uwid(glyph_wid[bcov[i]]);
+			int dy = uwid(S16(base, 4));
+			if (otf_r2l(feat)) {
+				dx += uwid(glyph_wid[bcov[i]]);
+				dy = -dy;
+			}
 			printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
 				feat, glyph_name[bcov[i]], cgrp[j], dx, dy, 0, 0);
 		}
@@ -685,12 +700,13 @@
 
 /* an otf gsub/gpos lookup */
 struct otflookup {
+	char scrp[8];		/* script name */
 	char feat[8];		/* feature name */
 	int lookup;		/* index into the lookup table */
 };
 
 /* parse the given gsub/gpos feature table */
-static int otf_featrec(void *otf, void *gtab, void *featrec, struct otflookup *lookups)
+static int otf_featrec(void *otf, void *gtab, void *featrec, char *script, struct otflookup *lookups)
 {
 	void *feats = gtab + U16(gtab, 6);
 	void *feat = feats + U16(featrec, 4);
@@ -699,6 +715,7 @@
 	for (i = 0; i < nlookups; i++) {
 		memcpy(lookups[i].feat, featrec, 4);
 		lookups[i].feat[4] = '\0';
+		strcpy(lookups[i].scrp, script);
 		lookups[i].lookup = U16(feat, 4 + 2 * i);
 	}
 	return nlookups;
@@ -705,7 +722,7 @@
 }
 
 /* parse the given language table and its feature tables */
-static int otf_lang(void *otf, void *gtab, void *lang, struct otflookup *lookups)
+static int otf_lang(void *otf, void *gtab, void *lang, char *script, struct otflookup *lookups)
 {
 	void *feats = gtab + U16(gtab, 6);
 	int featidx = U16(lang, 2);
@@ -713,10 +730,10 @@
 	int n = 0;
 	int i;
 	if (featidx != 0xffff)
-		n += otf_featrec(otf, gtab, feats + 2 + 6 * featidx, lookups + n);
+		n += otf_featrec(otf, gtab, feats + 2 + 6 * featidx, script, lookups + n);
 	for (i = 0; i < nfeat; i++)
 		n += otf_featrec(otf, gtab,
-				feats + 2 + 6 * U16(lang, 6 + 2 * i), lookups + n);
+				feats + 2 + 6 * U16(lang, 6 + 2 * i), script, lookups + n);
 	return n;
 }
 
@@ -724,8 +741,10 @@
 {
 	struct otflookup *l1 = v1;
 	struct otflookup *l2 = v2;
-	if (trfn_featrank(l1->feat) != trfn_featrank(l2->feat))
-		return trfn_featrank(l1->feat) - trfn_featrank(l2->feat);
+	if (strcmp(l1->scrp, l2->scrp))
+		return strcmp(l1->scrp, l2->scrp);
+	if (trfn_featrank(l1->scrp, l1->feat) != trfn_featrank(l1->scrp, l2->feat))
+		return trfn_featrank(l1->scrp, l1->feat) - trfn_featrank(l1->scrp, l2->feat);
 	return l1->lookup - l2->lookup;
 }
 
@@ -735,26 +754,28 @@
 	void *scripts = gpos + U16(gpos, 4);
 	int nscripts, nlangs;
 	void *script;
-	char tag[8];
+	char stag[8], ltag[8];		/* script and language tags */
 	int i, j;
 	int n = 0;
 	nscripts = U16(scripts, 0);
 	for (i = 0; i < nscripts; i++) {
 		void *grec = scripts + 2 + 6 * i;
-		memcpy(tag, grec, 4);
-		tag[4] = '\0';
-		if (!trfn_script(tag, nscripts))
+		memcpy(stag, grec, 4);
+		stag[4] = '\0';
+		if (!trfn_script(stag, nscripts))
 			continue;
 		script = scripts + U16(grec, 4);
 		nlangs = U16(script, 2);
 		if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
-			n += otf_lang(otf, gpos, script + U16(script, 0), lookups + n);
+			n += otf_lang(otf, gpos, script + U16(script, 0),
+						stag, lookups + n);
 		for (j = 0; j < nlangs; j++) {
 			void *lrec = script + 4 + 6 * j;
-			memcpy(tag, lrec, 4);
-			tag[4] = '\0';
-			if (trfn_lang(tag, nlangs + (U16(script, 0) != 0)))
-				n += otf_lang(otf, gpos, script + U16(lrec, 4), lookups + n);
+			memcpy(ltag, lrec, 4);
+			ltag[4] = '\0';
+			if (trfn_lang(ltag, nlangs + (U16(script, 0) != 0)))
+				n += otf_lang(otf, gpos, script + U16(lrec, 4),
+						stag, lookups + n);
 		}
 	}
 	qsort(lookups, n, sizeof(lookups[0]), (void *) lookupcmp);
@@ -766,12 +787,14 @@
 	struct otflookup lookups[NLOOKUPS];
 	void *lookuplist = gpos + U16(gpos, 8);
 	int nlookups = otf_gtab(otf, gpos, lookups);
+	char tag[16];
 	int i, j;
 	for (i = 0; i < nlookups; i++) {
 		void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
-		char *tag = lookups[i].feat;
 		int ltype = U16(lookup, 0);
 		int ntabs = U16(lookup, 4);
+		sprintf(tag, "%s:%s", lookups[i].feat,
+				lookups[i].scrp[0] ? lookups[i].scrp : "DFLT");
 		for (j = 0; j < ntabs; j++) {
 			void *tab = lookup + U16(lookup, 6 + 2 * j);
 			int type = ltype;
@@ -804,12 +827,14 @@
 	struct otflookup lookups[NLOOKUPS];
 	void *lookuplist = gsub + U16(gsub, 8);
 	int nlookups = otf_gtab(otf, gsub, lookups);
+	char tag[16];
 	int i, j;
 	for (i = 0; i < nlookups; i++) {
 		void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
-		char *tag = lookups[i].feat;
 		int ltype = U16(lookup, 0);
 		int ntabs = U16(lookup, 4);
+		sprintf(tag, "%s:%s", lookups[i].feat,
+				lookups[i].scrp[0] ? lookups[i].scrp : "DFLT");
 		for (j = 0; j < ntabs; j++) {
 			void *tab = lookup + U16(lookup, 6 + 2 * j);
 			int type = ltype;
--- a/trfn.h
+++ b/trfn.h
@@ -7,4 +7,4 @@
 void trfn_kern(char *c1, char *c2, int x);
 int trfn_script(char *script, int nscripts);
 int trfn_lang(char *lang, int nlangs);
-int trfn_featrank(char *feat);
+int trfn_featrank(char *scrp, char *feat);