ref: 1e3f9a4ab59afc89e620de3318a76df796d59b4f
parent: 70a9d7e1756ad571871fa815b3f84a9d7392035b
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Aug 5 05:31:16 EDT 2014
otf: chaining contextual substitution format 3
--- a/otf.c
+++ b/otf.c
@@ -22,6 +22,7 @@
#define CMAPLEN 4 /* cmap header length */
#define CMAPRECLEN 8 /* cmap record length */
#define CMAP4LEN 8 /* format 4 cmap subtable header length */
+#define GCTXLEN 16 /* number of context backtrack coverage arrays */
typedef unsigned int u32;
typedef unsigned short u16;
@@ -294,7 +295,7 @@
return 1;
}
-static void otf_gpostype1(void *otf, char *feat, char *sub)
+static void otf_gpostype1(void *otf, void *sub, char *feat)
{
int fmt = U16(sub, 0);
int vfmt = U16(sub, 4);
@@ -320,7 +321,7 @@
}
}
-static void otf_gpostype2(void *otf, char *feat, char *sub)
+static void otf_gpostype2(void *otf, void *sub, char *feat)
{
int fmt = U16(sub, 0);
int vfmt1 = U16(sub, 4);
@@ -396,7 +397,7 @@
}
}
-static void otf_gpostype3(void *otf, char *feat, char *sub)
+static void otf_gpostype3(void *otf, void *sub, char *feat)
{
int fmt = U16(sub, 0);
int cov[NGLYPHS];
@@ -441,11 +442,11 @@
for (j = 0; j < ntabs; j++) {
tab = lookup + U16(lookup, 6 + 2 * j);
if (type == 1)
- otf_gpostype1(otf, tag, tab);
+ otf_gpostype1(otf, tab, tag);
if (type == 2)
- otf_gpostype2(otf, tag, tab);
+ otf_gpostype2(otf, tab, tag);
if (type == 3)
- otf_gpostype3(otf, tag, tab);
+ otf_gpostype3(otf, tab, tag);
}
}
}
@@ -492,8 +493,59 @@
}
}
-static void otf_gsubtype1(void *otf, char *feat, char *sub)
+/* gsub context */
+struct gctx {
+ int *b[GCTXLEN], blen[GCTXLEN]; /* backtrack coverage arrays */
+ int *i[GCTXLEN], ilen[GCTXLEN]; /* input coverage arrays */
+ int *l[GCTXLEN], llen[GCTXLEN]; /* lookahead coverage arrays*/
+ int bn, in, ln; /* size of b[], i[], l[] */
+ int seqidx; /* sequence index */
+};
+
+static int gctx_len(struct gctx *ctx, int patlen)
{
+ int i, n = 0;
+ if (!ctx)
+ return 0;
+ for (i = 0; i < ctx->bn; i++)
+ n += ctx->blen[i];
+ for (i = 0; i < ctx->seqidx; i++)
+ n += ctx->ilen[i];
+ for (i = ctx->seqidx + patlen; i < ctx->in; i++)
+ n += ctx->ilen[i];
+ for (i = 0; i < ctx->ln; i++)
+ n += ctx->llen[i];
+ return n;
+}
+
+static void gctx_backtrack(struct gctx *ctx)
+{
+ int i, j;
+ if (!ctx)
+ return;
+ for (i = 0; i < ctx->bn; i++)
+ for (j = 0; j < ctx->blen[i]; j++)
+ printf(" %c%s", !j ? '=' : '|', glyph_name[ctx->b[i][j]]);
+ for (i = 0; i < ctx->seqidx; i++)
+ for (j = 0; j < ctx->ilen[i]; j++)
+ printf(" %c%s", !j ? '=' : '|', glyph_name[ctx->i[i][j]]);
+}
+
+static void gctx_lookahead(struct gctx *ctx, int patlen)
+{
+ int i, j;
+ if (!ctx)
+ return;
+ for (i = ctx->seqidx + patlen; i < ctx->in; i++)
+ for (j = 0; j < ctx->ilen[i]; j++)
+ printf(" %c%s", !j ? '=' : '|', glyph_name[ctx->i[i][j]]);
+ for (i = 0; i < ctx->ln; i++)
+ for (j = 0; j < ctx->llen[i]; j++)
+ printf(" %c%s", !j ? '=' : '|', glyph_name[ctx->l[i][j]]);
+}
+
+static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
+{
int cov[NGLYPHS];
int fmt = U16(sub, 0);
int ncov;
@@ -501,21 +553,29 @@
int i;
ncov = coverage(sub + U16(sub, 2), cov);
if (fmt == 1) {
- for (i = 0; i < ncov; i++)
- printf("gsub %s 2 -%s +%s\n",
- feat, glyph_name[cov[i]],
+ for (i = 0; i < ncov; i++) {
+ printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
+ gctx_backtrack(ctx);
+ printf(" -%s +%s", glyph_name[cov[i]],
glyph_name[cov[i] + S16(sub, 4)]);
+ gctx_lookahead(ctx, 1);
+ printf("\n");
+ }
}
if (fmt == 2) {
n = U16(sub, 4);
- for (i = 0; i < n; i++)
- printf("gsub %s 2 -%s +%s\n",
- feat, glyph_name[cov[i]],
+ for (i = 0; i < n; i++) {
+ printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
+ gctx_backtrack(ctx);
+ printf(" -%s +%s", glyph_name[cov[i]],
glyph_name[U16(sub, 6 + 2 * i)]);
+ gctx_lookahead(ctx, 1);
+ printf("\n");
+ }
}
}
-static void otf_gsubtype3(void *otf, char *feat, char *sub)
+static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
{
int cov[NGLYPHS];
int fmt = U16(sub, 0);
@@ -527,14 +587,18 @@
for (i = 0; i < n; i++) {
void *alt = sub + U16(sub, 6 + 2 * i);
int nalt = U16(alt, 0);
- for (j = 0; j < nalt; j++)
- printf("gsub %s 2 -%s +%s\n",
- feat, glyph_name[cov[i]],
+ for (j = 0; j < nalt; j++) {
+ printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
+ gctx_backtrack(ctx);
+ printf(" -%s +%s", glyph_name[cov[i]],
glyph_name[U16(alt, 2 + 2 * j)]);
+ gctx_lookahead(ctx, 1);
+ printf("\n");
+ }
}
}
-static void otf_gsubtype4(void *otf, char *feat, char *sub)
+static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
{
int fmt = U16(sub, 0);
int cov[NGLYPHS];
@@ -549,21 +613,78 @@
for (j = 0; j < nset; j++) {
void *lig = set + U16(set, 2 + 2 * j);
int nlig = U16(lig, 2);
- printf("gsub %s %d -%s",
- feat, nlig + 1, glyph_name[cov[i]]);
+ printf("gsub %s %d", feat, nlig + 1 + gctx_len(ctx, nlig));
+ gctx_backtrack(ctx);
+ printf(" -%s", glyph_name[cov[i]]);
for (k = 0; k < nlig - 1; k++)
printf(" -%s", glyph_name[U16(lig, 4 + 2 * k)]);
- printf(" +%s\n", glyph_name[U16(lig, 0)]);
+ printf(" +%s", glyph_name[U16(lig, 0)]);
+ gctx_lookahead(ctx, nlig);
+ printf("\n");
}
}
}
+static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
+{
+ struct gctx ctx = {{NULL}};
+ void *lookups = gsub + U16(gsub, 8);
+ int fmt = U16(sub, 0);
+ int gbank[NGLYPHS];
+ int gbank_pos = 0;
+ int n, i, j, nsub;
+ int off = 2;
+ if (fmt != 3)
+ 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);
+ ctx.b[i] = gbank + gbank_pos;
+ ctx.blen[i] = n;
+ gbank_pos += n;
+ }
+ off += 2 + 2 * ctx.bn;
+ ctx.in = U16(sub, off);
+ for (i = 0; i < ctx.in; i ++) {
+ n = coverage(sub + U16(sub, off + 2 + 2 * i), gbank + gbank_pos);
+ ctx.i[i] = gbank + gbank_pos;
+ ctx.ilen[i] = n;
+ gbank_pos += n;
+ }
+ off += 2 + 2 * ctx.in;
+ ctx.ln = U16(sub, off);
+ for (i = 0; i < ctx.ln; i ++) {
+ n = coverage(sub + U16(sub, off + 2 + 2 * i), gbank + gbank_pos);
+ ctx.l[i] = gbank + gbank_pos;
+ ctx.llen[i] = n;
+ gbank_pos += n;
+ }
+ off += 2 + 2 * ctx.ln;
+ nsub = U16(sub, off); /* nsub > 1 is not supported */
+ for (i = 0; i < nsub && i < 1; i++) {
+ int lidx = U16(sub, off + 2 + 4 * i + 2);
+ void *lookup = lookups + U16(lookups, 2 + 2 * lidx);
+ int type = U16(lookup, 0);
+ int ntabs = U16(lookup, 4);
+ ctx.seqidx = U16(sub, off + 2 + 4 * i);
+ for (j = 0; j < ntabs; j++) {
+ void *tab = lookup + U16(lookup, 6 + 2 * j);
+ if (type == 1)
+ otf_gsubtype1(otf, tab, feat, &ctx);
+ if (type == 3)
+ otf_gsubtype3(otf, tab, feat, &ctx);
+ if (type == 4)
+ otf_gsubtype4(otf, tab, feat, &ctx);
+ }
+ }
+}
+
static void otf_gsubfeatrec(void *otf, void *gsub, void *featrec)
{
void *feats = gsub + U16(gsub, 6);
void *lookups = gsub + U16(gsub, 8);
- void *feat, *lookup, *tab;
- int nlookups, type, ntabs;
+ void *feat;
+ int nlookups;
char tag[8] = "";
int i, j;
memcpy(tag, featrec, 4);
@@ -570,17 +691,19 @@
feat = feats + U16(featrec, 4);
nlookups = U16(feat, 2);
for (i = 0; i < nlookups; i++) {
- lookup = lookups + U16(lookups, 2 + 2 * U16(feat, 4 + 2 * i));
- type = U16(lookup, 0);
- ntabs = U16(lookup, 4);
+ void *lookup = lookups + U16(lookups, 2 + 2 * U16(feat, 4 + 2 * i));
+ int type = U16(lookup, 0);
+ int ntabs = U16(lookup, 4);
for (j = 0; j < ntabs; j++) {
- tab = lookup + U16(lookup, 6 + 2 * j);
+ void *tab = lookup + U16(lookup, 6 + 2 * j);
if (type == 1)
- otf_gsubtype1(otf, tag, tab);
+ otf_gsubtype1(otf, tab, tag, NULL);
if (type == 3)
- otf_gsubtype3(otf, tag, tab);
+ otf_gsubtype3(otf, tab, tag, NULL);
if (type == 4)
- otf_gsubtype4(otf, tag, tab);
+ otf_gsubtype4(otf, tab, tag, NULL);
+ if (type == 6)
+ otf_gsubtype6(otf, tab, tag, gsub);
}
}
}