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"))