ref: 9b3d87ae4231c4b57dbeec1c128127694c5a4c8d
parent: e1f6ca9d954bfd68207e929f1f9832d2383e219e
author: Ali Gholami Rudi <[email protected]>
date: Sun May 20 19:28:22 EDT 2018
otf: version 3.0 post tables
--- a/otf.c
+++ b/otf.c
@@ -10,7 +10,7 @@
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define LEN(a) (sizeof(a) / sizeof((a)[0]))
-#define NGLYPHS (1 << 14)
+#define NGLYPHS (1 << 16)
#define NLOOKUPS (1 << 12)
#define GNLEN (64)
#define NGRPS 2048
@@ -38,6 +38,7 @@
static int res; /* device resolution */
static int kmin; /* minimum kerning value */
static int warn; /* report unsupported tables */
+static int noname; /* post table version 3.0; no PS names*/
static char *macset[];
static char *stdset[];
@@ -160,6 +161,8 @@
int i;
post2 = post + 32;
glyph_n = U16(post2, 0);
+ if (U32(post, 0) == 0x30000)
+ noname = 1;
if (U32(post, 0) != 0x20000)
return;
index = post2 + 2;
@@ -235,16 +238,17 @@
}
}
-static int coverage(void *cov, int *out)
+static int *coverage(void *cov, int *ncov)
{
int fmt = U16(cov, 0);
int n = U16(cov, 2);
int beg, end;
- int ncov = 0;
int i, j;
+ int *out = malloc(glyph_n * sizeof(*out));
+ int cnt = 0;
if (fmt == 1) {
for (i = 0; i < n; i++)
- out[ncov++] = U16(cov, 4 + 2 * i);
+ out[cnt++] = U16(cov, 4 + 2 * i);
}
if (fmt == 2) {
for (i = 0; i < n; i++) {
@@ -251,10 +255,12 @@
beg = U16(cov, 4 + 6 * i);
end = U16(cov, 4 + 6 * i + 2);
for (j = beg; j <= end; j++)
- out[ncov++] = j;
+ out[cnt++] = j;
}
}
- return ncov;
+ if (ncov)
+ *ncov = cnt;
+ return out;
}
static int classdef(void *tab, int *gl, int *cls)
@@ -294,14 +300,17 @@
static int ggrp_class(int *src, int *cls, int nsrc, int id)
{
- int g[NGLYPHS];
+ int *g = malloc(nsrc * sizeof(g[0]));
int n = 0;
int i;
+ int grp;
for (i = 0; i < nsrc; i++)
if (cls[i] == id)
g[n++] = src[i];
qsort(g, n, sizeof(g[0]), (void *) intcmp);
- return ggrp_make(g, n);
+ grp = ggrp_make(g, n);
+ free(g);
+ return grp;
}
static int ggrp_coverage(int *g, int n)
@@ -354,11 +363,11 @@
{
int fmt = U16(sub, 0);
int vfmt = U16(sub, 4);
- int cov[NGLYPHS];
+ int *cov;
int ncov, nvals;
int vlen = valuerecord_len(vfmt);
int i;
- ncov = coverage(sub + U16(sub, 2), cov);
+ cov = coverage(sub + U16(sub, 2), &ncov);
if (fmt == 1) {
for (i = 0; i < ncov; i++) {
if (valuerecord_small(vfmt, sub + 6))
@@ -378,6 +387,7 @@
printf("\n");
}
}
+ free(cov);
}
/* pair adjustment positioning */
@@ -391,9 +401,8 @@
int i, j;
vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
if (fmt == 1) {
- int cov[NGLYPHS];
int nc1 = U16(sub, 8);
- coverage(sub + U16(sub, 2), cov);
+ int *cov = coverage(sub + U16(sub, 2), NULL);
for (i = 0; i < nc1; i++) {
void *c2 = sub + U16(sub, 10 + 2 * i);
int nc2 = U16(c2, 0);
@@ -412,11 +421,12 @@
printf("\n");
}
}
+ free(cov);
}
if (fmt == 2) {
- int gl1[NGLYPHS], gl2[NGLYPHS];
- int cls1[NGLYPHS], cls2[NGLYPHS];
- int grp1[NGLYPHS], grp2[NGLYPHS];
+ static int gl1[NGLYPHS], gl2[NGLYPHS];
+ static int cls1[NGLYPHS], cls2[NGLYPHS];
+ static int grp1[NGLYPHS], grp2[NGLYPHS];
int ngl1 = classdef(sub + U16(sub, 8), gl1, cls1);
int ngl2 = classdef(sub + U16(sub, 10), gl2, cls2);
int ncls1 = U16(sub, 12);
@@ -447,17 +457,17 @@
static void otf_gpostype3(void *otf, void *sub, char *feat)
{
int fmt = U16(sub, 0);
- int cov[NGLYPHS];
- int icov[NGLYPHS];
- int ocov[NGLYPHS];
+ int *cov, *icov, *ocov;
int i, n;
int icnt = 0;
int ocnt = 0;
int igrp, ogrp;
- coverage(sub + U16(sub, 2), cov);
if (fmt != 1)
return;
+ cov = coverage(sub + U16(sub, 2), NULL);
n = U16(sub, 4);
+ icov = malloc(n * sizeof(icov[0]));
+ ocov = malloc(n * sizeof(ocov[0]));
for (i = 0; i < n; i++)
if (U16(sub, 6 + 4 * i))
ocov[ocnt++] = cov[i];
@@ -466,6 +476,8 @@
icov[icnt++] = cov[i];
igrp = ggrp_coverage(icov, icnt);
ogrp = ggrp_coverage(ocov, ocnt);
+ free(icov);
+ free(ocov);
for (i = 0; i < n; i++) {
int prev = U16(sub, 6 + 4 * i);
int next = U16(sub, 6 + 4 * i + 2);
@@ -490,6 +502,7 @@
0, 0, dx, dy);
}
}
+ free(cov);
}
/* mark-to-base attachment positioning */
@@ -496,8 +509,8 @@
static void otf_gpostype4(void *otf, void *sub, char *feat)
{
int fmt = U16(sub, 0);
- int mcov[NGLYPHS]; /* mark coverage */
- int bcov[NGLYPHS]; /* base coverage */
+ int *mcov; /* mark coverage */
+ int *bcov; /* base coverage */
int cgrp[1024]; /* glyph groups assigned to classes */
int bgrp; /* the group assigned to base glyphs */
int mcnt; /* mark coverage size */
@@ -508,19 +521,20 @@
int i, j;
if (fmt != 1)
return;
- mcnt = coverage(sub + U16(sub, 2), mcov);
- bcnt = coverage(sub + U16(sub, 4), bcov);
+ mcov = coverage(sub + U16(sub, 2), &mcnt);
+ bcov = coverage(sub + U16(sub, 4), &bcnt);
ccnt = U16(sub, 6);
marks = sub + U16(sub, 8);
bases = sub + U16(sub, 10);
bgrp = ggrp_coverage(bcov, bcnt);
for (i = 0; i < ccnt; i++) {
- int grp[NGLYPHS];
+ int *grp = malloc(mcnt * sizeof(grp[0]));
int cnt = 0;
for (j = 0; j < mcnt; j++)
if (U16(marks, 2 + 4 * j) == i)
grp[cnt++] = mcov[j];
cgrp[i] = ggrp_coverage(grp, cnt);
+ free(grp);
}
for (i = 0; i < mcnt; i++) {
void *mark = marks + U16(marks, 2 + 4 * i + 2); /* mark anchor */
@@ -546,6 +560,8 @@
feat, glyph_name[bcov[i]], cgrp[j], dx, dy, 0, 0);
}
}
+ free(mcov);
+ free(bcov);
}
/* gsub context */
@@ -587,13 +603,15 @@
/* single substitution */
static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
{
- int cov[NGLYPHS];
+ int *cov;
int fmt = U16(sub, 0);
int ncov;
int i;
- ncov = coverage(sub + U16(sub, 2), cov);
+ cov = coverage(sub + U16(sub, 2), &ncov);
if (fmt == 1) {
for (i = 0; i < ncov; i++) {
+ if (cov[i] + S16(sub, 4) >= glyph_n)
+ continue;
printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
gctx_backtrack(ctx);
printf(" -%s +%s", glyph_name[cov[i]],
@@ -613,17 +631,18 @@
printf("\n");
}
}
+ free(cov);
}
/* alternate substitution */
static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
{
- int cov[NGLYPHS];
+ int *cov;
int fmt = U16(sub, 0);
int n, i, j;
if (fmt != 1)
return;
- coverage(sub + U16(sub, 2), cov);
+ cov = coverage(sub + U16(sub, 2), NULL);
n = U16(sub, 4);
for (i = 0; i < n; i++) {
void *alt = sub + U16(sub, 6 + 2 * i);
@@ -637,6 +656,7 @@
printf("\n");
}
}
+ free(cov);
}
/* ligature substitution */
@@ -643,11 +663,11 @@
static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
{
int fmt = U16(sub, 0);
- int cov[NGLYPHS];
+ int *cov;
int n, i, j, k;
if (fmt != 1)
return;
- coverage(sub + U16(sub, 2), cov);
+ cov = coverage(sub + U16(sub, 2), NULL);
n = U16(sub, 4);
for (i = 0; i < n; i++) {
void *set = sub + U16(sub, 6 + 2 * i);
@@ -665,6 +685,7 @@
printf("\n");
}
}
+ free(cov);
}
/* chaining contextual substitution */
@@ -673,7 +694,7 @@
struct gctx ctx = {{0}};
void *lookups = gsub + U16(gsub, 8);
int fmt = U16(sub, 0);
- int cov[NGLYPHS];
+ int *cov;
int i, j, nsub, ncov;
int off = 2;
if (fmt != 3) {
@@ -682,20 +703,23 @@
}
ctx.bn = U16(sub, off);
for (i = 0; i < ctx.bn; i++) {
- ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
+ cov = coverage(sub + U16(sub, off + 2 + 2 * i), &ncov);
ctx.bgrp[i] = ggrp_coverage(cov, ncov);
+ free(cov);
}
off += 2 + 2 * ctx.bn;
ctx.in = U16(sub, off);
for (i = 0; i < ctx.in; i++) {
- ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
+ cov = coverage(sub + U16(sub, off + 2 + 2 * i), &ncov);
ctx.igrp[i] = ggrp_coverage(cov, ncov);
+ free(cov);
}
off += 2 + 2 * ctx.in;
ctx.ln = U16(sub, off);
for (i = 0; i < ctx.ln; i ++) {
- ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
+ cov = coverage(sub + U16(sub, off + 2 + 2 * i), &ncov);
ctx.lgrp[i] = ggrp_coverage(cov, ncov);
+ free(cov);
}
off += 2 + 2 * ctx.ln;
nsub = U16(sub, off); /* nsub > 1 is not supported */
@@ -1020,7 +1044,7 @@
void *topidx; /* top dict index */
void *stridx; /* string idx */
void *chridx; /* charstrings index */
- void *charset; /* charset offset of top dict table */
+ void *charset; /* charset offset */
int bbox[4] = {0};
int i, j;
if (U8(cff, 0) != 1)
@@ -1036,12 +1060,12 @@
cffidx_len(topidx, 0), 15, NULL);
glyph_n = cffidx_cnt(chridx);
strcpy(glyph_name[0], ".notdef");
- if (U8(charset, 0) == 0) {
+ if (!noname && U8(charset, 0) == 0) {
for (i = 0; i < glyph_n; i++)
cff_char(stridx, U16(charset, 1 + i * 2),
glyph_name[i + 1]);
}
- if (U8(charset, 0) == 1 || U8(charset, 0) == 2) {
+ if (!noname && (U8(charset, 0) == 1 || U8(charset, 0) == 2)) {
int g = 1;
int sz = U8(charset, 0) == 1 ? 3 : 4;
for (i = 0; g < glyph_n; i++) {
@@ -1084,6 +1108,10 @@
otf_glyf(otf_buf, otf_table(otf_buf, "glyf"));
if (otf_table(otf_buf, "CFF "))
otf_cff(otf_buf, otf_table(otf_buf, "CFF "));
+ if (noname) {
+ for (i = 1; i < glyph_n; i++)
+ sprintf(glyph_name[i], "uni%04X", glyph_code[i]);
+ }
otf_hmtx(otf_buf, otf_table(otf_buf, "hmtx"));
for (i = 0; i < glyph_n; i++) {
trfn_char(glyph_name[i], -1,