shithub: neatmkfn

Download patch

ref: f8c8bf6715587c17fc215367dd895b497d6d483f
parent: 1e3f9a4ab59afc89e620de3318a76df796d59b4f
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Aug 5 05:57:21 EDT 2014

otf: warn about unsupported otf features with -w

--- a/mkfn.c
+++ b/mkfn.c
@@ -131,7 +131,7 @@
 }
 
 int otf_read(void);
-void otf_feat(int res, int kmin);
+void otf_feat(int res, int kmin, int warn);
 
 static char *usage =
 	"Usage: mktrfn [options] <input >output\n"
@@ -145,21 +145,26 @@
 	"  -k kmin \tspecify the minimum amount of kerning (0)\n"
 	"  -b      \tinclude glyph bounding boxes\n"
 	"  -S scrs \tcomma-separated list of scripts to include (help to list)\n"
-	"  -L langs\tcomma-separated list of languages to include (help to list)\n";
+	"  -L langs\tcomma-separated list of languages to include (help to list)\n"
+	"  -w      \twarn about unsupported font features\n";
 
 int main(int argc, char *argv[])
 {
 	int afm = 1;
-	int i = 1;
 	int res = 720;
 	int spc = 0;
 	int kmin = 0;
 	int bbox = 0;
+	int warn = 0;
+	int i;
 	for (i = 1; i < argc && argv[i][0] == '-'; i++) {
 		switch (argv[i][1]) {
 		case 'a':
 			afm = 1;
 			break;
+		case 'b':
+			bbox = 1;
+			break;
 		case 'k':
 			kmin = atoi(argv[i][2] ? argv[i] + 2 : argv[++i]);
 			break;
@@ -184,8 +189,8 @@
 		case 't':
 			trfn_trfont(argv[i][2] ? argv[i] + 2 : argv[++i]);
 			break;
-		case 'b':
-			bbox = 1;
+		case 'w':
+			warn = 1;
 			break;
 		default:
 			printf("%s", usage);
@@ -199,7 +204,7 @@
 		otf_read();
 	trfn_print();
 	if (!afm)
-		otf_feat(res, kmin);
+		otf_feat(res, kmin, warn);
 	trfn_done();
 	return 0;
 }
--- a/otf.c
+++ b/otf.c
@@ -38,6 +38,7 @@
 static int upm;			/* units per em */
 static int res;			/* device resolution */
 static int kmin;		/* minimum kerning value */
+static int warn;
 
 static char *macset[];
 
@@ -52,6 +53,17 @@
 	return (w < 0 ? owid(w) - d / 2 : owid(w) + d / 2) / d;
 }
 
+/* report unsupported otf tables */
+static void otf_unsupported(char *sub, int type, int fmt)
+{
+	if (warn) {
+		fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
+		if (fmt > 0)
+			fprintf(stderr, " format %d", fmt);
+		fprintf(stderr, "\n");
+	}
+}
+
 /* find the otf table with the given name */
 static void *otf_table(void *otf, char *name)
 {
@@ -295,6 +307,7 @@
 	return 1;
 }
 
+/* single adjustment positioning */
 static void otf_gpostype1(void *otf, void *sub, char *feat)
 {
 	int fmt = U16(sub, 0);
@@ -321,13 +334,14 @@
 	}
 }
 
+/* pair adjustment positioning */
 static void otf_gpostype2(void *otf, void *sub, char *feat)
 {
 	int fmt = U16(sub, 0);
-	int vfmt1 = U16(sub, 4);
-	int vfmt2 = U16(sub, 6);
+	int vfmt1 = U16(sub, 4);	/* valuerecord 1 */
+	int vfmt2 = U16(sub, 6);	/* valuerecord 2 */
 	int fmtoff1, fmtoff2;
-	int vrlen;		/* valuerecord1 and valuerecord2 length */
+	int vrlen;			/* the length of vfmt1 and vfmt2 */
 	int i, j, k, l;
 	vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
 	if (fmt == 1) {
@@ -397,6 +411,7 @@
 	}
 }
 
