shithub: neatmkfn

Download patch

ref: 7c1e51d85563e6726d0eecc3cc149a6e26584975
parent: 7bdfd06ce987fb87de5ca577363a07e28b8b7616
author: Ali Gholami Rudi <ali@rudi.ir>
date: Fri Mar 23 15:31:08 EDT 2018

otf: report OpenType language of font rules

Font gpos and gsub lines may now look like "gsub feat:scrp:lang ...".
Also, for every script specified with -S, all languages all
languages are included by default.  The list of languages may
be overriden with -L, as before.

--- a/mkfn.c
+++ b/mkfn.c
@@ -1,7 +1,7 @@
 /*
  * NEATMKFN - GENERATE NEATROFF FONT DESCRIPTIONS
  *
- * Copyright (C) 2012-2016 Ali Gholami Rudi <ali at rudi dot ir>
+ * Copyright (C) 2012-2018 Ali Gholami Rudi <ali at rudi dot ir>
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -82,7 +82,7 @@
 int trfn_lang(char *lang, int nlangs)
 {
 	if (!trfn_langs)
-		return nlangs == 1 || !lang;
+		return 1;
 	if (!lang)
 		lang = "";
 	if (!strcmp("help", trfn_langs))
--- a/otf.c
+++ b/otf.c
@@ -725,42 +725,66 @@
 /* an otf gsub/gpos lookup */
 struct otflookup {
 	char scrp[8];		/* script name */
+	char lang[8];		/* language 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, char *script, struct otflookup *lookups)
+static int otf_featrec(void *otf, void *gtab, void *featrec,
+			char *stag, char *ltag,
+			struct otflookup *lookups, int lookups_n)
 {
 	void *feats = gtab + U16(gtab, 6);
 	void *feat = feats + U16(featrec, 4);
-	int nlookups = U16(feat, 2);
-	int i;
-	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);
+	int n = U16(feat, 2);
+	int i, j;
+	for (i = 0; i < n; i++) {
+		int lookup = U16(feat, 4 + 2 * i);	/* lookup index */
+		/* do not store features common to all languages in a script */
+		for (j = 0; j < lookups_n; j++)
+			if (lookups[j].lookup == lookup && !lookups[j].lang[0])
+				if (!strcmp(lookups[j].scrp, stag))
+					break;
+		if (j == lookups_n) {
+			memcpy(lookups[j].feat, featrec, 4);
+			lookups[j].feat[4] = '\0';
+			strcpy(lookups[j].scrp, stag);
+			strcpy(lookups[j].lang, ltag);
+			lookups[j].lookup = U16(feat, 4 + 2 * i);
+			lookups_n++;
+		}
 	}
-	return nlookups;
+	return lookups_n;
 }
 
 /* parse the given language table and its feature tables */
-static int otf_lang(void *otf, void *gtab, void *lang, char *script, struct otflookup *lookups)
+static int otf_lang(void *otf, void *gtab, void *lang, char *stag, char *ltag,
+		struct otflookup *lookups, int lookups_n)
 {
 	void *feats = gtab + U16(gtab, 6);
 	int featidx = U16(lang, 2);
 	int nfeat = U16(lang, 4);
-	int n = 0;
 	int i;
 	if (featidx != 0xffff)
-		n += otf_featrec(otf, gtab, feats + 2 + 6 * featidx, script, lookups + n);
+		lookups_n = otf_featrec(otf, gtab, feats + 2 + 6 * featidx,
+				stag, ltag, lookups, lookups_n);
 	for (i = 0; i < nfeat; i++)
-		n += otf_featrec(otf, gtab,
-				feats + 2 + 6 * U16(lang, 6 + 2 * i), script, lookups + n);
-	return n;
+		lookups_n = otf_featrec(otf, gtab, feats + 2 + 6 * U16(lang, 6 + 2 * i),
+				stag, ltag, lookups, lookups_n);
+	return lookups_n;
 }
 
+/* return lookup table tag (i.e. liga:latn:ENG); returns a static buffer */
+static char *lookuptag(struct otflookup *lu)
+{
+	static char tag[16];
+	sprintf(tag, "%s:%s", lu->feat, lu->scrp[0] ? lu->scrp : "DFLT");
+	if (lu->lang[0])
+		sprintf(strchr(tag, '\0'), ":%s", lu->lang);
+	return tag;
+}
+
 static int lookupcmp(void *v1, void *v2)
 {
 	struct otflookup *l1 = v1;
@@ -791,15 +815,15 @@
 		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),
-						stag, 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(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);
+				n = otf_lang(otf, gpos, script + U16(lrec, 4),
+						stag, ltag, lookups, n);
 		}
 	}
 	qsort(lookups, n, sizeof(lookups[0]), (void *) lookupcmp);
@@ -811,14 +835,12 @@
 	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);
 		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");
+		char *tag = lookuptag(&lookups[i]);
 		for (j = 0; j < ntabs; j++) {
 			void *tab = lookup + U16(lookup, 6 + 2 * j);
 			int type = ltype;
@@ -851,14 +873,12 @@
 	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);
 		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");
+		char *tag = lookuptag(&lookups[i]);
 		for (j = 0; j < ntabs; j++) {
 			void *tab = lookup + U16(lookup, 6 + 2 * j);
 			int type = ltype;