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;