+/* cursive attachment positioning */
 static void otf_gpostype3(void *otf, void *sub, char *feat)
 {
 	int fmt = U16(sub, 0);
@@ -424,6 +439,7 @@
 	}
 }
 
+/* parse the given gpos feature table */
 static void otf_gposfeatrec(void *otf, void *gpos, void *featrec)
 {
 	void *feats = gpos + U16(gpos, 6);
@@ -441,16 +457,24 @@
 		ntabs = U16(lookup, 4);
 		for (j = 0; j < ntabs; j++) {
 			tab = lookup + U16(lookup, 6 + 2 * j);
-			if (type == 1)
+			switch (type) {
+			case 1:
 				otf_gpostype1(otf, tab, tag);
-			if (type == 2)
+				break;
+			case 2:
 				otf_gpostype2(otf, tab, tag);
-			if (type == 3)
+				break;
+			case 3:
 				otf_gpostype3(otf, tab, tag);
+				break;
+			default:
+				otf_unsupported("GPOS", type, 0);
+			}
 		}
 	}
 }
 
+/* parse the given gpos language table and its feature tables */
 static void otf_gposlang(void *otf, void *gpos, void *lang)
 {
 	void *feats = gpos + U16(gpos, 6);
@@ -544,6 +568,7 @@
 			printf(" %c%s", !j ? '=' : '|', glyph_name[ctx->l[i][j]]);
 }
 
+/* single substitution */
 static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
 {
 	int cov[NGLYPHS];
@@ -575,6 +600,7 @@
 	}
 }
 
+/* alternate substitution */
 static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
 {
 	int cov[NGLYPHS];
@@ -598,6 +624,7 @@
 	}
 }
 
+/* ligature substitution */
 static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
 {
 	int fmt = U16(sub, 0);
@@ -625,6 +652,7 @@
 	}
 }
 
+/* chaining contextual substitution */
 static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
 {
 	struct gctx ctx = {{NULL}};
@@ -634,8 +662,10 @@
 	int gbank_pos = 0;
 	int n, i, j, nsub;
 	int off = 2;
-	if (fmt != 3)
+	if (fmt != 3) {
+		otf_unsupported("GSUB", 6, fmt);
 		return;
+	}
 	ctx.bn = U16(sub, off);
 	for (i = 0; i < ctx.bn; i++) {
 		n = coverage(sub + U16(sub, off + 2 + 2 * i), gbank + gbank_pos);
@@ -679,6 +709,7 @@
 	}
 }
 
+/* parse the given gsub feature table */
 static void otf_gsubfeatrec(void *otf, void *gsub, void *featrec)
 {
 	void *feats = gsub + U16(gsub, 6);
@@ -696,18 +727,27 @@
 		int ntabs = U16(lookup, 4);
 		for (j = 0; j < ntabs; j++) {
 			void *tab = lookup + U16(lookup, 6 + 2 * j);
-			if (type == 1)
+			switch (type) {
+			case 1:
 				otf_gsubtype1(otf, tab, tag, NULL);
-			if (type == 3)
+				break;
+			case 3:
 				otf_gsubtype3(otf, tab, tag, NULL);
-			if (type == 4)
+				break;
+			case 4:
 				otf_gsubtype4(otf, tab, tag, NULL);
-			if (type == 6)
+				break;
+			case 6:
 				otf_gsubtype6(otf, tab, tag, gsub);
+				break;
+			default:
+				otf_unsupported("GSUB", type, 0);
+			}
 		}
 	}
 }
 
+/* parse the given gsub language table and its feature tables */
 static void otf_gsublang(void *otf, void *gsub, void *lang)
 {
 	void *feats = gsub + U16(gsub, 6);
@@ -789,10 +829,11 @@
 	return 0;
 }
 
-void otf_feat(int r, int k)
+void otf_feat(int r, int k, int w)
 {
 	res = r;
 	kmin = k;
+	warn = w;
 	if (otf_table(buf, "GSUB"))
 		otf_gsub(buf, otf_table(buf, "GSUB"));
 	if (otf_table(buf, "GPOS"))