ref: a100cd99db8f71ec9d1caeb4d16b65f1f7d0a693
dir: /plan9/otf.c/
#line 1 "otf.c.in"
/* this file is generated. do not modify. */
#include "otfsys.h"
#include "otf.h"
#include "otfpriv.h"
#define f2dot14(o) (f = b[2*o]<<8 | b[2*o+1], (f>>14)+(f&((1<<14)-1))/16384.0)
int indentΔ = 2;
#define rchr(s) (be ? ((s)[0]<<8 | (s)[1]) : ((s)[1]<<8 | (s)[0]))
static u8int mark[] = {0x00, 0x00, 0xc0, 0xe0, 0xf0};
static int
utf16to8(u8int *o, int osz, u8int *s, int sz)
{
u32int c, c2;
int i, wr, j, be;
i = 0;
be = 1;
if(s[0] == 0xfe && s[1] == 0xff)
i += 2;
else if(s[0] == 0xff && s[1] == 0xfe){
be = 0;
i += 2;
}
for(; i < sz-1 && osz > 1;){
c = rchr(&s[i]);
i += 2;
if(c >= 0xd800 && c <= 0xdbff && i < sz-1){
c2 = rchr(&s[i]);
if(c2 >= 0xdc00 && c2 <= 0xdfff){
c = 0x10000 | (c - 0xd800)<<10 | (c2 - 0xdc00);
i += 2;
}else
return -1;
}else if(c >= 0xdc00 && c <= 0xdfff)
return -1;
if(c < 0x80)
wr = 1;
else if(c < 0x800)
wr = 2;
else if(c < 0x10000)
wr = 3;
else
wr = 4;
osz -= wr;
if(osz < 1)
break;
o += wr;
for(j = wr; j > 1; j--){
*(--o) = (c & 0xbf) | 0x80;
c >>= 6;
}
*(--o) = (u8int)c | mark[wr];
o += wr;
}
*o = 0;
return i;
}
static char *
strtoutf8(Otf *o, u8int *in, int sz)
{
char *s;
// FIXME this is not sufficient, obviously - need more platform/encoding handling
if(o->platformID == 0 || (o->platformID == 3 && o->encodingID == 1)){
s = malloc(sz/2+1);
utf16to8((u8int*)s, sz/2+1, in, sz);
}else{
s = malloc(sz+1);
memcpy(s, in, sz);
s[sz] = 0;
}
return s;
}
Otf *
otfopen(Otfile *f)
{
Otf *o;
if((o = calloc(1, sizeof(*o))) == nil){
werrstr("no memory");
}else{
o->f = f;
if(read_TableDirectory(o, &o->td) != 0){
free(o);
o = nil;
}
}
return o;
}
void
otfprint(Otf *o, Otfile *out, int indent)
{
print_TableDirectory(out, indent, o, &o->td);
}
void
otfclose(Otf *o)
{
if(o == nil)
return;
// FIXME traverse and free everything
free(o);
}
static int
otfpushrange(Otf *o, int off, int len)
{
Range *r;
int x;
r = nil;
if(o->r != nil){
if(len < 0)
len = o->r->len - off;
if(len < 0 || off+len > o->r->len){
werrstr("range overflow (len %d) by %d bytes", len, off+len - o->r->len);
goto err;
}
off += o->r->start;
}else if(len < 0){
len = 0x7fffffff;
}
if((r = malloc(sizeof(*r))) == nil){
werrstr("no memory");
goto err;
}
r->par = o->r;
r->start = off;
r->len = len;
r->prevoff = o->off;
if((x = o->f->seek(o->f->aux, off, 0)) != off){
werrstr("seek offset: need %d, got %d", off, x);
goto err;
}
o->off = off;
o->r = r;
return 0;
err:
free(r);
return -1;
}
static int
otfpoprange(Otf *o)
{
Range *r;
int x;
r = o->r;
if(r == nil){
werrstr("pop without push");
goto err;
}
if((x = o->f->seek(o->f->aux, r->prevoff, 0)) != r->prevoff){
werrstr("seek offset: need %d, got %d", r->prevoff, x);
goto err;
}
o->off = r->prevoff;
o->r = r->par;
free(r);
return 0;
err:
return -1;
}
static void
otfpopranges(Otf *o)
{
while(o->r != nil)
otfpoprange(o);
}
static u8int *
otfreadn(Otf *o, int n)
{
Range *r;
u8int *b;
int x;
r = o->r;
if(r != nil && o->off+n > r->start+r->len){
werrstr("need %d at %d, have %d at %d", n, o->off, r->len, r->start);
goto err;
}
if(n > o->bufsz){
if((b = realloc(o->buf, n)) == nil){
werrstr("no memory");
goto err;
}
o->buf = b;
o->bufsz = n;
}
if((x = o->f->read(o->f->aux, o->buf, n)) != n){
werrstr("need %d, got %d; off %d", n, x, o->off);
goto err;
}
o->off += n;
return o->buf;
err:
return nil;
}
static int
otfarray(Otf *o, void **arr_, void *fun_, int elsz, int num)
{
int i;
int (*fun)(Otf*, void*);
u8int *arr;
if((arr = calloc(num, elsz)) == nil){
werrstr("no memory");
goto err;
}
fun = fun_;
for(i = 0; i < num; i++){
if(fun(o, arr + i*elsz) < 0)
goto err;
}
*arr_ = arr;
return 0;
err:
free(arr);
return -1;
}
enum {
CGLYPH_FL_WORD_ARGS = 1<<0,
CGLYPH_FL_SCALE = 1<<3,
CGLYPH_FL_OVERLAP_COMPOUND = 1<<10,
CGLYPH_FL_UNSCALED_COMPONENT_OFFSET = 1<<12,
};
static int
read_ComponentGlyph(Otf *o, ComponentGlyph **out, int instr)
{
ComponentGlyph *v;
u8int *b;
s16int f;
if((v = calloc(1, sizeof(*v))) == nil){
nomem:
werrstr("no memory");
goto err;
}
if((b = otfreadn(o, 2*2)) == nil)
goto err;
v->flags = (b[0]<<8 | b[1]) & ~CGLYPH_FL_OVERLAP_COMPOUND;
v->glyphIndex = b[2]<<8 | b[3];
instr |= v->flags & CGLYPH_FL_INSTRUCTIONS;
if(v->flags & CGLYPH_FL_UNSCALED_COMPONENT_OFFSET)
v->flags &= ~(CGLYPH_FL_UNSCALED_COMPONENT_OFFSET | CGLYPH_FL_SCALED_COMPONENT_OFFSET);
if((v->flags & CGLYPH_FL_WORD_ARGS) != 0 && (b = otfreadn(o, 2*2)) != nil){
if(v->flags & CGLYPH_FL_SIGNED_XY){
v->arg1 = (s16int)(b[0]<<8 | b[1]);
v->arg2 = (s16int)(b[2]<<8 | b[3]);
}else{
v->arg1 = b[0]<<8 | b[1];
v->arg1 = b[2]<<8 | b[3];
}
}else if((b = otfreadn(o, 2)) != nil){
if(v->flags & CGLYPH_FL_SIGNED_XY){
v->arg1 = (s8int)b[0];
v->arg2 = (s8int)b[1];
}else{
v->arg1 = b[0];
v->arg2 = b[1];
}
}
if(b == nil)
goto err;
v->scaleX = 1.0;
v->scaleY = 1.0;
if((v->flags & CGLYPH_FL_SCALE) != 0 && (b = otfreadn(o, 2)) != nil){
v->scaleX = f2dot14(0);
v->scaleY = v->scaleX;
v->flags &= ~CGLYPH_FL_SCALE;
v->flags |= CGLYPH_FL_SCALE_XY;
}else if((v->flags & CGLYPH_FL_SCALE_XY) != 0 && (b = otfreadn(o, 2*2)) != nil){
v->scaleX = f2dot14(0);
v->scaleY = f2dot14(1);
}else if((v->flags & CGLYPH_FL_2X2_TRANSFORM) != 0 && (b = otfreadn(o, 2*2*2)) != nil){
v->scaleX = f2dot14(0);
v->scale01 = f2dot14(1);
v->scale10 = f2dot14(2);
v->scaleY = f2dot14(3);
}
if(b == nil)
goto err;
if((v->flags & CGLYPH_FL_MORE_COMPONENTS) != 0){
if(read_ComponentGlyph(o, &v->next, instr) != 0){
free(v);
return -1;
}
}else if(instr != 0){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->numInstr = b[0]<<8 | b[1];
if((v->instr = malloc(v->numInstr)) == nil)
goto nomem;
if(v->numInstr > 0 && (b = otfreadn(o, v->numInstr)) == nil)
goto err;
memcpy(v->instr, b, v->numInstr);
}
*out = v;
return 0;
err:
if(v != nil)
free(v->instr);
free(v);
werrstr("ComponentGlyph: %r");
return -1;
}
void
print_ComponentGlyph(Otfile *f, int indent, Otf *o, ComponentGlyph *v)
{
void *a = f->aux;
f->print(a, "%*s%s: %#"PRIx16"%s%s%s%s%s%s%s%s%s%s\n", indent, "", "flags", v->flags,
(v->flags&CGLYPH_FL_SIGNED_XY)?" CGLYPH_FL_SIGNED_XY":"",
(v->flags&CGLYPH_FL_ROUND_TO_GRID_XY)?" CGLYPH_FL_ROUND_TO_GRID_XY":"",
(v->flags&CGLYPH_FL_SCALE)?" CGLYPH_FL_SCALE":"",
(v->flags&CGLYPH_FL_MORE_COMPONENTS)?" CGLYPH_FL_MORE_COMPONENTS":"",
(v->flags&CGLYPH_FL_SCALE_XY)?" CGLYPH_FL_SCALE_XY":"",
(v->flags&CGLYPH_FL_2X2_TRANSFORM)?" CGLYPH_FL_2X2_TRANSFORM":"",
(v->flags&CGLYPH_FL_INSTRUCTIONS)?" CGLYPH_FL_INSTRUCTIONS":"",
(v->flags&CGLYPH_FL_METRICS)?" CGLYPH_FL_METRICS":"",
(v->flags&CGLYPH_FL_OVERLAP_COMPOUND)?" CGLYPH_FL_OVERLAP_COMPOUND":"",
(v->flags&CGLYPH_FL_SCALED_COMPONENT_OFFSET)?" CGLYPH_FL_SCALED_COMPONENT_OFFSET":""
);
f->print(a, "%*s%s: %"PRIu16"\n", indent, "", "glyphIndex", v->glyphIndex);
if(v->arg1 != 0 || v->arg2 != 0){
f->print(f->aux, "%*s%s: %d\n", indent, "", "arg1", v->arg1);
f->print(f->aux, "%*s%s: %d\n", indent, "", "arg2", v->arg2);
}
if(v->flags & CGLYPH_FL_SCALE_XY){
f->print(a, "%*s%s: %g\n", indent, "", "scaleX", v->scaleX);
f->print(a, "%*s%s: %g\n", indent, "", "scaleY", v->scaleY);
}else if(v->flags & CGLYPH_FL_2X2_TRANSFORM){
f->print(a, "%*s%s: %g\n", indent, "", "scaleX", v->scaleX);
f->print(a, "%*s%s: %g\n", indent, "", "scale01", v->scale01);
f->print(a, "%*s%s: %g\n", indent, "", "scale10", v->scale10);
f->print(a, "%*s%s: %g\n", indent, "", "scaleY", v->scaleY);
}
if(v->numInstr > 0 && v->instr != nil){
f->print(a, "%*s%s: %"PRIu16"\n", indent, "", "numInstr", v->numInstr);
f->print(a, "%*s%s:", indent, "", "instr");
for(int i = 0; i < v->numInstr; i++)
f->print(a, " %02"PRIx8, v->instr[i]);
f->print(a, "\n");
}
if(v->next != nil){
f->print(a, "%*s%s:\n", indent, "", "next");
print_ComponentGlyph(f, indent+indentΔ, o, v->next);
}
}
enum {
GLYPH_FL_ON_CURVE_POINT = 1<<0,
GLYPH_FL_X_SHORT_VECTOR = 1<<1,
GLYPH_FL_Y_SHORT_VECTOR = 1<<2,
GLYPH_FL_REPEAT = 1<<3,
GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1<<4,
GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1<<5,
GLYPH_FL_OVERLAP_SIMPLE = 1<<6,
};
static int
read_SimpleGlyph(Otf *o, SimpleGlyph **out)
{
SimpleGlyph *v;
u8int *b, *flags;
int i, n, nflags, c, nc;
flags = nil;
if((v = calloc(1, sizeof(*v))) == nil){
nomem:
werrstr("no memory");
goto err;
}
v->numEndPtsOfContours = o->numberOfContours;
n = o->numberOfContours;
if((b = otfreadn(o, 2*n+2)) == nil)
goto err;
if((v->endPtsOfContours = malloc(2*n)) == nil)
goto nomem;
for(int i = 0; i < n; i++)
v->endPtsOfContours[i] = b[2*i+0]<<8 | b[2*i+1];
v->numPoints = 1 + v->endPtsOfContours[o->numberOfContours-1];
v->instructionLength = b[2*n+0]<<8 | b[2*n+1];
n = v->instructionLength;
if((b = otfreadn(o, n)) == nil)
goto err;
if((v->instructions = malloc(n)) == nil)
goto nomem;
memcpy(v->instructions, b, n);
if((flags = malloc(v->numPoints)) == nil) /* not supposed to be more than that, 64Kb max */
goto nomem;
for(nflags = 0; nflags < v->numPoints;){
if((b = otfreadn(o, 1)) == nil)
goto err;
if((flags[nflags++] = *b) & GLYPH_FL_REPEAT){
flags[nflags-1] ^= GLYPH_FL_REPEAT;
if((b = otfreadn(o, 1)) == nil)
goto err;
if(nflags + *b > v->numPoints){
werrstr("repeat overflow (%d+%d > %d)", nflags, *b, v->numPoints);
goto err;
}
memset(flags+nflags, flags[nflags-1], *b);
nflags += *b;
}
}
if((v->points = calloc(v->numPoints, sizeof(*v->points))) == nil)
goto nomem;
/* flags first */
for(i = n = 0; i < nflags && n < v->numPoints; i++, n++)
v->points[n].onCurve = (flags[i] & GLYPH_FL_ON_CURVE_POINT) != 0;
/* read packed x coordinates */
c = 0;
for(i = n = 0; i < nflags && n < v->numPoints; i++){
if((flags[i] & GLYPH_FL_X_SHORT_VECTOR) != 0){
if((b = otfreadn(o, 1)) == nil)
goto err;
nc = *b;
if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) == 0)
nc = -nc;
c = v->points[n++].x = c + nc;
}else if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) != 0){
v->points[n++].x = c;
}else{
if((b = otfreadn(o, 2)) == nil)
goto err;
c += (s16int)(b[0]<<8 | b[1]);
v->points[n++].x = c;
}
}
/* read packed y coordinates */
c = 0;
for(i = n = 0; i < nflags && n < v->numPoints; i++){
if((flags[i] & GLYPH_FL_Y_SHORT_VECTOR) != 0){
if((b = otfreadn(o, 1)) == nil)
goto err;
nc = *b;
if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) == 0)
nc = -nc;
c = v->points[n++].y = c + nc;
}else if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) != 0){
v->points[n++].y = c;
}else{
if((b = otfreadn(o, 2)) == nil)
goto err;
c += (s16int)(b[0]<<8 | b[1]);
v->points[n++].y = c;
}
}
free(flags);
*out = v;
return 0;
err:
free(flags);
if(v != nil){
free(v->endPtsOfContours);
free(v->instructions);
free(v->points);
}
free(v);
werrstr("SimpleGlyph: %r");
return -1;
}
void
print_SimpleGlyph(Otfile *f, int indent, Otf *o, SimpleGlyph *v)
{
void *a = f->aux;
USED(o);
if(v->numEndPtsOfContours > 0){
f->print(a, "%*s%s:", indent, "", "endPtsOfContours");
for(int i = 0; i < v->numEndPtsOfContours; i++)
f->print(a, " %"PRId16, v->endPtsOfContours[i]);
f->print(a, "\n");
}
if(v->instructionLength > 0){
f->print(a, "%*s%s: %ud\n", indent, "", "instructionLength", v->instructionLength);
f->print(a, "%*s%s:", indent, "", "instructions");
for(int i = 0; i < v->instructionLength; i++)
f->print(a, " %02"PRIx8, v->instructions[i]);
f->print(a, "\n");
}
if(v->numPoints > 0){
f->print(a, "%*s%s: %d\n", indent, "", "numPoints", v->numPoints);
f->print(a, "%*s%s:", indent, "", "points");
for(int i = 0; i < v->numPoints; i++)
f->print(a, " (%d,%d,%s)", v->points[i].x, v->points[i].y, v->points[i].onCurve?"on":"off");
f->print(a, "\n");
}
}
Glyf *
otfglyf(Otf *o, int index)
{
Glyf *g;
int off, len, i;
if((g = calloc(1, sizeof(*g))) == nil){
werrstr("no memory");
goto err;
}
if(o->td.head == nil){
werrstr("no head table");
goto err;
}
if(o->td.loca == nil){
werrstr("no loca table");
goto err;
}
if(o->glyf.offset == 0){
for(i = 0; i < o->td.numTables; i++){
TableRecord *rec = o->td.tableRecords+i;
if(rec->tableTag == (u32int)('g'<<24|'l'<<16|'y'<<8|'f')){
o->glyf = *rec;
break;
}
}
if(o->glyf.offset == 0){
werrstr("no glyf table");
goto err;
}
}
if(index < 0 || index >= o->numGlyphs){
werrstr("index out of range");
goto err;
}
if(o->indexToLocFormat == 0){
off = (int)o->td.loca->shortOffsets[index]*2;
len = (int)o->td.loca->shortOffsets[index+1]*2 - off;
}else{
off = o->td.loca->longOffsets[index];
len = o->td.loca->longOffsets[index+1] - off;
}
if(len < 1) /* no outlines */
return g;
if(otfpushrange(o, o->glyf.offset, o->glyf.length) < 0)
goto err;
if(otfpushrange(o, off, len) < 0)
goto err;
if(read_Glyf(o, g) < 0){
free(g);
g = nil;
}
otfpoprange(o);
otfpoprange(o);
return g;
err:
free(g);
otfpopranges(o);
return nil;
}
int
otfglyfnum(Otf *o)
{
return o->numGlyphs;
}
int
otfrune2glyph(Otf *o, Rune r)
{
RuneMapper *m;
int i, g;
for(i = 0, m = o->td.cmap->mappers; i < o->td.cmap->numMappers; i++, m++){
if((g = m->rune2glyph(m->aux, r)) >= 0)
return g;
}
return -1;
}
Rune
otfglyph2rune(Otf *o, int g)
{
RuneMapper *m;
Rune r;
int i;
for(i = 0, m = o->td.cmap->mappers; i < o->td.cmap->numMappers; i++, m++){
if((r = m->glyph2rune(m->aux, g)) != NoRune)
return r;
}
return NoRune;
}
enum {
PLAT_UNICODE,
PLAT_MACINTOSH, /* "currently discouraged", unsupported */
PLAT_ISO, /* deprecated, unsupported */
PLAT_WINDOWS,
PLAT_CUSTOM, /* deprecated, unsupported */
};
/* supported subtable formats: 4, 6, 10, 12, 13 */
/* FIXME: need to implement (higher to lower prio): 14 */
enum {
ENC_UNICODE_1_0, /* deprecated, unsupported */
ENC_UNICODE_1_1, /* deprecated, unsupported */
ENC_UNICODE_ISO, /* deprecated, unsupported */
ENC_UNICODE_2_0_BMP, /* subtable format 4, 6 */
ENC_UNICODE_2_0_FULL, /* subtable format 10, 12 */
ENC_UNICODE_VAR_SEQ, /* subtable format 14 */
ENC_UNICODE_FULL, /* subtable format 13 (many-to-one) */
ENC_WINDOWS_SYMBOL = 0, /* unsupported */
ENC_WINDOWS_UNICODE_BMP, /* subtable format 4 */
ENC_WINDOWS_SHIFTJIS, /* unsupported */
ENC_WINDOWS_PRC, /* unsupported */
ENC_WINDOWS_BIG5, /* unsupported */
ENC_WINDOWS_WANSUNG, /* unsupported */
ENC_WINDOWS_JOHAB, /* unsupported */
ENC_WINDOWS_UNICODE_FULL = 10, /* subtable format 12 */
};
static int
cmap4rune2glyph(void *aux, Rune r)
{
SubtableCmap4 *sc;
int i, b, e, n, x, segC;
if(r > 0xffff)
return -1;
sc = aux;
segC = sc->segCountX2/2;
for(b = 0, e = segC-1; b <= e; ){
i = (b + e)/2;
if(sc->endCode[i] < r)
b = i + 1;
else if(sc->startCode[i] > r)
e = i - 1;
else if(sc->idRangeOffset[i] == 0){
x = r + sc->idDelta[i];
if(x < 0)
x += 65536;
return x;
}else{
x = i + sc->idRangeOffset[i]/2 + (r - sc->startCode[i]) - segC;
n = (sc->length-((8*2)+(sc->segCountX2*4)))/2;
if(x < 0 || x >= n)
break;
return sc->glyphIdArray[x];
}
}
return -1;
}
static Rune
cmap4glyph2rune(void *aux, int g)
{
USED(aux); USED(g);
/* FIXME - other mapper will hopefully pick up after */
return 'x';
}
static int
cmap6rune2glyph(void *aux, Rune r)
{
SubtableCmap6 *sc;
sc = aux;
if(r >= sc->firstCode){
r -= sc->firstCode;
if(r < sc->entryCount)
return sc->glyphIdArray[r];
}
return -1;
}
static Rune
cmap6glyph2rune(void *aux, int g)
{
SubtableCmap6 *sc;
sc = aux;
if(g >= 0 && g < sc->entryCount)
return (Rune)sc->firstCode + g;
return NoRune;
}
static int
cmap10rune2glyph(void *aux, Rune r)
{
SubtableCmap10 *sc;
sc = aux;
if(r >= sc->startCharCode){
r -= sc->startCharCode;
if(r < sc->numChars)
return sc->glyphIdArray[r];
}
return -1;
}
static Rune
cmap10glyph2rune(void *aux, int g)
{
SubtableCmap10 *sc;
sc = aux;
if(g >= 0 && g < sc->numChars)
return sc->startCharCode + g;
return NoRune;
}
static int
cmap12rune2glyph(void *aux, Rune r)
{
SubtableCmap12or13 *sc;
MapGroup *m;
int b, e, x;
sc = aux;
for(b = 0, e = sc->numGroups-1; b <= e; ){
x = (b + e)/2;
m = sc->groups + x;
if(m->endCharCode < r)
b = x + 1;
else if(m->startCharCode > r)
e = x - 1;
else
return m->startGlyphID + (r - m->startCharCode);
}
return -1;
}
static Rune
cmap12glyph2rune(void *aux, int g)
{
SubtableCmap12or13 *sc;
MapGroup *m;
int i;
sc = aux;
for(i = 0, m = sc->groups; i < sc->numGroups; i++, m++){
if(g >= m->startGlyphID && g <= m->startGlyphID+(m->endCharCode-m->startCharCode))
return m->startCharCode + (g - m->startGlyphID);
}
return NoRune;
}
static int
cmap13rune2glyph(void *aux, Rune r)
{
SubtableCmap12or13 *sc;
MapGroup *m;
int b, e, x;
sc = aux;
for(b = 0, e = sc->numGroups-1; b <= e; ){
x = (b + e)/2;
m = sc->groups + x;
if(m->endCharCode < r)
b = x + 1;
else if(m->startCharCode > r)
e = x - 1;
else
return m->startGlyphID;
}
return -1;
}
static Rune
cmap13glyph2rune(void *aux, int g)
{
SubtableCmap12or13 *sc;
MapGroup *m;
int i;
sc = aux;
for(i = 0, m = sc->groups; i < sc->numGroups; i++, m++){
if(g == m->startGlyphID)
return m->startCharCode;/* this doesn't make sense for constant mapping */
}
return NoRune;
}
static int
otfcmapUnicode(TableCmap *c, EncodingRecord *er, int *parsed, int *unsupported)
{
SubtableCmap *sc;
sc = er->subtable;
switch(er->encodingID){
case ENC_UNICODE_2_0_BMP:
if(sc->format == 4){
c->mappers[c->numMappers].rune2glyph = cmap4rune2glyph;
c->mappers[c->numMappers].glyph2rune = cmap4glyph2rune;
c->mappers[c->numMappers++].aux = &sc->sub4;
(*parsed)++;
break;
}
if(sc->format == 6){
c->mappers[c->numMappers].rune2glyph = cmap6rune2glyph;
c->mappers[c->numMappers].glyph2rune = cmap6glyph2rune;
c->mappers[c->numMappers++].aux = &sc->sub6;
(*parsed)++;
break;
}
(*unsupported)++;
werrstr("2.0 bmp: fmt %d", sc->format);
goto err;
case ENC_UNICODE_2_0_FULL: /* this one is good */
if(sc->format == 10){
if(sc->sub10.numChars < 1){
werrstr("2.0 full: no chars");
goto err;
}
c->mappers[c->numMappers].rune2glyph = cmap10rune2glyph;
c->mappers[c->numMappers].glyph2rune = cmap10glyph2rune;
c->mappers[c->numMappers++].aux = &sc->sub10;
(*parsed)++;
break;
}
if(sc->format == 12){
if(sc->sub12or13.numGroups < 1){
werrstr("2.0 full: no groups");
goto err;
}
c->mappers[c->numMappers].rune2glyph = cmap12rune2glyph;
c->mappers[c->numMappers].glyph2rune = cmap12glyph2rune;
c->mappers[c->numMappers++].aux = &sc->sub12or13;
(*parsed)++;
break;
}
(*unsupported)++;
werrstr("2.0 full: fmt %d", sc->format);
goto err;
case ENC_UNICODE_VAR_SEQ:
/* FIXME */
break;
case ENC_UNICODE_FULL:
if(sc->format == 13){
if(sc->sub12or13.numGroups < 1){
werrstr("full: no groups");
goto err;
}
c->mappers[c->numMappers].rune2glyph = cmap13rune2glyph;
c->mappers[c->numMappers].glyph2rune = cmap13glyph2rune;
c->mappers[c->numMappers++].aux = &sc->sub12or13;
(*parsed)++;
break;
}
(*unsupported)++;
werrstr("full: fmt %d", sc->format);
goto err;
case ENC_UNICODE_1_0:
case ENC_UNICODE_1_1:
case ENC_UNICODE_ISO:
(*unsupported)++;
werrstr("deprecated encoding: %d", er->encodingID);
goto err;
default:
(*unsupported)++;
werrstr("unknown encoding: %d", er->encodingID);
goto err;
}
return 0;
err:
werrstr("unicode: %r");
return -1;
}
static int
otfcmapWindows(TableCmap *c, EncodingRecord *er, int *parsed, int *unsupported)
{
SubtableCmap *sc;
sc = er->subtable;
switch(er->encodingID){
case ENC_WINDOWS_UNICODE_BMP:
if(sc->format == 4){
c->mappers[c->numMappers].rune2glyph = cmap4rune2glyph;
c->mappers[c->numMappers].glyph2rune = cmap4glyph2rune;
c->mappers[c->numMappers++].aux = &sc->sub4;
(*parsed)++;
break;
}
if(sc->format == 6){
c->mappers[c->numMappers].rune2glyph = cmap6rune2glyph;
c->mappers[c->numMappers].glyph2rune = cmap6glyph2rune;
c->mappers[c->numMappers++].aux = &sc->sub6;
(*parsed)++;
break;
}
(*unsupported)++;
werrstr("unicode bmp: fmt %d", sc->format);
goto err;
case ENC_WINDOWS_UNICODE_FULL:
if(sc->format != 12){
(*unsupported)++;
werrstr("unicode full: fmt %d", sc->format);
goto err;
}
if(sc->sub12or13.numGroups < 1){
werrstr("unicode full: no groups");
goto err;
}
c->mappers[c->numMappers].rune2glyph = cmap12rune2glyph;
c->mappers[c->numMappers].glyph2rune = cmap12glyph2rune;
c->mappers[c->numMappers++].aux = &sc->sub12or13;
(*parsed)++;
break;
case ENC_WINDOWS_SYMBOL:
case ENC_WINDOWS_SHIFTJIS:
case ENC_WINDOWS_PRC:
case ENC_WINDOWS_BIG5:
case ENC_WINDOWS_WANSUNG:
case ENC_WINDOWS_JOHAB:
(*unsupported)++;
werrstr("unsupported encoding: %d", er->encodingID);
goto err;
default:
(*unsupported)++;
werrstr("unknown encoding: %d", er->encodingID);
goto err;
}
return 0;
err:
werrstr("windows: %r");
return -1;
}
static int
otfcmap(TableCmap *c)
{
int i, parsed, unsupported;
EncodingRecord *er;
parsed = 0;
unsupported = 0;
for(i = 0, er = c->encodingRecords; i < c->numTables; i++, er++){
if(c->numMappers >= nelem(c->mappers)) /* give up */
break;
switch(er->platformID){
case PLAT_UNICODE:
/* FIXME issue a warning if returned non-zero */
if(otfcmapUnicode(c, er, &parsed, &unsupported) != 0)
goto err;
break;
case PLAT_WINDOWS:
/* FIXME issue a warning if returned non-zero */
if(otfcmapWindows(c, er, &parsed, &unsupported) != 0)
goto err;
break;
case PLAT_MACINTOSH:
case PLAT_ISO:
case PLAT_CUSTOM:
default:
unsupported++;
break;
}
}
if(parsed > 0)
return 0;
if(unsupported > 0)
werrstr(" (%d unsupported)", unsupported);
else
werrstr("");
werrstr("no usable records%r");
/* FIXME - eventually this return should be removed */
return 0;
err:
werrstr("cmap: %r");
return -1;
}
int
read_SubHeader(Otf *o, SubHeader *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->firstCode = b[0]<<8 | b[1];
v->entryCode = b[2]<<8 | b[3];
v->idDelta = b[4]<<8 | b[5];
v->idRangeOffset = b[6]<<8 | b[7];
return 0;
err:
werrstr("%s: %r", "SubHeader");
return -1;
}
void
print_SubHeader(Otfile *f, int indent, Otf *o, SubHeader *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "firstCode", v->firstCode);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "entryCode", v->entryCode);
f->print(f->aux, "%*s%s: %d\n", indent, "", "idDelta", v->idDelta);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "idRangeOffset", v->idRangeOffset);
USED(o);
}
int
read_MapGroup(Otf *o, MapGroup *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 12)) == nil)
goto err;
v->startCharCode = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->endCharCode = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
v->startGlyphID = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11];
return 0;
err:
werrstr("%s: %r", "MapGroup");
return -1;
}
void
print_MapGroup(Otfile *f, int indent, Otf *o, MapGroup *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "startCharCode", v->startCharCode);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "endCharCode", v->endCharCode);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "startGlyphID", v->startGlyphID);
USED(o);
}
int
read_SubtableCmap0(Otf *o, SubtableCmap0 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 260)) == nil)
goto err;
v->length = b[0]<<8 | b[1];
v->language = b[2]<<8 | b[3];
for(int i = 0; i < 256; i++)
v->glyphIdArray[i] = b[4+i*1];
return 0;
err:
werrstr("%s: %r", "SubtableCmap0");
return -1;
}
void
print_SubtableCmap0(Otfile *f, int indent, Otf *o, SubtableCmap0 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "language", v->language);
for(int i = 0; i < 256; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "glyphIdArray", i, v->glyphIdArray[i]);
USED(o);
}
int
read_SubtableCmap2(Otf *o, SubtableCmap2 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->length = b[0]<<8 | b[1];
v->language = b[2]<<8 | b[3];
return 0;
err:
werrstr("%s: %r", "SubtableCmap2");
return -1;
}
void
print_SubtableCmap2(Otfile *f, int indent, Otf *o, SubtableCmap2 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "language", v->language);
USED(o);
}
int
read_SubtableCmap4(Otf *o, SubtableCmap4 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 12)) == nil)
goto err;
v->length = b[0]<<8 | b[1];
v->language = b[2]<<8 | b[3];
v->segCountX2 = b[4]<<8 | b[5];
if(v->segCountX2 <= 0){
werrstr("%s: invalid value: %d (%#ux)", "segCountX2", v->segCountX2, v->segCountX2);
goto err;
}
v->searchRange = b[6]<<8 | b[7];
v->entrySelector = b[8]<<8 | b[9];
v->rangeShift = b[10]<<8 | b[11];
if((b = otfreadn(o, (v->segCountX2/2)*2)) == nil)
goto err;
v->endCode = malloc((v->segCountX2/2)*sizeof(*v->endCode));
for(int i = 0; i < (v->segCountX2/2); i++)
v->endCode[i] = b[0+i*2]<<8 | b[1+i*2];
if((b = otfreadn(o, 2)) == nil)
goto err;
USED(b);
if((b = otfreadn(o, (v->segCountX2/2)*2)) == nil)
goto err;
v->startCode = malloc((v->segCountX2/2)*sizeof(*v->startCode));
for(int i = 0; i < (v->segCountX2/2); i++)
v->startCode[i] = b[0+i*2]<<8 | b[1+i*2];
if((b = otfreadn(o, (v->segCountX2/2)*2)) == nil)
goto err;
v->idDelta = malloc((v->segCountX2/2)*sizeof(*v->idDelta));
for(int i = 0; i < (v->segCountX2/2); i++)
v->idDelta[i] = b[0+i*2]<<8 | b[1+i*2];
if((b = otfreadn(o, (v->segCountX2/2)*2)) == nil)
goto err;
v->idRangeOffset = malloc((v->segCountX2/2)*sizeof(*v->idRangeOffset));
for(int i = 0; i < (v->segCountX2/2); i++)
v->idRangeOffset[i] = b[0+i*2]<<8 | b[1+i*2];
if((b = otfreadn(o, ((v->length-((8*2)+(v->segCountX2*4)))/2)*2)) == nil)
goto err;
v->glyphIdArray = malloc(((v->length-((8*2)+(v->segCountX2*4)))/2)*sizeof(*v->glyphIdArray));
for(int i = 0; i < ((v->length-((8*2)+(v->segCountX2*4)))/2); i++)
v->glyphIdArray[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "SubtableCmap4");
return -1;
}
void
print_SubtableCmap4(Otfile *f, int indent, Otf *o, SubtableCmap4 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "language", v->language);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "segCountX2", v->segCountX2);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "searchRange", v->searchRange);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "entrySelector", v->entrySelector);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "rangeShift", v->rangeShift);
for(int i = 0; i < (v->segCountX2/2); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "endCode", i, v->endCode[i]);
for(int i = 0; i < (v->segCountX2/2); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "startCode", i, v->startCode[i]);
for(int i = 0; i < (v->segCountX2/2); i++)
f->print(f->aux, "%*s%s[%d]: %d\n", indent, "", "idDelta", i, v->idDelta[i]);
for(int i = 0; i < (v->segCountX2/2); i++)
f->print(f->aux, "%*s%s[%d]: %d\n", indent, "", "idRangeOffset", i, v->idRangeOffset[i]);
for(int i = 0; i < ((v->length-((8*2)+(v->segCountX2*4)))/2); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "glyphIdArray", i, v->glyphIdArray[i]);
USED(o);
}
int
read_SubtableCmap6(Otf *o, SubtableCmap6 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->length = b[0]<<8 | b[1];
v->language = b[2]<<8 | b[3];
v->firstCode = b[4]<<8 | b[5];
v->entryCount = b[6]<<8 | b[7];
if((b = otfreadn(o, v->entryCount*2)) == nil)
goto err;
v->glyphIdArray = malloc(v->entryCount*sizeof(*v->glyphIdArray));
for(int i = 0; i < v->entryCount; i++)
v->glyphIdArray[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "SubtableCmap6");
return -1;
}
void
print_SubtableCmap6(Otfile *f, int indent, Otf *o, SubtableCmap6 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "language", v->language);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "firstCode", v->firstCode);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "entryCount", v->entryCount);
for(int i = 0; i < v->entryCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "glyphIdArray", i, v->glyphIdArray[i]);
USED(o);
}
int
read_SubtableCmap8(Otf *o, SubtableCmap8 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8200)) == nil)
goto err;
v->length = b[0]<<8 | b[1];
v->language = b[2]<<8 | b[3];
for(int i = 0; i < 8192; i++)
v->is32[i] = b[4+i*1];
v->numGroups = b[8196]<<24 | b[8197]<<16 | b[8198]<<8 | b[8199];
if(otfarray(o, &v->groups, read_MapGroup, sizeof(MapGroup), v->numGroups) < 0){
werrstr("%s: %r", "groups");
goto err;
}
return 0;
err:
werrstr("%s: %r", "SubtableCmap8");
return -1;
}
void
print_SubtableCmap8(Otfile *f, int indent, Otf *o, SubtableCmap8 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "language", v->language);
for(int i = 0; i < 8192; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "is32", i, v->is32[i]);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numGroups", v->numGroups);
for(int i = 0; i < v->numGroups; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "groups", i);
print_MapGroup(f, indent+indentΔ, o, &v->groups[i]);
}
USED(o);
}
int
read_SubtableCmap10(Otf *o, SubtableCmap10 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 18)) == nil)
goto err;
v->reserved = b[0]<<8 | b[1];
v->length = b[2]<<24 | b[3]<<16 | b[4]<<8 | b[5];
v->language = b[6]<<24 | b[7]<<16 | b[8]<<8 | b[9];
v->startCharCode = b[10]<<24 | b[11]<<16 | b[12]<<8 | b[13];
v->numChars = b[14]<<24 | b[15]<<16 | b[16]<<8 | b[17];
if((b = otfreadn(o, ((v->length-((2*2)+(4*4)))/2)*2)) == nil)
goto err;
v->glyphIdArray = malloc(((v->length-((2*2)+(4*4)))/2)*sizeof(*v->glyphIdArray));
for(int i = 0; i < ((v->length-((2*2)+(4*4)))/2); i++)
v->glyphIdArray[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "SubtableCmap10");
return -1;
}
void
print_SubtableCmap10(Otfile *f, int indent, Otf *o, SubtableCmap10 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "reserved", v->reserved);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "language", v->language);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "startCharCode", v->startCharCode);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numChars", v->numChars);
for(int i = 0; i < ((v->length-((2*2)+(4*4)))/2); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "glyphIdArray", i, v->glyphIdArray[i]);
USED(o);
}
int
read_SubtableCmap12or13(Otf *o, SubtableCmap12or13 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 14)) == nil)
goto err;
v->reserved = b[0]<<8 | b[1];
v->length = b[2]<<24 | b[3]<<16 | b[4]<<8 | b[5];
v->language = b[6]<<24 | b[7]<<16 | b[8]<<8 | b[9];
v->numGroups = b[10]<<24 | b[11]<<16 | b[12]<<8 | b[13];
if(otfarray(o, &v->groups, read_MapGroup, sizeof(MapGroup), v->numGroups) < 0){
werrstr("%s: %r", "groups");
goto err;
}
return 0;
err:
werrstr("%s: %r", "SubtableCmap12or13");
return -1;
}
void
print_SubtableCmap12or13(Otfile *f, int indent, Otf *o, SubtableCmap12or13 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "reserved", v->reserved);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "language", v->language);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numGroups", v->numGroups);
for(int i = 0; i < v->numGroups; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "groups", i);
print_MapGroup(f, indent+indentΔ, o, &v->groups[i]);
}
USED(o);
}
int
read_UnicodeRange(Otf *o, UnicodeRange *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->startUnicodeValue = b[0]<<16 | b[1]<<8 | b[2];
v->additionalCount = b[3];
return 0;
err:
werrstr("%s: %r", "UnicodeRange");
return -1;
}
void
print_UnicodeRange(Otfile *f, int indent, Otf *o, UnicodeRange *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "startUnicodeValue", v->startUnicodeValue);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "additionalCount", v->additionalCount);
USED(o);
}
int
read_DefaultUVS(Otf *o, DefaultUVS *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->numUnicodeValueRanges = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(otfarray(o, &v->ranges, read_UnicodeRange, sizeof(UnicodeRange), v->numUnicodeValueRanges) < 0){
werrstr("%s: %r", "ranges");
goto err;
}
return 0;
err:
werrstr("%s: %r", "DefaultUVS");
return -1;
}
void
print_DefaultUVS(Otfile *f, int indent, Otf *o, DefaultUVS *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numUnicodeValueRanges", v->numUnicodeValueRanges);
for(int i = 0; i < v->numUnicodeValueRanges; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "ranges", i);
print_UnicodeRange(f, indent+indentΔ, o, &v->ranges[i]);
}
USED(o);
}
int
read_UVSMapping(Otf *o, UVSMapping *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 5)) == nil)
goto err;
v->unicodeValue = b[0]<<16 | b[1]<<8 | b[2];
v->glyphID = b[3]<<8 | b[4];
return 0;
err:
werrstr("%s: %r", "UVSMapping");
return -1;
}
void
print_UVSMapping(Otfile *f, int indent, Otf *o, UVSMapping *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "unicodeValue", v->unicodeValue);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID);
USED(o);
}
int
read_NonDefaultUVS(Otf *o, NonDefaultUVS *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->numUVSMappings = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(otfarray(o, &v->uvsMappings, read_UVSMapping, sizeof(UVSMapping), v->numUVSMappings) < 0){
werrstr("%s: %r", "uvsMappings");
goto err;
}
return 0;
err:
werrstr("%s: %r", "NonDefaultUVS");
return -1;
}
void
print_NonDefaultUVS(Otfile *f, int indent, Otf *o, NonDefaultUVS *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numUVSMappings", v->numUVSMappings);
for(int i = 0; i < v->numUVSMappings; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "uvsMappings", i);
print_UVSMapping(f, indent+indentΔ, o, &v->uvsMappings[i]);
}
USED(o);
}
int
read_VariationSelector(Otf *o, VariationSelector *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 11)) == nil)
goto err;
v->varSelector = b[0]<<16 | b[1]<<8 | b[2];
v->defaultUVSOffset = b[3]<<24 | b[4]<<16 | b[5]<<8 | b[6];
v->nonDefaultUVSOffset = b[7]<<24 | b[8]<<16 | b[9]<<8 | b[10];
if(v->defaultUVSOffset != 0){
if(otfpushrange(o, v->defaultUVSOffset, -1) < 0)
goto err;
v->defaultUVS = calloc(1, sizeof(*v->defaultUVS));
if(read_DefaultUVS(o, v->defaultUVS) < 0){
werrstr("%s: %r", "defaultUVS");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->nonDefaultUVSOffset != 0){
if(otfpushrange(o, v->nonDefaultUVSOffset, -1) < 0)
goto err;
v->nonDefaultUVS = calloc(1, sizeof(*v->nonDefaultUVS));
if(read_NonDefaultUVS(o, v->nonDefaultUVS) < 0){
werrstr("%s: %r", "nonDefaultUVS");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "VariationSelector");
return -1;
}
void
print_VariationSelector(Otfile *f, int indent, Otf *o, VariationSelector *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "varSelector", v->varSelector);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "defaultUVSOffset", v->defaultUVSOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "nonDefaultUVSOffset", v->nonDefaultUVSOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "defaultUVS");
if(v->defaultUVS != nil)
print_DefaultUVS(f, indent+indentΔ, o, v->defaultUVS);
f->print(f->aux, "%*s%s:\n", indent, "", "nonDefaultUVS");
if(v->nonDefaultUVS != nil)
print_NonDefaultUVS(f, indent+indentΔ, o, v->nonDefaultUVS);
USED(o);
}
int
read_SubtableCmap14(Otf *o, SubtableCmap14 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->length = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->numVarSelectorRecords = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
if(otfarray(o, &v->varSelector, read_VariationSelector, sizeof(VariationSelector), v->numVarSelectorRecords) < 0){
werrstr("%s: %r", "varSelector");
goto err;
}
return 0;
err:
werrstr("%s: %r", "SubtableCmap14");
return -1;
}
void
print_SubtableCmap14(Otfile *f, int indent, Otf *o, SubtableCmap14 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numVarSelectorRecords", v->numVarSelectorRecords);
for(int i = 0; i < v->numVarSelectorRecords; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "varSelector", i);
print_VariationSelector(f, indent+indentΔ, o, &v->varSelector[i]);
}
USED(o);
}
int
read_SubtableCmap(Otf *o, SubtableCmap *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->format = b[0]<<8 | b[1];
if(v->format != 0 && v->format != 2 && v->format != 4 && v->format != 6 && v->format != 8 && v->format != 10 && v->format != 12 && v->format != 13 && v->format != 14){
werrstr("%s: invalid value: %d (%#ux)", "format", v->format, v->format);
goto err;
}
if(v->format == 0){
if(read_SubtableCmap0(o, &v->sub0) < 0){
werrstr("%s: %r", "sub0");
goto err;
}
}
if(v->format == 2){
if(read_SubtableCmap2(o, &v->sub2) < 0){
werrstr("%s: %r", "sub2");
goto err;
}
}
if(v->format == 4){
if(read_SubtableCmap4(o, &v->sub4) < 0){
werrstr("%s: %r", "sub4");
goto err;
}
}
if(v->format == 6){
if(read_SubtableCmap6(o, &v->sub6) < 0){
werrstr("%s: %r", "sub6");
goto err;
}
}
if(v->format == 8){
if(read_SubtableCmap8(o, &v->sub8) < 0){
werrstr("%s: %r", "sub8");
goto err;
}
}
if(v->format == 10){
if(read_SubtableCmap10(o, &v->sub10) < 0){
werrstr("%s: %r", "sub10");
goto err;
}
}
if(v->format == 12 || v->format == 13){
if(read_SubtableCmap12or13(o, &v->sub12or13) < 0){
werrstr("%s: %r", "sub12or13");
goto err;
}
}
if(v->format == 14){
if(read_SubtableCmap14(o, &v->sub14) < 0){
werrstr("%s: %r", "sub14");
goto err;
}
}
return 0;
err:
werrstr("%s: %r", "SubtableCmap");
return -1;
}
void
print_SubtableCmap(Otfile *f, int indent, Otf *o, SubtableCmap *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "format", v->format);
if(v->format == 0){
f->print(f->aux, "%*s%s:\n", indent, "", "sub0");
print_SubtableCmap0(f, indent+indentΔ, o, &v->sub0);
}
if(v->format == 2){
f->print(f->aux, "%*s%s:\n", indent, "", "sub2");
print_SubtableCmap2(f, indent+indentΔ, o, &v->sub2);
}
if(v->format == 4){
f->print(f->aux, "%*s%s:\n", indent, "", "sub4");
print_SubtableCmap4(f, indent+indentΔ, o, &v->sub4);
}
if(v->format == 6){
f->print(f->aux, "%*s%s:\n", indent, "", "sub6");
print_SubtableCmap6(f, indent+indentΔ, o, &v->sub6);
}
if(v->format == 8){
f->print(f->aux, "%*s%s:\n", indent, "", "sub8");
print_SubtableCmap8(f, indent+indentΔ, o, &v->sub8);
}
if(v->format == 10){
f->print(f->aux, "%*s%s:\n", indent, "", "sub10");
print_SubtableCmap10(f, indent+indentΔ, o, &v->sub10);
}
if(v->format == 12 || v->format == 13){
f->print(f->aux, "%*s%s:\n", indent, "", "sub12or13");
print_SubtableCmap12or13(f, indent+indentΔ, o, &v->sub12or13);
}
if(v->format == 14){
f->print(f->aux, "%*s%s:\n", indent, "", "sub14");
print_SubtableCmap14(f, indent+indentΔ, o, &v->sub14);
}
USED(o);
}
int
read_EncodingRecord(Otf *o, EncodingRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->platformID = b[0]<<8 | b[1];
if(v->platformID > 4){
werrstr("%s: invalid value: %d (%#ux)", "platformID", v->platformID, v->platformID);
goto err;
}
v->encodingID = b[2]<<8 | b[3];
v->subtableOffset = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
if(v->subtableOffset != 0){
if(otfpushrange(o, v->subtableOffset, -1) < 0)
goto err;
v->subtable = calloc(1, sizeof(*v->subtable));
if(read_SubtableCmap(o, v->subtable) < 0){
werrstr("%s: %r", "subtable");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "EncodingRecord");
return -1;
}
void
print_EncodingRecord(Otfile *f, int indent, Otf *o, EncodingRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "platformID", v->platformID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "encodingID", v->encodingID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "subtableOffset", v->subtableOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "subtable");
if(v->subtable != nil)
print_SubtableCmap(f, indent+indentΔ, o, v->subtable);
USED(o);
}
int
read_TableCmap(Otf *o, TableCmap *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
u16int version = b[0]<<8 | b[1];
if(version != 0){
werrstr("%s: invalid value: %d (%#ux)", "version", version, version);
goto err;
}
v->numTables = b[2]<<8 | b[3];
if(otfarray(o, &v->encodingRecords, read_EncodingRecord, sizeof(EncodingRecord), v->numTables) < 0){
werrstr("%s: %r", "encodingRecords");
goto err;
}
if(otfcmap(v) < 0)
goto err;
return 0;
err:
werrstr("%s: %r", "TableCmap");
return -1;
}
void
print_TableCmap(Otfile *f, int indent, Otf *o, TableCmap *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numTables", v->numTables);
for(int i = 0; i < v->numTables; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "encodingRecords", i);
print_EncodingRecord(f, indent+indentΔ, o, &v->encodingRecords[i]);
}
USED(o);
}
int
read_TableHead(Otf *o, TableHead *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 54)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
u16int minorVersion = b[2]<<8 | b[3];
if(minorVersion != 0){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", minorVersion, minorVersion);
goto err;
}
u32int magicNumber = b[12]<<24 | b[13]<<16 | b[14]<<8 | b[15];
if(magicNumber != 0x5f0f3cf5){
werrstr("%s: invalid value: %d (%#ux)", "magicNumber", magicNumber, magicNumber);
goto err;
}
v->flags = b[16]<<8 | b[17];
v->unitsPerEm = b[18]<<8 | b[19];
if(v->unitsPerEm < 16 || v->unitsPerEm > 16384){
werrstr("%s: invalid value: %d (%#ux)", "unitsPerEm", v->unitsPerEm, v->unitsPerEm);
goto err;
}
v->created = ((s64int)b[20]<<56 | (s64int)b[21]<<48 | (s64int)b[22]<<40 | (s64int)b[23]<<32 | b[24]<<24 | b[25]<<16 | b[26]<<8 | b[27]) - 2082844800LL;
v->modified = ((s64int)b[28]<<56 | (s64int)b[29]<<48 | (s64int)b[30]<<40 | (s64int)b[31]<<32 | b[32]<<24 | b[33]<<16 | b[34]<<8 | b[35]) - 2082844800LL;
v->xMin = b[36]<<8 | b[37];
v->yMin = b[38]<<8 | b[39];
v->xMax = b[40]<<8 | b[41];
v->yMax = b[42]<<8 | b[43];
v->macStyle = b[44]<<8 | b[45];
v->lowestRecPPEM = b[46]<<8 | b[47];
s16int fontDirectionHint = b[48]<<8 | b[49];
if(fontDirectionHint < -2 || fontDirectionHint > 2){
werrstr("%s: invalid value: %d (%#ux)", "fontDirectionHint", fontDirectionHint, fontDirectionHint);
goto err;
}
v->indexToLocFormat = b[50]<<8 | b[51];
o->indexToLocFormat = v->indexToLocFormat;
if(v->indexToLocFormat > 1){
werrstr("%s: invalid value: %d (%#ux)", "indexToLocFormat", v->indexToLocFormat, v->indexToLocFormat);
goto err;
}
s16int glyphDataFormat = b[52]<<8 | b[53];
if(glyphDataFormat != 0){
werrstr("%s: invalid value: %d (%#ux)", "glyphDataFormat", glyphDataFormat, glyphDataFormat);
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableHead");
return -1;
}
void
print_TableHead(Otfile *f, int indent, Otf *o, TableHead *v)
{
f->print(f->aux, "%*s%s: %#ux%s%s%s%s%s%s%s%s%s\n", indent, "", "flags", v->flags, (v->flags&HEAD_FL_BASELINE_Y_0)?" HEAD_FL_BASELINE_Y_0":"", (v->flags&HEAD_FL_LEFT_SIDEBEARING_X_0)?" HEAD_FL_LEFT_SIDEBEARING_X_0":"", (v->flags&HEAD_FL_INSTR_DEP_POINT_SZ)?" HEAD_FL_INSTR_DEP_POINT_SZ":"", (v->flags&HEAD_FL_FORCE_PPEM_INT)?" HEAD_FL_FORCE_PPEM_INT":"", (v->flags&HEAD_FL_INSTR_ALT_ADVANCE_WIDTH)?" HEAD_FL_INSTR_ALT_ADVANCE_WIDTH":"", (v->flags&HEAD_FL_LOSSLESS)?" HEAD_FL_LOSSLESS":"", (v->flags&HEAD_FL_CONVERTED)?" HEAD_FL_CONVERTED":"", (v->flags&HEAD_FL_CLEARTYPE)?" HEAD_FL_CLEARTYPE":"", (v->flags&HEAD_FL_LAST_RESORT)?" HEAD_FL_LAST_RESORT":"");
f->print(f->aux, "%*s%s: %ud\n", indent, "", "unitsPerEm", v->unitsPerEm);
f->print(f->aux, "%*s%s: %τ\n", indent, "", "created", fmttime(v->created));
f->print(f->aux, "%*s%s: %τ\n", indent, "", "modified", fmttime(v->modified));
f->print(f->aux, "%*s%s: %d\n", indent, "", "xMin", v->xMin);
f->print(f->aux, "%*s%s: %d\n", indent, "", "yMin", v->yMin);
f->print(f->aux, "%*s%s: %d\n", indent, "", "xMax", v->xMax);
f->print(f->aux, "%*s%s: %d\n", indent, "", "yMax", v->yMax);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "macStyle", v->macStyle);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lowestRecPPEM", v->lowestRecPPEM);
f->print(f->aux, "%*s%s: %d\n", indent, "", "indexToLocFormat", v->indexToLocFormat);
USED(o);
}
int
read_TableHhea(Otf *o, TableHhea *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 36)) == nil)
goto err;
v->majorVersion = b[0]<<8 | b[1];
if(v->majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", v->majorVersion, v->majorVersion);
goto err;
}
v->minorVersion = b[2]<<8 | b[3];
if(v->minorVersion != 0){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", v->minorVersion, v->minorVersion);
goto err;
}
v->ascender = b[4]<<8 | b[5];
v->descender = b[6]<<8 | b[7];
v->lineGap = b[8]<<8 | b[9];
v->advanceWidthMax = b[10]<<8 | b[11];
v->minLeftSideBearing = b[12]<<8 | b[13];
v->minRightSideBearing = b[14]<<8 | b[15];
v->xMaxExtent = b[16]<<8 | b[17];
v->caretSlopeRise = b[18]<<8 | b[19];
v->caretSlopeRun = b[20]<<8 | b[21];
v->caretOffset = b[22]<<8 | b[23];
v->metricDataFormat = b[32]<<8 | b[33];
if(v->metricDataFormat != 0){
werrstr("%s: invalid value: %d (%#ux)", "metricDataFormat", v->metricDataFormat, v->metricDataFormat);
goto err;
}
v->numberOfHMetrics = b[34]<<8 | b[35];
o->numberOfHMetrics = v->numberOfHMetrics;
return 0;
err:
werrstr("%s: %r", "TableHhea");
return -1;
}
void
print_TableHhea(Otfile *f, int indent, Otf *o, TableHhea *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "majorVersion", v->majorVersion);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion);
f->print(f->aux, "%*s%s: %d\n", indent, "", "ascender", v->ascender);
f->print(f->aux, "%*s%s: %d\n", indent, "", "descender", v->descender);
f->print(f->aux, "%*s%s: %d\n", indent, "", "lineGap", v->lineGap);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "advanceWidthMax", v->advanceWidthMax);
f->print(f->aux, "%*s%s: %d\n", indent, "", "minLeftSideBearing", v->minLeftSideBearing);
f->print(f->aux, "%*s%s: %d\n", indent, "", "minRightSideBearing", v->minRightSideBearing);
f->print(f->aux, "%*s%s: %d\n", indent, "", "xMaxExtent", v->xMaxExtent);
f->print(f->aux, "%*s%s: %d\n", indent, "", "caretSlopeRise", v->caretSlopeRise);
f->print(f->aux, "%*s%s: %d\n", indent, "", "caretSlopeRun", v->caretSlopeRun);
f->print(f->aux, "%*s%s: %d\n", indent, "", "caretOffset", v->caretOffset);
f->print(f->aux, "%*s%s: %d\n", indent, "", "metricDataFormat", v->metricDataFormat);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numberOfHMetrics", v->numberOfHMetrics);
USED(o);
}
int
read_Glyf(Otf *o, Glyf *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 10)) == nil)
goto err;
v->numberOfContours = b[0]<<8 | b[1];
o->numberOfContours = v->numberOfContours;
v->xMin = b[2]<<8 | b[3];
v->yMin = b[4]<<8 | b[5];
v->xMax = b[6]<<8 | b[7];
v->yMax = b[8]<<8 | b[9];
if(v->numberOfContours < 0 && read_ComponentGlyph(o, &v->component, 0) < 0)
goto err;
if(v->numberOfContours > 0 && read_SimpleGlyph(o, &v->simple) < 0)
goto err;
return 0;
err:
werrstr("%s: %r", "Glyf");
return -1;
}
void
print_Glyf(Otfile *f, int indent, Otf *o, Glyf *v)
{
f->print(f->aux, "%*s%s: %d\n", indent, "", "numberOfContours", v->numberOfContours);
f->print(f->aux, "%*s%s: %d\n", indent, "", "xMin", v->xMin);
f->print(f->aux, "%*s%s: %d\n", indent, "", "yMin", v->yMin);
f->print(f->aux, "%*s%s: %d\n", indent, "", "xMax", v->xMax);
f->print(f->aux, "%*s%s: %d\n", indent, "", "yMax", v->yMax);
if(v->component != nil){
f->print(f->aux, "%*s%s:\n", indent, "", "component");
print_ComponentGlyph(f, indent+indentΔ, o, v->component);
}else if(v->simple != nil){
f->print(f->aux, "%*s%s:\n", indent, "", "simple");
print_SimpleGlyph(f, indent+indentΔ, o, v->simple);
}
USED(o);
}
int
read_LongHorMetric(Otf *o, LongHorMetric *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->advanceWidth = b[0]<<8 | b[1];
v->lsb = b[2]<<8 | b[3];
return 0;
err:
werrstr("%s: %r", "LongHorMetric");
return -1;
}
void
print_LongHorMetric(Otfile *f, int indent, Otf *o, LongHorMetric *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "advanceWidth", v->advanceWidth);
f->print(f->aux, "%*s%s: %d\n", indent, "", "lsb", v->lsb);
USED(o);
}
int
read_TableMaxp(Otf *o, TableMaxp *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
u32int version = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(version != 20480 && version != 0x10000){
werrstr("%s: invalid value: %d (%#ux)", "version", version, version);
goto err;
}
v->numGlyphs = b[4]<<8 | b[5];
o->numGlyphs = v->numGlyphs;
return 0;
err:
werrstr("%s: %r", "TableMaxp");
return -1;
}
void
print_TableMaxp(Otfile *f, int indent, Otf *o, TableMaxp *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numGlyphs", v->numGlyphs);
USED(o);
}
int
read_TableHmtx(Otf *o, TableHmtx *v)
{
u8int *b = nil; USED(b);
if(otfarray(o, &v->hMetrics, read_LongHorMetric, sizeof(LongHorMetric), o->numberOfHMetrics) < 0){
werrstr("%s: %r", "hMetrics");
goto err;
}
if((b = otfreadn(o, (o->numGlyphs-o->numberOfHMetrics)*2)) == nil)
goto err;
v->leftSideBearings = malloc((o->numGlyphs-o->numberOfHMetrics)*sizeof(*v->leftSideBearings));
for(int i = 0; i < (o->numGlyphs-o->numberOfHMetrics); i++)
v->leftSideBearings[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "TableHmtx");
return -1;
}
void
print_TableHmtx(Otfile *f, int indent, Otf *o, TableHmtx *v)
{
for(int i = 0; i < o->numberOfHMetrics; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "hMetrics", i);
print_LongHorMetric(f, indent+indentΔ, o, &v->hMetrics[i]);
}
for(int i = 0; i < (o->numGlyphs-o->numberOfHMetrics); i++)
f->print(f->aux, "%*s%s[%d]: %d\n", indent, "", "leftSideBearings", i, v->leftSideBearings[i]);
USED(o);
}
int
read_TablePost(Otf *o, TablePost *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 16)) == nil)
goto err;
u32int version = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(version != 0x10000 && version != 0x20000 && version != 0x25000 && version != 0x30000){
werrstr("%s: invalid value: %d (%#ux)", "version", version, version);
goto err;
}
v->italicAngle = (b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7])/65536.0f;
v->underlinePosition = b[8]<<8 | b[9];
v->underlineThickness = b[10]<<8 | b[11];
v->isFixedPitch = b[12]<<24 | b[13]<<16 | b[14]<<8 | b[15];
return 0;
err:
werrstr("%s: %r", "TablePost");
return -1;
}
void
print_TablePost(Otfile *f, int indent, Otf *o, TablePost *v)
{
f->print(f->aux, "%*s%s: %g\n", indent, "", "italicAngle", v->italicAngle);
f->print(f->aux, "%*s%s: %d\n", indent, "", "underlinePosition", v->underlinePosition);
f->print(f->aux, "%*s%s: %d\n", indent, "", "underlineThickness", v->underlineThickness);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "isFixedPitch", v->isFixedPitch);
USED(o);
}
int
read_NameRecord(Otf *o, NameRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 12)) == nil)
goto err;
v->platformID = b[0]<<8 | b[1];
o->platformID = v->platformID;
v->encodingID = b[2]<<8 | b[3];
o->encodingID = v->encodingID;
v->languageID = b[4]<<8 | b[5];
v->nameID = b[6]<<8 | b[7];
v->stringLength = b[8]<<8 | b[9];
v->stringOffset = b[10]<<8 | b[11];
if((o->storageOffset+v->stringOffset) != 0){
if(otfpushrange(o, (o->storageOffset+v->stringOffset), -1) < 0)
goto err;
if((b = otfreadn(o, v->stringLength)) == nil)
goto err;
v->string = strtoutf8(o, b, v->stringLength);
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "NameRecord");
return -1;
}
void
print_NameRecord(Otfile *f, int indent, Otf *o, NameRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "platformID", v->platformID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "encodingID", v->encodingID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "languageID", v->languageID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "nameID", v->nameID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "stringLength", v->stringLength);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "stringOffset", v->stringOffset);
f->print(f->aux, "%*s%s: %s\n", indent, "", "string", v->string);
USED(o);
}
int
read_LangTagRecord(Otf *o, LangTagRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->length = b[0]<<8 | b[1];
v->langTagOffset = b[2]<<8 | b[3];
if((o->storageOffset+v->langTagOffset) != 0){
if(otfpushrange(o, (o->storageOffset+v->langTagOffset), -1) < 0)
goto err;
if((b = otfreadn(o, v->length)) == nil)
goto err;
v->langTag = malloc(v->length/2+1);
utf16to8((u8int*)v->langTag, v->length/2+1, b, v->length);
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "LangTagRecord");
return -1;
}
void
print_LangTagRecord(Otfile *f, int indent, Otf *o, LangTagRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "langTagOffset", v->langTagOffset);
f->print(f->aux, "%*s%s: %s\n", indent, "", "langTag", v->langTag);
USED(o);
}
int
read_TableName(Otf *o, TableName *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->version = b[0]<<8 | b[1];
if(v->version != 0 && v->version != 1){
werrstr("%s: invalid value: %d (%#ux)", "version", v->version, v->version);
goto err;
}
v->count = b[2]<<8 | b[3];
v->storageOffset = b[4]<<8 | b[5];
o->storageOffset = v->storageOffset;
if(otfarray(o, &v->nameRecord, read_NameRecord, sizeof(NameRecord), v->count) < 0){
werrstr("%s: %r", "nameRecord");
goto err;
}
if(v->version >= 1){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->langTagCount = b[0]<<8 | b[1];
}
if(v->version >= 1){
if(otfarray(o, &v->langTagRecord, read_LangTagRecord, sizeof(LangTagRecord), v->langTagCount) < 0){
werrstr("%s: %r", "langTagRecord");
goto err;
}
}
return 0;
err:
werrstr("%s: %r", "TableName");
return -1;
}
void
print_TableName(Otfile *f, int indent, Otf *o, TableName *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "version", v->version);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "count", v->count);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "storageOffset", v->storageOffset);
for(int i = 0; i < v->count; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "nameRecord", i);
print_NameRecord(f, indent+indentΔ, o, &v->nameRecord[i]);
}
if(v->version >= 1)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "langTagCount", v->langTagCount);
if(v->version >= 1){
for(int i = 0; i < v->langTagCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "langTagRecord", i);
print_LangTagRecord(f, indent+indentΔ, o, &v->langTagRecord[i]);
}
}
USED(o);
}
int
read_BigGlyphMetrics(Otf *o, BigGlyphMetrics *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->height = b[0];
v->width = b[1];
v->horiBearingX = b[2];
v->horiBearingY = b[3];
v->horiAdvance = b[4];
v->vertBearingX = b[5];
v->vertBearingY = b[6];
v->vertAdvance = b[7];
return 0;
err:
werrstr("%s: %r", "BigGlyphMetrics");
return -1;
}
void
print_BigGlyphMetrics(Otfile *f, int indent, Otf *o, BigGlyphMetrics *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "height", v->height);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "width", v->width);
f->print(f->aux, "%*s%s: %d\n", indent, "", "horiBearingX", v->horiBearingX);
f->print(f->aux, "%*s%s: %d\n", indent, "", "horiBearingY", v->horiBearingY);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "horiAdvance", v->horiAdvance);
f->print(f->aux, "%*s%s: %d\n", indent, "", "vertBearingX", v->vertBearingX);
f->print(f->aux, "%*s%s: %d\n", indent, "", "vertBearingY", v->vertBearingY);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "vertAdvance", v->vertAdvance);
USED(o);
}
int
read_SmallGlyphMetrics(Otf *o, SmallGlyphMetrics *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 5)) == nil)
goto err;
v->height = b[0];
v->width = b[1];
v->bearingX = b[2];
v->bearingY = b[3];
v->advance = b[4];
return 0;
err:
werrstr("%s: %r", "SmallGlyphMetrics");
return -1;
}
void
print_SmallGlyphMetrics(Otfile *f, int indent, Otf *o, SmallGlyphMetrics *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "height", v->height);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "width", v->width);
f->print(f->aux, "%*s%s: %d\n", indent, "", "bearingX", v->bearingX);
f->print(f->aux, "%*s%s: %d\n", indent, "", "bearingY", v->bearingY);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "advance", v->advance);
USED(o);
}
int
read_SbitLineMetrics(Otf *o, SbitLineMetrics *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 12)) == nil)
goto err;
v->ascender = b[0];
v->descender = b[1];
v->widthMax = b[2];
v->caretSlopeNumerator = b[3];
v->caretSlopeDenumerator = b[4];
v->caretOffset = b[5];
v->minOriginSB = b[6];
v->minAdvanceSB = b[7];
v->maxBeforeBL = b[8];
v->minAfterBL = b[9];
return 0;
err:
werrstr("%s: %r", "SbitLineMetrics");
return -1;
}
void
print_SbitLineMetrics(Otfile *f, int indent, Otf *o, SbitLineMetrics *v)
{
f->print(f->aux, "%*s%s: %d\n", indent, "", "ascender", v->ascender);
f->print(f->aux, "%*s%s: %d\n", indent, "", "descender", v->descender);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "widthMax", v->widthMax);
f->print(f->aux, "%*s%s: %d\n", indent, "", "caretSlopeNumerator", v->caretSlopeNumerator);
f->print(f->aux, "%*s%s: %d\n", indent, "", "caretSlopeDenumerator", v->caretSlopeDenumerator);
f->print(f->aux, "%*s%s: %d\n", indent, "", "caretOffset", v->caretOffset);
f->print(f->aux, "%*s%s: %d\n", indent, "", "minOriginSB", v->minOriginSB);
f->print(f->aux, "%*s%s: %d\n", indent, "", "minAdvanceSB", v->minAdvanceSB);
f->print(f->aux, "%*s%s: %d\n", indent, "", "maxBeforeBL", v->maxBeforeBL);
f->print(f->aux, "%*s%s: %d\n", indent, "", "minAfterBL", v->minAfterBL);
USED(o);
}
int
read_IndexSubtable1(Otf *o, IndexSubtable1 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, ((o->lastGlyphIndex-o->firstGlyphIndex)+2)*4)) == nil)
goto err;
v->sbitOffsets = malloc(((o->lastGlyphIndex-o->firstGlyphIndex)+2)*sizeof(*v->sbitOffsets));
for(int i = 0; i < ((o->lastGlyphIndex-o->firstGlyphIndex)+2); i++)
v->sbitOffsets[i] = b[0+i*4]<<24 | b[1+i*4]<<16 | b[2+i*4]<<8 | b[3+i*4];
return 0;
err:
werrstr("%s: %r", "IndexSubtable1");
return -1;
}
void
print_IndexSubtable1(Otfile *f, int indent, Otf *o, IndexSubtable1 *v)
{
for(int i = 0; i < ((o->lastGlyphIndex-o->firstGlyphIndex)+2); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "sbitOffsets", i, v->sbitOffsets[i]);
USED(o);
}
int
read_IndexSubtable2(Otf *o, IndexSubtable2 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->imageSize = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(read_BigGlyphMetrics(o, &v->bigMetrics) < 0){
werrstr("%s: %r", "bigMetrics");
goto err;
}
return 0;
err:
werrstr("%s: %r", "IndexSubtable2");
return -1;
}
void
print_IndexSubtable2(Otfile *f, int indent, Otf *o, IndexSubtable2 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "imageSize", v->imageSize);
f->print(f->aux, "%*s%s:\n", indent, "", "bigMetrics");
print_BigGlyphMetrics(f, indent+indentΔ, o, &v->bigMetrics);
USED(o);
}
int
read_IndexSubtable3(Otf *o, IndexSubtable3 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, ((o->lastGlyphIndex-o->firstGlyphIndex)+2)*2)) == nil)
goto err;
v->sbitOffsets = malloc(((o->lastGlyphIndex-o->firstGlyphIndex)+2)*sizeof(*v->sbitOffsets));
for(int i = 0; i < ((o->lastGlyphIndex-o->firstGlyphIndex)+2); i++)
v->sbitOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "IndexSubtable3");
return -1;
}
void
print_IndexSubtable3(Otfile *f, int indent, Otf *o, IndexSubtable3 *v)
{
for(int i = 0; i < ((o->lastGlyphIndex-o->firstGlyphIndex)+2); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "sbitOffsets", i, v->sbitOffsets[i]);
USED(o);
}
int
read_GlyphIdOffsetPair(Otf *o, GlyphIdOffsetPair *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->glyphID = b[0]<<8 | b[1];
v->sbitOffset = b[2]<<8 | b[3];
return 0;
err:
werrstr("%s: %r", "GlyphIdOffsetPair");
return -1;
}
void
print_GlyphIdOffsetPair(Otfile *f, int indent, Otf *o, GlyphIdOffsetPair *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "sbitOffset", v->sbitOffset);
USED(o);
}
int
read_IndexSubtable4(Otf *o, IndexSubtable4 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->numGlyphs = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(otfarray(o, &v->glyphArray, read_GlyphIdOffsetPair, sizeof(GlyphIdOffsetPair), (v->numGlyphs+1)) < 0){
werrstr("%s: %r", "glyphArray");
goto err;
}
return 0;
err:
werrstr("%s: %r", "IndexSubtable4");
return -1;
}
void
print_IndexSubtable4(Otfile *f, int indent, Otf *o, IndexSubtable4 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numGlyphs", v->numGlyphs);
for(int i = 0; i < (v->numGlyphs+1); i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "glyphArray", i);
print_GlyphIdOffsetPair(f, indent+indentΔ, o, &v->glyphArray[i]);
}
USED(o);
}
int
read_IndexSubtable5(Otf *o, IndexSubtable5 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->imageSize = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(read_BigGlyphMetrics(o, &v->bigMetrics) < 0){
werrstr("%s: %r", "bigMetrics");
goto err;
}
if((b = otfreadn(o, 4)) == nil)
goto err;
v->numGlyphs = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if((b = otfreadn(o, v->numGlyphs*2)) == nil)
goto err;
v->glyphIdArray = malloc(v->numGlyphs*sizeof(*v->glyphIdArray));
for(int i = 0; i < v->numGlyphs; i++)
v->glyphIdArray[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "IndexSubtable5");
return -1;
}
void
print_IndexSubtable5(Otfile *f, int indent, Otf *o, IndexSubtable5 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "imageSize", v->imageSize);
f->print(f->aux, "%*s%s:\n", indent, "", "bigMetrics");
print_BigGlyphMetrics(f, indent+indentΔ, o, &v->bigMetrics);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numGlyphs", v->numGlyphs);
for(int i = 0; i < v->numGlyphs; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "glyphIdArray", i, v->glyphIdArray[i]);
USED(o);
}
int
read_IndexSubtable(Otf *o, IndexSubtable *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->indexFormat = b[0]<<8 | b[1];
if(v->indexFormat < 1 || v->indexFormat > 5){
werrstr("%s: invalid value: %d (%#ux)", "indexFormat", v->indexFormat, v->indexFormat);
goto err;
}
v->imageFormat = b[2]<<8 | b[3];
v->imageDataOffset = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
if(v->indexFormat == 1){
if(read_IndexSubtable1(o, &v->sub1) < 0){
werrstr("%s: %r", "sub1");
goto err;
}
}
if(v->indexFormat == 2){
if(read_IndexSubtable2(o, &v->sub2) < 0){
werrstr("%s: %r", "sub2");
goto err;
}
}
if(v->indexFormat == 3){
if(read_IndexSubtable3(o, &v->sub3) < 0){
werrstr("%s: %r", "sub3");
goto err;
}
}
if(v->indexFormat == 4){
if(read_IndexSubtable4(o, &v->sub4) < 0){
werrstr("%s: %r", "sub4");
goto err;
}
}
if(v->indexFormat == 5){
if(read_IndexSubtable5(o, &v->sub5) < 0){
werrstr("%s: %r", "sub5");
goto err;
}
}
return 0;
err:
werrstr("%s: %r", "IndexSubtable");
return -1;
}
void
print_IndexSubtable(Otfile *f, int indent, Otf *o, IndexSubtable *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "indexFormat", v->indexFormat);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "imageFormat", v->imageFormat);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "imageDataOffset", v->imageDataOffset);
if(v->indexFormat == 1){
f->print(f->aux, "%*s%s:\n", indent, "", "sub1");
print_IndexSubtable1(f, indent+indentΔ, o, &v->sub1);
}
if(v->indexFormat == 2){
f->print(f->aux, "%*s%s:\n", indent, "", "sub2");
print_IndexSubtable2(f, indent+indentΔ, o, &v->sub2);
}
if(v->indexFormat == 3){
f->print(f->aux, "%*s%s:\n", indent, "", "sub3");
print_IndexSubtable3(f, indent+indentΔ, o, &v->sub3);
}
if(v->indexFormat == 4){
f->print(f->aux, "%*s%s:\n", indent, "", "sub4");
print_IndexSubtable4(f, indent+indentΔ, o, &v->sub4);
}
if(v->indexFormat == 5){
f->print(f->aux, "%*s%s:\n", indent, "", "sub5");
print_IndexSubtable5(f, indent+indentΔ, o, &v->sub5);
}
USED(o);
}
int
read_IndexSubtableRecord(Otf *o, IndexSubtableRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->firstGlyphIndex = b[0]<<8 | b[1];
o->firstGlyphIndex = v->firstGlyphIndex;
v->lastGlyphIndex = b[2]<<8 | b[3];
o->lastGlyphIndex = v->lastGlyphIndex;
v->indexSubtableOffset = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
if(v->indexSubtableOffset != 0){
if(otfpushrange(o, v->indexSubtableOffset, -1) < 0)
goto err;
v->indexSubtable = calloc(1, sizeof(*v->indexSubtable));
if(read_IndexSubtable(o, v->indexSubtable) < 0){
werrstr("%s: %r", "indexSubtable");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "IndexSubtableRecord");
return -1;
}
void
print_IndexSubtableRecord(Otfile *f, int indent, Otf *o, IndexSubtableRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "firstGlyphIndex", v->firstGlyphIndex);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lastGlyphIndex", v->lastGlyphIndex);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "indexSubtableOffset", v->indexSubtableOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "indexSubtable");
if(v->indexSubtable != nil)
print_IndexSubtable(f, indent+indentΔ, o, v->indexSubtable);
USED(o);
}
int
read_BitmapSize(Otf *o, BitmapSize *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 16)) == nil)
goto err;
v->indexSubtableListOffset = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->indexSubtableListSize = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
v->numberOfIndexSubtables = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11];
if(read_SbitLineMetrics(o, &v->hori) < 0){
werrstr("%s: %r", "hori");
goto err;
}
if(read_SbitLineMetrics(o, &v->vert) < 0){
werrstr("%s: %r", "vert");
goto err;
}
if((b = otfreadn(o, 8)) == nil)
goto err;
v->startGlyphIndex = b[0]<<8 | b[1];
v->endGlyphIndex = b[2]<<8 | b[3];
v->ppemX = b[4];
v->ppemY = b[5];
v->bitDepth = b[6];
v->flags = b[7];
if(v->indexSubtableListOffset != 0){
if(otfpushrange(o, v->indexSubtableListOffset, -1) < 0)
goto err;
if(otfarray(o, &v->indexSubtableList, read_IndexSubtableRecord, sizeof(IndexSubtableRecord), v->numberOfIndexSubtables) < 0){
werrstr("%s: %r", "indexSubtableList");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "BitmapSize");
return -1;
}
void
print_BitmapSize(Otfile *f, int indent, Otf *o, BitmapSize *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "indexSubtableListOffset", v->indexSubtableListOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "indexSubtableListSize", v->indexSubtableListSize);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numberOfIndexSubtables", v->numberOfIndexSubtables);
f->print(f->aux, "%*s%s:\n", indent, "", "hori");
print_SbitLineMetrics(f, indent+indentΔ, o, &v->hori);
f->print(f->aux, "%*s%s:\n", indent, "", "vert");
print_SbitLineMetrics(f, indent+indentΔ, o, &v->vert);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "startGlyphIndex", v->startGlyphIndex);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "endGlyphIndex", v->endGlyphIndex);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "ppemX", v->ppemX);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "ppemY", v->ppemY);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "bitDepth", v->bitDepth);
f->print(f->aux, "%*s%s: %#ux%s%s\n", indent, "", "flags", v->flags, (v->flags&BITMAPSIZE_FL_HORIZONTAL_METRICS)?" BITMAPSIZE_FL_HORIZONTAL_METRICS":"", (v->flags&BITMAPSIZE_FL_VERTICAL_METRICS)?" BITMAPSIZE_FL_VERTICAL_METRICS":"");
for(int i = 0; i < v->numberOfIndexSubtables; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "indexSubtableList", i);
print_IndexSubtableRecord(f, indent+indentΔ, o, &v->indexSubtableList[i]);
}
USED(o);
}
int
read_TableEBDT(Otf *o, TableEBDT *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->majorVersion = b[0]<<8 | b[1];
if(v->majorVersion != 2){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", v->majorVersion, v->majorVersion);
goto err;
}
u16int minorVersion = b[2]<<8 | b[3];
if(minorVersion != 0){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", minorVersion, minorVersion);
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableEBDT");
return -1;
}
void
print_TableEBDT(Otfile *f, int indent, Otf *o, TableEBDT *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "majorVersion", v->majorVersion);
USED(o);
}
int
read_TableEBLC(Otf *o, TableEBLC *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 2){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
u16int minorVersion = b[2]<<8 | b[3];
if(minorVersion != 0){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", minorVersion, minorVersion);
goto err;
}
v->numSizes = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
if(otfarray(o, &v->bitmapSizes, read_BitmapSize, sizeof(BitmapSize), v->numSizes) < 0){
werrstr("%s: %r", "bitmapSizes");
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableEBLC");
return -1;
}
void
print_TableEBLC(Otfile *f, int indent, Otf *o, TableEBLC *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numSizes", v->numSizes);
for(int i = 0; i < v->numSizes; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "bitmapSizes", i);
print_BitmapSize(f, indent+indentΔ, o, &v->bitmapSizes[i]);
}
USED(o);
}
int
read_AttachList(Otf *o, AttachList *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->coverageOffset = b[0]<<8 | b[1];
v->glyphCount = b[2]<<8 | b[3];
if((b = otfreadn(o, v->glyphCount*2)) == nil)
goto err;
v->attachPointOffsets = malloc(v->glyphCount*sizeof(*v->attachPointOffsets));
for(int i = 0; i < v->glyphCount; i++)
v->attachPointOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "AttachList");
return -1;
}
void
print_AttachList(Otfile *f, int indent, Otf *o, AttachList *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "coverageOffset", v->coverageOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphCount", v->glyphCount);
for(int i = 0; i < v->glyphCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "attachPointOffsets", i, v->attachPointOffsets[i]);
USED(o);
}
int
read_AttachPoint(Otf *o, AttachPoint *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->pointCount = b[0]<<8 | b[1];
if((b = otfreadn(o, v->pointCount*2)) == nil)
goto err;
v->pointIndices = malloc(v->pointCount*sizeof(*v->pointIndices));
for(int i = 0; i < v->pointCount; i++)
v->pointIndices[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "AttachPoint");
return -1;
}
void
print_AttachPoint(Otfile *f, int indent, Otf *o, AttachPoint *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "pointCount", v->pointCount);
for(int i = 0; i < v->pointCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "pointIndices", i, v->pointIndices[i]);
USED(o);
}
int
read_LigCaretList(Otf *o, LigCaretList *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->coverageOffset = b[0]<<8 | b[1];
v->ligGlyphCount = b[2]<<8 | b[3];
if((b = otfreadn(o, v->ligGlyphCount*2)) == nil)
goto err;
v->ligGlyphOffsets = malloc(v->ligGlyphCount*sizeof(*v->ligGlyphOffsets));
for(int i = 0; i < v->ligGlyphCount; i++)
v->ligGlyphOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "LigCaretList");
return -1;
}
void
print_LigCaretList(Otfile *f, int indent, Otf *o, LigCaretList *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "coverageOffset", v->coverageOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "ligGlyphCount", v->ligGlyphCount);
for(int i = 0; i < v->ligGlyphCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "ligGlyphOffsets", i, v->ligGlyphOffsets[i]);
USED(o);
}
int
read_LigGlyph(Otf *o, LigGlyph *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->caretCount = b[0]<<8 | b[1];
if((b = otfreadn(o, v->caretCount*2)) == nil)
goto err;
v->caretValueOffsets = malloc(v->caretCount*sizeof(*v->caretValueOffsets));
for(int i = 0; i < v->caretCount; i++)
v->caretValueOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "LigGlyph");
return -1;
}
void
print_LigGlyph(Otfile *f, int indent, Otf *o, LigGlyph *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "caretCount", v->caretCount);
for(int i = 0; i < v->caretCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "caretValueOffsets", i, v->caretValueOffsets[i]);
USED(o);
}
int
read_CaretValue(Otf *o, CaretValue *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->format = b[0]<<8 | b[1];
if(v->format < 1 || v->format > 3){
werrstr("%s: invalid value: %d (%#ux)", "format", v->format, v->format);
goto err;
}
if(v->format == 1 || v->format == 3){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->coordinate = b[0]<<8 | b[1];
}
if(v->format == 2){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->caretValuePointIndex = b[0]<<8 | b[1];
}
if(v->format == 3){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->deviceOffset = b[0]<<8 | b[1];
}
return 0;
err:
werrstr("%s: %r", "CaretValue");
return -1;
}
void
print_CaretValue(Otfile *f, int indent, Otf *o, CaretValue *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "format", v->format);
if(v->format == 1 || v->format == 3)
f->print(f->aux, "%*s%s: %d\n", indent, "", "coordinate", v->coordinate);
if(v->format == 2)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "caretValuePointIndex", v->caretValuePointIndex);
if(v->format == 3)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "deviceOffset", v->deviceOffset);
USED(o);
}
int
read_ValueRecord(Otf *o, ValueRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 16)) == nil)
goto err;
v->xPlacement = b[0]<<8 | b[1];
v->yPlacement = b[2]<<8 | b[3];
v->xAdvance = b[4]<<8 | b[5];
v->yAdvance = b[6]<<8 | b[7];
v->xPlaDeviceOffset = b[8]<<8 | b[9];
v->yPlaDeviceOffset = b[10]<<8 | b[11];
v->xAdvDeviceOffset = b[12]<<8 | b[13];
v->yAdvDeviceOffset = b[14]<<8 | b[15];
return 0;
err:
werrstr("%s: %r", "ValueRecord");
return -1;
}
void
print_ValueRecord(Otfile *f, int indent, Otf *o, ValueRecord *v)
{
f->print(f->aux, "%*s%s: %d\n", indent, "", "xPlacement", v->xPlacement);
f->print(f->aux, "%*s%s: %d\n", indent, "", "yPlacement", v->yPlacement);
f->print(f->aux, "%*s%s: %d\n", indent, "", "xAdvance", v->xAdvance);
f->print(f->aux, "%*s%s: %d\n", indent, "", "yAdvance", v->yAdvance);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "xPlaDeviceOffset", v->xPlaDeviceOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "yPlaDeviceOffset", v->yPlaDeviceOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "xAdvDeviceOffset", v->xAdvDeviceOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "yAdvDeviceOffset", v->yAdvDeviceOffset);
USED(o);
}
int
read_SinglePos(Otf *o, SinglePos *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->format = b[0]<<8 | b[1];
if(v->format != 1 && v->format != 2){
werrstr("%s: invalid value: %d (%#ux)", "format", v->format, v->format);
goto err;
}
v->coverageOffset = b[2]<<8 | b[3];
v->valueFormat = b[4]<<8 | b[5];
if(v->format == 1){
if(read_ValueRecord(o, &v->valueRecord) < 0){
werrstr("%s: %r", "valueRecord");
goto err;
}
}
if(v->format == 2){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->valueCount = b[0]<<8 | b[1];
}
if(v->format == 2){
if(otfarray(o, &v->valueRecords, read_ValueRecord, sizeof(ValueRecord), v->valueCount) < 0){
werrstr("%s: %r", "valueRecords");
goto err;
}
}
return 0;
err:
werrstr("%s: %r", "SinglePos");
return -1;
}
void
print_SinglePos(Otfile *f, int indent, Otf *o, SinglePos *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "format", v->format);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "coverageOffset", v->coverageOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "valueFormat", v->valueFormat);
if(v->format == 1){
f->print(f->aux, "%*s%s:\n", indent, "", "valueRecord");
print_ValueRecord(f, indent+indentΔ, o, &v->valueRecord);
}
if(v->format == 2)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "valueCount", v->valueCount);
if(v->format == 2){
for(int i = 0; i < v->valueCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "valueRecords", i);
print_ValueRecord(f, indent+indentΔ, o, &v->valueRecords[i]);
}
}
USED(o);
}
int
read_TableGDEF(Otf *o, TableGDEF *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 12)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
v->minorVersion = b[2]<<8 | b[3];
if(v->minorVersion != 0 && v->minorVersion != 2 && v->minorVersion != 3){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", v->minorVersion, v->minorVersion);
goto err;
}
v->glyphClassDefOffset = b[4]<<8 | b[5];
v->attachListOffset = b[6]<<8 | b[7];
v->ligCaretListOffset = b[8]<<8 | b[9];
v->markAttachClassDefOffset = b[10]<<8 | b[11];
if(v->minorVersion >= 2){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->markGlyphSetsDefOffset = b[0]<<8 | b[1];
}
if(v->minorVersion >= 3){
if((b = otfreadn(o, 4)) == nil)
goto err;
v->itemVarStoreOffset = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
}
return 0;
err:
werrstr("%s: %r", "TableGDEF");
return -1;
}
void
print_TableGDEF(Otfile *f, int indent, Otf *o, TableGDEF *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphClassDefOffset", v->glyphClassDefOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "attachListOffset", v->attachListOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "ligCaretListOffset", v->ligCaretListOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "markAttachClassDefOffset", v->markAttachClassDefOffset);
if(v->minorVersion >= 2)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "markGlyphSetsDefOffset", v->markGlyphSetsDefOffset);
if(v->minorVersion >= 3)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "itemVarStoreOffset", v->itemVarStoreOffset);
USED(o);
}
int
read_LangSys(Otf *o, LangSys *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->requiredFeatureIndex = b[2]<<8 | b[3];
v->featureIndexCount = b[4]<<8 | b[5];
if((b = otfreadn(o, v->featureIndexCount*2)) == nil)
goto err;
v->featureIndices = malloc(v->featureIndexCount*sizeof(*v->featureIndices));
for(int i = 0; i < v->featureIndexCount; i++)
v->featureIndices[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "LangSys");
return -1;
}
void
print_LangSys(Otfile *f, int indent, Otf *o, LangSys *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "requiredFeatureIndex", v->requiredFeatureIndex);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "featureIndexCount", v->featureIndexCount);
for(int i = 0; i < v->featureIndexCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "featureIndices", i, v->featureIndices[i]);
USED(o);
}
int
read_LangSysRecord(Otf *o, LangSysRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->langSysTag = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->langSysOffset = b[4]<<8 | b[5];
if(v->langSysOffset != 0){
if(otfpushrange(o, v->langSysOffset, -1) < 0)
goto err;
v->langSys = calloc(1, sizeof(*v->langSys));
if(read_LangSys(o, v->langSys) < 0){
werrstr("%s: %r", "langSys");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "LangSysRecord");
return -1;
}
void
print_LangSysRecord(Otfile *f, int indent, Otf *o, LangSysRecord *v)
{
f->print(f->aux, "%*s%s: %c%c%c%c\n", indent, "", "langSysTag", v->langSysTag>>24, v->langSysTag>>16, v->langSysTag>>8, v->langSysTag>>0);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "langSysOffset", v->langSysOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "langSys");
if(v->langSys != nil)
print_LangSys(f, indent+indentΔ, o, v->langSys);
USED(o);
}
int
read_Script(Otf *o, Script *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->defaultLangSysOffset = b[0]<<8 | b[1];
v->langSysCount = b[2]<<8 | b[3];
if(otfarray(o, &v->langSysRecords, read_LangSysRecord, sizeof(LangSysRecord), v->langSysCount) < 0){
werrstr("%s: %r", "langSysRecords");
goto err;
}
if(v->defaultLangSysOffset != 0){
if(otfpushrange(o, v->defaultLangSysOffset, -1) < 0)
goto err;
v->defaultLangSys = calloc(1, sizeof(*v->defaultLangSys));
if(read_LangSys(o, v->defaultLangSys) < 0){
werrstr("%s: %r", "defaultLangSys");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "Script");
return -1;
}
void
print_Script(Otfile *f, int indent, Otf *o, Script *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "defaultLangSysOffset", v->defaultLangSysOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "langSysCount", v->langSysCount);
for(int i = 0; i < v->langSysCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "langSysRecords", i);
print_LangSysRecord(f, indent+indentΔ, o, &v->langSysRecords[i]);
}
f->print(f->aux, "%*s%s:\n", indent, "", "defaultLangSys");
if(v->defaultLangSys != nil)
print_LangSys(f, indent+indentΔ, o, v->defaultLangSys);
USED(o);
}
int
read_ScriptRecord(Otf *o, ScriptRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->scriptTag = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->scriptOffset = b[4]<<8 | b[5];
if(v->scriptOffset != 0){
if(otfpushrange(o, v->scriptOffset, -1) < 0)
goto err;
v->script = calloc(1, sizeof(*v->script));
if(read_Script(o, v->script) < 0){
werrstr("%s: %r", "script");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "ScriptRecord");
return -1;
}
void
print_ScriptRecord(Otfile *f, int indent, Otf *o, ScriptRecord *v)
{
f->print(f->aux, "%*s%s: %c%c%c%c\n", indent, "", "scriptTag", v->scriptTag>>24, v->scriptTag>>16, v->scriptTag>>8, v->scriptTag>>0);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "scriptOffset", v->scriptOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "script");
if(v->script != nil)
print_Script(f, indent+indentΔ, o, v->script);
USED(o);
}
int
read_ScriptList(Otf *o, ScriptList *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->scriptCount = b[0]<<8 | b[1];
if(otfarray(o, &v->scriptRecords, read_ScriptRecord, sizeof(ScriptRecord), v->scriptCount) < 0){
werrstr("%s: %r", "scriptRecords");
goto err;
}
return 0;
err:
werrstr("%s: %r", "ScriptList");
return -1;
}
void
print_ScriptList(Otfile *f, int indent, Otf *o, ScriptList *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "scriptCount", v->scriptCount);
for(int i = 0; i < v->scriptCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "scriptRecords", i);
print_ScriptRecord(f, indent+indentΔ, o, &v->scriptRecords[i]);
}
USED(o);
}
int
read_Feature(Otf *o, Feature *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->featureParamsOffset = b[0]<<8 | b[1];
v->lookupIndexCount = b[2]<<8 | b[3];
if((b = otfreadn(o, v->lookupIndexCount*2)) == nil)
goto err;
v->lookupListIndices = malloc(v->lookupIndexCount*sizeof(*v->lookupListIndices));
for(int i = 0; i < v->lookupIndexCount; i++)
v->lookupListIndices[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "Feature");
return -1;
}
void
print_Feature(Otfile *f, int indent, Otf *o, Feature *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "featureParamsOffset", v->featureParamsOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookupIndexCount", v->lookupIndexCount);
for(int i = 0; i < v->lookupIndexCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "lookupListIndices", i, v->lookupListIndices[i]);
USED(o);
}
int
read_FeatureRecord(Otf *o, FeatureRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->featureTag = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->featureOffset = b[4]<<8 | b[5];
if(v->featureOffset != 0){
if(otfpushrange(o, v->featureOffset, -1) < 0)
goto err;
v->feature = calloc(1, sizeof(*v->feature));
if(read_Feature(o, v->feature) < 0){
werrstr("%s: %r", "feature");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "FeatureRecord");
return -1;
}
void
print_FeatureRecord(Otfile *f, int indent, Otf *o, FeatureRecord *v)
{
f->print(f->aux, "%*s%s: %c%c%c%c\n", indent, "", "featureTag", v->featureTag>>24, v->featureTag>>16, v->featureTag>>8, v->featureTag>>0);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "featureOffset", v->featureOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "feature");
if(v->feature != nil)
print_Feature(f, indent+indentΔ, o, v->feature);
USED(o);
}
int
read_FeatureList(Otf *o, FeatureList *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->featureCount = b[0]<<8 | b[1];
if(otfarray(o, &v->featureRecords, read_FeatureRecord, sizeof(FeatureRecord), v->featureCount) < 0){
werrstr("%s: %r", "featureRecords");
goto err;
}
return 0;
err:
werrstr("%s: %r", "FeatureList");
return -1;
}
void
print_FeatureList(Otfile *f, int indent, Otf *o, FeatureList *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "featureCount", v->featureCount);
for(int i = 0; i < v->featureCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "featureRecords", i);
print_FeatureRecord(f, indent+indentΔ, o, &v->featureRecords[i]);
}
USED(o);
}
int
read_Lookup(Otf *o, Lookup *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->lookupType = b[0]<<8 | b[1];
v->lookupFlag = b[2]<<8 | b[3];
v->subTableCount = b[4]<<8 | b[5];
if((b = otfreadn(o, v->subTableCount*2)) == nil)
goto err;
v->subtableOffsets = malloc(v->subTableCount*sizeof(*v->subtableOffsets));
for(int i = 0; i < v->subTableCount; i++)
v->subtableOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
if((b = otfreadn(o, 2)) == nil)
goto err;
v->markFilteringSet = b[0]<<8 | b[1];
return 0;
err:
werrstr("%s: %r", "Lookup");
return -1;
}
void
print_Lookup(Otfile *f, int indent, Otf *o, Lookup *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookupType", v->lookupType);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookupFlag", v->lookupFlag);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "subTableCount", v->subTableCount);
for(int i = 0; i < v->subTableCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "subtableOffsets", i, v->subtableOffsets[i]);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "markFilteringSet", v->markFilteringSet);
USED(o);
}
int
read_LookupList(Otf *o, LookupList *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->lookupCount = b[0]<<8 | b[1];
if((b = otfreadn(o, v->lookupCount*2)) == nil)
goto err;
v->lookupOffsets = malloc(v->lookupCount*sizeof(*v->lookupOffsets));
for(int i = 0; i < v->lookupCount; i++)
v->lookupOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "LookupList");
return -1;
}
void
print_LookupList(Otfile *f, int indent, Otf *o, LookupList *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookupCount", v->lookupCount);
for(int i = 0; i < v->lookupCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "lookupOffsets", i, v->lookupOffsets[i]);
USED(o);
}
int
read_TableGPOS(Otf *o, TableGPOS *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 10)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
v->minorVersion = b[2]<<8 | b[3];
if(v->minorVersion > 1){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", v->minorVersion, v->minorVersion);
goto err;
}
v->scriptListOffset = b[4]<<8 | b[5];
v->featureListOffset = b[6]<<8 | b[7];
v->lookupListOffset = b[8]<<8 | b[9];
if(v->minorVersion == 1){
if((b = otfreadn(o, 4)) == nil)
goto err;
v->featureVariationsOffset = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
}
if(v->scriptListOffset != 0){
if(otfpushrange(o, v->scriptListOffset, -1) < 0)
goto err;
v->scriptList = calloc(1, sizeof(*v->scriptList));
if(read_ScriptList(o, v->scriptList) < 0){
werrstr("%s: %r", "scriptList");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->featureListOffset != 0){
if(otfpushrange(o, v->featureListOffset, -1) < 0)
goto err;
v->featureList = calloc(1, sizeof(*v->featureList));
if(read_FeatureList(o, v->featureList) < 0){
werrstr("%s: %r", "featureList");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->lookupListOffset != 0){
if(otfpushrange(o, v->lookupListOffset, -1) < 0)
goto err;
v->lookupList = calloc(1, sizeof(*v->lookupList));
if(read_LookupList(o, v->lookupList) < 0){
werrstr("%s: %r", "lookupList");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableGPOS");
return -1;
}
void
print_TableGPOS(Otfile *f, int indent, Otf *o, TableGPOS *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "scriptListOffset", v->scriptListOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "featureListOffset", v->featureListOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookupListOffset", v->lookupListOffset);
if(v->minorVersion == 1)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "featureVariationsOffset", v->featureVariationsOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "scriptList");
if(v->scriptList != nil)
print_ScriptList(f, indent+indentΔ, o, v->scriptList);
f->print(f->aux, "%*s%s:\n", indent, "", "featureList");
if(v->featureList != nil)
print_FeatureList(f, indent+indentΔ, o, v->featureList);
f->print(f->aux, "%*s%s:\n", indent, "", "lookupList");
if(v->lookupList != nil)
print_LookupList(f, indent+indentΔ, o, v->lookupList);
USED(o);
}
int
read_TableGSUB(Otf *o, TableGSUB *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 10)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
v->minorVersion = b[2]<<8 | b[3];
if(v->minorVersion > 1){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", v->minorVersion, v->minorVersion);
goto err;
}
v->scriptListOffset = b[4]<<8 | b[5];
v->featureListOffset = b[6]<<8 | b[7];
v->lookupListOffset = b[8]<<8 | b[9];
if(v->minorVersion == 1){
if((b = otfreadn(o, 4)) == nil)
goto err;
v->featureVariationsOffset = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
}
if(v->scriptListOffset != 0){
if(otfpushrange(o, v->scriptListOffset, -1) < 0)
goto err;
v->scriptList = calloc(1, sizeof(*v->scriptList));
if(read_ScriptList(o, v->scriptList) < 0){
werrstr("%s: %r", "scriptList");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->featureListOffset != 0){
if(otfpushrange(o, v->featureListOffset, -1) < 0)
goto err;
v->featureList = calloc(1, sizeof(*v->featureList));
if(read_FeatureList(o, v->featureList) < 0){
werrstr("%s: %r", "featureList");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableGSUB");
return -1;
}
void
print_TableGSUB(Otfile *f, int indent, Otf *o, TableGSUB *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "scriptListOffset", v->scriptListOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "featureListOffset", v->featureListOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookupListOffset", v->lookupListOffset);
if(v->minorVersion == 1)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "featureVariationsOffset", v->featureVariationsOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "scriptList");
if(v->scriptList != nil)
print_ScriptList(f, indent+indentΔ, o, v->scriptList);
f->print(f->aux, "%*s%s:\n", indent, "", "featureList");
if(v->featureList != nil)
print_FeatureList(f, indent+indentΔ, o, v->featureList);
USED(o);
}
int
read_MathValueRecord(Otf *o, MathValueRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->value = b[0]<<8 | b[1];
v->deviceOffset = b[2]<<8 | b[3];
return 0;
err:
werrstr("%s: %r", "MathValueRecord");
return -1;
}
void
print_MathValueRecord(Otfile *f, int indent, Otf *o, MathValueRecord *v)
{
f->print(f->aux, "%*s%s: %d\n", indent, "", "value", v->value);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "deviceOffset", v->deviceOffset);
USED(o);
}
int
read_MathConstants(Otf *o, MathConstants *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->scriptPercentScaleDown = b[0]<<8 | b[1];
v->scriptScriptPercentScaleDown = b[2]<<8 | b[3];
v->delimitedSubFormulaMinHeight = b[4]<<8 | b[5];
v->displayOperatorMinHeight = b[6]<<8 | b[7];
if(read_MathValueRecord(o, &v->mathLeading) < 0){
werrstr("%s: %r", "mathLeading");
goto err;
}
if(read_MathValueRecord(o, &v->axisHeight) < 0){
werrstr("%s: %r", "axisHeight");
goto err;
}
if(read_MathValueRecord(o, &v->accentBaseHeight) < 0){
werrstr("%s: %r", "accentBaseHeight");
goto err;
}
if(read_MathValueRecord(o, &v->flattenedAccentBaseHeight) < 0){
werrstr("%s: %r", "flattenedAccentBaseHeight");
goto err;
}
if(read_MathValueRecord(o, &v->subscriptShiftDown) < 0){
werrstr("%s: %r", "subscriptShiftDown");
goto err;
}
if(read_MathValueRecord(o, &v->subscriptTopMax) < 0){
werrstr("%s: %r", "subscriptTopMax");
goto err;
}
if(read_MathValueRecord(o, &v->subscriptBaselineDropMin) < 0){
werrstr("%s: %r", "subscriptBaselineDropMin");
goto err;
}
if(read_MathValueRecord(o, &v->superscriptShiftUp) < 0){
werrstr("%s: %r", "superscriptShiftUp");
goto err;
}
if(read_MathValueRecord(o, &v->superscriptShiftUpCramped) < 0){
werrstr("%s: %r", "superscriptShiftUpCramped");
goto err;
}
if(read_MathValueRecord(o, &v->superscriptBottomMin) < 0){
werrstr("%s: %r", "superscriptBottomMin");
goto err;
}
if(read_MathValueRecord(o, &v->superscriptBaselineDropMax) < 0){
werrstr("%s: %r", "superscriptBaselineDropMax");
goto err;
}
if(read_MathValueRecord(o, &v->subSuperscriptGapMin) < 0){
werrstr("%s: %r", "subSuperscriptGapMin");
goto err;
}
if(read_MathValueRecord(o, &v->superscriptBottomMaxWithSubscript) < 0){
werrstr("%s: %r", "superscriptBottomMaxWithSubscript");
goto err;
}
if(read_MathValueRecord(o, &v->spaceAfterScript) < 0){
werrstr("%s: %r", "spaceAfterScript");
goto err;
}
if(read_MathValueRecord(o, &v->upperLimitGapMin) < 0){
werrstr("%s: %r", "upperLimitGapMin");
goto err;
}
if(read_MathValueRecord(o, &v->upperLimitBaselineRiseMin) < 0){
werrstr("%s: %r", "upperLimitBaselineRiseMin");
goto err;
}
if(read_MathValueRecord(o, &v->lowerLimitGapMin) < 0){
werrstr("%s: %r", "lowerLimitGapMin");
goto err;
}
if(read_MathValueRecord(o, &v->lowerLimitBaselineDropMin) < 0){
werrstr("%s: %r", "lowerLimitBaselineDropMin");
goto err;
}
if(read_MathValueRecord(o, &v->stackTopShiftUp) < 0){
werrstr("%s: %r", "stackTopShiftUp");
goto err;
}
if(read_MathValueRecord(o, &v->stackTopDisplayStyleShiftUp) < 0){
werrstr("%s: %r", "stackTopDisplayStyleShiftUp");
goto err;
}
if(read_MathValueRecord(o, &v->stackBottomShiftDown) < 0){
werrstr("%s: %r", "stackBottomShiftDown");
goto err;
}
if(read_MathValueRecord(o, &v->stackBottomDisplayStyleShiftDown) < 0){
werrstr("%s: %r", "stackBottomDisplayStyleShiftDown");
goto err;
}
if(read_MathValueRecord(o, &v->stackGapMin) < 0){
werrstr("%s: %r", "stackGapMin");
goto err;
}
if(read_MathValueRecord(o, &v->stackDisplayStyleGapMin) < 0){
werrstr("%s: %r", "stackDisplayStyleGapMin");
goto err;
}
if(read_MathValueRecord(o, &v->stretchStackTopShiftUp) < 0){
werrstr("%s: %r", "stretchStackTopShiftUp");
goto err;
}
if(read_MathValueRecord(o, &v->stretchStackBottomShiftDown) < 0){
werrstr("%s: %r", "stretchStackBottomShiftDown");
goto err;
}
if(read_MathValueRecord(o, &v->stretchStackGapAboveMin) < 0){
werrstr("%s: %r", "stretchStackGapAboveMin");
goto err;
}
if(read_MathValueRecord(o, &v->stretchStackGapBelowMin) < 0){
werrstr("%s: %r", "stretchStackGapBelowMin");
goto err;
}
if(read_MathValueRecord(o, &v->fractionNumeratorShiftUp) < 0){
werrstr("%s: %r", "fractionNumeratorShiftUp");
goto err;
}
if(read_MathValueRecord(o, &v->fractionNumeratorDisplayStyleShiftUp) < 0){
werrstr("%s: %r", "fractionNumeratorDisplayStyleShiftUp");
goto err;
}
if(read_MathValueRecord(o, &v->fractionDenominatorShiftDown) < 0){
werrstr("%s: %r", "fractionDenominatorShiftDown");
goto err;
}
if(read_MathValueRecord(o, &v->fractionDenominatorDisplayStyleShiftDown) < 0){
werrstr("%s: %r", "fractionDenominatorDisplayStyleShiftDown");
goto err;
}
if(read_MathValueRecord(o, &v->fractionNumeratorGapMin) < 0){
werrstr("%s: %r", "fractionNumeratorGapMin");
goto err;
}
if(read_MathValueRecord(o, &v->fractionNumDisplayStyleGapMin) < 0){
werrstr("%s: %r", "fractionNumDisplayStyleGapMin");
goto err;
}
if(read_MathValueRecord(o, &v->fractionRuleThickness) < 0){
werrstr("%s: %r", "fractionRuleThickness");
goto err;
}
if(read_MathValueRecord(o, &v->fractionDenominatorGapMin) < 0){
werrstr("%s: %r", "fractionDenominatorGapMin");
goto err;
}
if(read_MathValueRecord(o, &v->fractionDenomDisplayStyleGapMin) < 0){
werrstr("%s: %r", "fractionDenomDisplayStyleGapMin");
goto err;
}
if(read_MathValueRecord(o, &v->skewedFractionHorizontalGap) < 0){
werrstr("%s: %r", "skewedFractionHorizontalGap");
goto err;
}
if(read_MathValueRecord(o, &v->skewedFractionVerticalGap) < 0){
werrstr("%s: %r", "skewedFractionVerticalGap");
goto err;
}
if(read_MathValueRecord(o, &v->overbarVerticalGap) < 0){
werrstr("%s: %r", "overbarVerticalGap");
goto err;
}
if(read_MathValueRecord(o, &v->overbarRuleThickness) < 0){
werrstr("%s: %r", "overbarRuleThickness");
goto err;
}
if(read_MathValueRecord(o, &v->overbarExtraAscender) < 0){
werrstr("%s: %r", "overbarExtraAscender");
goto err;
}
if(read_MathValueRecord(o, &v->underbarVerticalGap) < 0){
werrstr("%s: %r", "underbarVerticalGap");
goto err;
}
if(read_MathValueRecord(o, &v->underbarRuleThickness) < 0){
werrstr("%s: %r", "underbarRuleThickness");
goto err;
}
if(read_MathValueRecord(o, &v->underbarExtraDescender) < 0){
werrstr("%s: %r", "underbarExtraDescender");
goto err;
}
if(read_MathValueRecord(o, &v->radicalVerticalGap) < 0){
werrstr("%s: %r", "radicalVerticalGap");
goto err;
}
if(read_MathValueRecord(o, &v->radicalDisplayStyleVerticalGap) < 0){
werrstr("%s: %r", "radicalDisplayStyleVerticalGap");
goto err;
}
if(read_MathValueRecord(o, &v->radicalRuleThickness) < 0){
werrstr("%s: %r", "radicalRuleThickness");
goto err;
}
if(read_MathValueRecord(o, &v->radicalExtraAscender) < 0){
werrstr("%s: %r", "radicalExtraAscender");
goto err;
}
if(read_MathValueRecord(o, &v->radicalKernBeforeDegree) < 0){
werrstr("%s: %r", "radicalKernBeforeDegree");
goto err;
}
if(read_MathValueRecord(o, &v->radicalKernAfterDegree) < 0){
werrstr("%s: %r", "radicalKernAfterDegree");
goto err;
}
if((b = otfreadn(o, 2)) == nil)
goto err;
v->radicalDegreeBottomRaisePercent = b[0]<<8 | b[1];
return 0;
err:
werrstr("%s: %r", "MathConstants");
return -1;
}
void
print_MathConstants(Otfile *f, int indent, Otf *o, MathConstants *v)
{
f->print(f->aux, "%*s%s: %d\n", indent, "", "scriptPercentScaleDown", v->scriptPercentScaleDown);
f->print(f->aux, "%*s%s: %d\n", indent, "", "scriptScriptPercentScaleDown", v->scriptScriptPercentScaleDown);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "delimitedSubFormulaMinHeight", v->delimitedSubFormulaMinHeight);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "displayOperatorMinHeight", v->displayOperatorMinHeight);
f->print(f->aux, "%*s%s:\n", indent, "", "mathLeading");
print_MathValueRecord(f, indent+indentΔ, o, &v->mathLeading);
f->print(f->aux, "%*s%s:\n", indent, "", "axisHeight");
print_MathValueRecord(f, indent+indentΔ, o, &v->axisHeight);
f->print(f->aux, "%*s%s:\n", indent, "", "accentBaseHeight");
print_MathValueRecord(f, indent+indentΔ, o, &v->accentBaseHeight);
f->print(f->aux, "%*s%s:\n", indent, "", "flattenedAccentBaseHeight");
print_MathValueRecord(f, indent+indentΔ, o, &v->flattenedAccentBaseHeight);
f->print(f->aux, "%*s%s:\n", indent, "", "subscriptShiftDown");
print_MathValueRecord(f, indent+indentΔ, o, &v->subscriptShiftDown);
f->print(f->aux, "%*s%s:\n", indent, "", "subscriptTopMax");
print_MathValueRecord(f, indent+indentΔ, o, &v->subscriptTopMax);
f->print(f->aux, "%*s%s:\n", indent, "", "subscriptBaselineDropMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->subscriptBaselineDropMin);
f->print(f->aux, "%*s%s:\n", indent, "", "superscriptShiftUp");
print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptShiftUp);
f->print(f->aux, "%*s%s:\n", indent, "", "superscriptShiftUpCramped");
print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptShiftUpCramped);
f->print(f->aux, "%*s%s:\n", indent, "", "superscriptBottomMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptBottomMin);
f->print(f->aux, "%*s%s:\n", indent, "", "superscriptBaselineDropMax");
print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptBaselineDropMax);
f->print(f->aux, "%*s%s:\n", indent, "", "subSuperscriptGapMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->subSuperscriptGapMin);
f->print(f->aux, "%*s%s:\n", indent, "", "superscriptBottomMaxWithSubscript");
print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptBottomMaxWithSubscript);
f->print(f->aux, "%*s%s:\n", indent, "", "spaceAfterScript");
print_MathValueRecord(f, indent+indentΔ, o, &v->spaceAfterScript);
f->print(f->aux, "%*s%s:\n", indent, "", "upperLimitGapMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->upperLimitGapMin);
f->print(f->aux, "%*s%s:\n", indent, "", "upperLimitBaselineRiseMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->upperLimitBaselineRiseMin);
f->print(f->aux, "%*s%s:\n", indent, "", "lowerLimitGapMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->lowerLimitGapMin);
f->print(f->aux, "%*s%s:\n", indent, "", "lowerLimitBaselineDropMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->lowerLimitBaselineDropMin);
f->print(f->aux, "%*s%s:\n", indent, "", "stackTopShiftUp");
print_MathValueRecord(f, indent+indentΔ, o, &v->stackTopShiftUp);
f->print(f->aux, "%*s%s:\n", indent, "", "stackTopDisplayStyleShiftUp");
print_MathValueRecord(f, indent+indentΔ, o, &v->stackTopDisplayStyleShiftUp);
f->print(f->aux, "%*s%s:\n", indent, "", "stackBottomShiftDown");
print_MathValueRecord(f, indent+indentΔ, o, &v->stackBottomShiftDown);
f->print(f->aux, "%*s%s:\n", indent, "", "stackBottomDisplayStyleShiftDown");
print_MathValueRecord(f, indent+indentΔ, o, &v->stackBottomDisplayStyleShiftDown);
f->print(f->aux, "%*s%s:\n", indent, "", "stackGapMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->stackGapMin);
f->print(f->aux, "%*s%s:\n", indent, "", "stackDisplayStyleGapMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->stackDisplayStyleGapMin);
f->print(f->aux, "%*s%s:\n", indent, "", "stretchStackTopShiftUp");
print_MathValueRecord(f, indent+indentΔ, o, &v->stretchStackTopShiftUp);
f->print(f->aux, "%*s%s:\n", indent, "", "stretchStackBottomShiftDown");
print_MathValueRecord(f, indent+indentΔ, o, &v->stretchStackBottomShiftDown);
f->print(f->aux, "%*s%s:\n", indent, "", "stretchStackGapAboveMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->stretchStackGapAboveMin);
f->print(f->aux, "%*s%s:\n", indent, "", "stretchStackGapBelowMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->stretchStackGapBelowMin);
f->print(f->aux, "%*s%s:\n", indent, "", "fractionNumeratorShiftUp");
print_MathValueRecord(f, indent+indentΔ, o, &v->fractionNumeratorShiftUp);
f->print(f->aux, "%*s%s:\n", indent, "", "fractionNumeratorDisplayStyleShiftUp");
print_MathValueRecord(f, indent+indentΔ, o, &v->fractionNumeratorDisplayStyleShiftUp);
f->print(f->aux, "%*s%s:\n", indent, "", "fractionDenominatorShiftDown");
print_MathValueRecord(f, indent+indentΔ, o, &v->fractionDenominatorShiftDown);
f->print(f->aux, "%*s%s:\n", indent, "", "fractionDenominatorDisplayStyleShiftDown");
print_MathValueRecord(f, indent+indentΔ, o, &v->fractionDenominatorDisplayStyleShiftDown);
f->print(f->aux, "%*s%s:\n", indent, "", "fractionNumeratorGapMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->fractionNumeratorGapMin);
f->print(f->aux, "%*s%s:\n", indent, "", "fractionNumDisplayStyleGapMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->fractionNumDisplayStyleGapMin);
f->print(f->aux, "%*s%s:\n", indent, "", "fractionRuleThickness");
print_MathValueRecord(f, indent+indentΔ, o, &v->fractionRuleThickness);
f->print(f->aux, "%*s%s:\n", indent, "", "fractionDenominatorGapMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->fractionDenominatorGapMin);
f->print(f->aux, "%*s%s:\n", indent, "", "fractionDenomDisplayStyleGapMin");
print_MathValueRecord(f, indent+indentΔ, o, &v->fractionDenomDisplayStyleGapMin);
f->print(f->aux, "%*s%s:\n", indent, "", "skewedFractionHorizontalGap");
print_MathValueRecord(f, indent+indentΔ, o, &v->skewedFractionHorizontalGap);
f->print(f->aux, "%*s%s:\n", indent, "", "skewedFractionVerticalGap");
print_MathValueRecord(f, indent+indentΔ, o, &v->skewedFractionVerticalGap);
f->print(f->aux, "%*s%s:\n", indent, "", "overbarVerticalGap");
print_MathValueRecord(f, indent+indentΔ, o, &v->overbarVerticalGap);
f->print(f->aux, "%*s%s:\n", indent, "", "overbarRuleThickness");
print_MathValueRecord(f, indent+indentΔ, o, &v->overbarRuleThickness);
f->print(f->aux, "%*s%s:\n", indent, "", "overbarExtraAscender");
print_MathValueRecord(f, indent+indentΔ, o, &v->overbarExtraAscender);
f->print(f->aux, "%*s%s:\n", indent, "", "underbarVerticalGap");
print_MathValueRecord(f, indent+indentΔ, o, &v->underbarVerticalGap);
f->print(f->aux, "%*s%s:\n", indent, "", "underbarRuleThickness");
print_MathValueRecord(f, indent+indentΔ, o, &v->underbarRuleThickness);
f->print(f->aux, "%*s%s:\n", indent, "", "underbarExtraDescender");
print_MathValueRecord(f, indent+indentΔ, o, &v->underbarExtraDescender);
f->print(f->aux, "%*s%s:\n", indent, "", "radicalVerticalGap");
print_MathValueRecord(f, indent+indentΔ, o, &v->radicalVerticalGap);
f->print(f->aux, "%*s%s:\n", indent, "", "radicalDisplayStyleVerticalGap");
print_MathValueRecord(f, indent+indentΔ, o, &v->radicalDisplayStyleVerticalGap);
f->print(f->aux, "%*s%s:\n", indent, "", "radicalRuleThickness");
print_MathValueRecord(f, indent+indentΔ, o, &v->radicalRuleThickness);
f->print(f->aux, "%*s%s:\n", indent, "", "radicalExtraAscender");
print_MathValueRecord(f, indent+indentΔ, o, &v->radicalExtraAscender);
f->print(f->aux, "%*s%s:\n", indent, "", "radicalKernBeforeDegree");
print_MathValueRecord(f, indent+indentΔ, o, &v->radicalKernBeforeDegree);
f->print(f->aux, "%*s%s:\n", indent, "", "radicalKernAfterDegree");
print_MathValueRecord(f, indent+indentΔ, o, &v->radicalKernAfterDegree);
f->print(f->aux, "%*s%s: %d\n", indent, "", "radicalDegreeBottomRaisePercent", v->radicalDegreeBottomRaisePercent);
USED(o);
}
int
read_MathItalicsCorrectionInfo(Otf *o, MathItalicsCorrectionInfo *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->italicsCorrectionCoverageOffset = b[0]<<8 | b[1];
v->italicsCorrectionCount = b[2]<<8 | b[3];
if(otfarray(o, &v->italicsCorrection, read_MathValueRecord, sizeof(MathValueRecord), v->italicsCorrectionCount) < 0){
werrstr("%s: %r", "italicsCorrection");
goto err;
}
return 0;
err:
werrstr("%s: %r", "MathItalicsCorrectionInfo");
return -1;
}
void
print_MathItalicsCorrectionInfo(Otfile *f, int indent, Otf *o, MathItalicsCorrectionInfo *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "italicsCorrectionCoverageOffset", v->italicsCorrectionCoverageOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "italicsCorrectionCount", v->italicsCorrectionCount);
for(int i = 0; i < v->italicsCorrectionCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "italicsCorrection", i);
print_MathValueRecord(f, indent+indentΔ, o, &v->italicsCorrection[i]);
}
USED(o);
}
int
read_MathTopAccentAttachment(Otf *o, MathTopAccentAttachment *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->topAccentCoverageOffset = b[0]<<8 | b[1];
v->topAccentAttachmentCount = b[2]<<8 | b[3];
if(otfarray(o, &v->topAccentAttachment, read_MathValueRecord, sizeof(MathValueRecord), v->topAccentAttachmentCount) < 0){
werrstr("%s: %r", "topAccentAttachment");
goto err;
}
return 0;
err:
werrstr("%s: %r", "MathTopAccentAttachment");
return -1;
}
void
print_MathTopAccentAttachment(Otfile *f, int indent, Otf *o, MathTopAccentAttachment *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "topAccentCoverageOffset", v->topAccentCoverageOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "topAccentAttachmentCount", v->topAccentAttachmentCount);
for(int i = 0; i < v->topAccentAttachmentCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "topAccentAttachment", i);
print_MathValueRecord(f, indent+indentΔ, o, &v->topAccentAttachment[i]);
}
USED(o);
}
int
read_MathKernInfoRecord(Otf *o, MathKernInfoRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->topRightMathKernOffset = b[0]<<8 | b[1];
v->topLeftMathKernOffset = b[2]<<8 | b[3];
v->bottomRightMathKernOffset = b[4]<<8 | b[5];
v->bottomLeftMathKernOffset = b[6]<<8 | b[7];
return 0;
err:
werrstr("%s: %r", "MathKernInfoRecord");
return -1;
}
void
print_MathKernInfoRecord(Otfile *f, int indent, Otf *o, MathKernInfoRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "topRightMathKernOffset", v->topRightMathKernOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "topLeftMathKernOffset", v->topLeftMathKernOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "bottomRightMathKernOffset", v->bottomRightMathKernOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "bottomLeftMathKernOffset", v->bottomLeftMathKernOffset);
USED(o);
}
int
read_MathKernInfo(Otf *o, MathKernInfo *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->mathKernCoverageOffset = b[0]<<8 | b[1];
v->mathKernCount = b[2]<<8 | b[3];
if(otfarray(o, &v->mathKernInfoRecords, read_MathKernInfoRecord, sizeof(MathKernInfoRecord), v->mathKernCount) < 0){
werrstr("%s: %r", "mathKernInfoRecords");
goto err;
}
return 0;
err:
werrstr("%s: %r", "MathKernInfo");
return -1;
}
void
print_MathKernInfo(Otfile *f, int indent, Otf *o, MathKernInfo *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mathKernCoverageOffset", v->mathKernCoverageOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mathKernCount", v->mathKernCount);
for(int i = 0; i < v->mathKernCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "mathKernInfoRecords", i);
print_MathKernInfoRecord(f, indent+indentΔ, o, &v->mathKernInfoRecords[i]);
}
USED(o);
}
int
read_MathKern(Otf *o, MathKern *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->heightCount = b[0]<<8 | b[1];
if(otfarray(o, &v->correctionHeight, read_MathValueRecord, sizeof(MathValueRecord), v->heightCount) < 0){
werrstr("%s: %r", "correctionHeight");
goto err;
}
if(otfarray(o, &v->kernValues, read_MathValueRecord, sizeof(MathValueRecord), v->heightCount) < 0){
werrstr("%s: %r", "kernValues");
goto err;
}
return 0;
err:
werrstr("%s: %r", "MathKern");
return -1;
}
void
print_MathKern(Otfile *f, int indent, Otf *o, MathKern *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "heightCount", v->heightCount);
for(int i = 0; i < v->heightCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "correctionHeight", i);
print_MathValueRecord(f, indent+indentΔ, o, &v->correctionHeight[i]);
}
for(int i = 0; i < v->heightCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "kernValues", i);
print_MathValueRecord(f, indent+indentΔ, o, &v->kernValues[i]);
}
USED(o);
}
int
read_Coverage1(Otf *o, Coverage1 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->glyphCount = b[0]<<8 | b[1];
if((b = otfreadn(o, v->glyphCount*2)) == nil)
goto err;
v->glyphArray = malloc(v->glyphCount*sizeof(*v->glyphArray));
for(int i = 0; i < v->glyphCount; i++)
v->glyphArray[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "Coverage1");
return -1;
}
void
print_Coverage1(Otfile *f, int indent, Otf *o, Coverage1 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphCount", v->glyphCount);
for(int i = 0; i < v->glyphCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "glyphArray", i, v->glyphArray[i]);
USED(o);
}
int
read_RangeRecord(Otf *o, RangeRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->startGlyphID = b[0]<<8 | b[1];
v->endGlyphID = b[2]<<8 | b[3];
v->startCoverageIndex = b[4]<<8 | b[5];
return 0;
err:
werrstr("%s: %r", "RangeRecord");
return -1;
}
void
print_RangeRecord(Otfile *f, int indent, Otf *o, RangeRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "startGlyphID", v->startGlyphID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "endGlyphID", v->endGlyphID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "startCoverageIndex", v->startCoverageIndex);
USED(o);
}
int
read_Coverage2(Otf *o, Coverage2 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->rangeCount = b[0]<<8 | b[1];
if(otfarray(o, &v->rangeRecords, read_RangeRecord, sizeof(RangeRecord), v->rangeCount) < 0){
werrstr("%s: %r", "rangeRecords");
goto err;
}
return 0;
err:
werrstr("%s: %r", "Coverage2");
return -1;
}
void
print_Coverage2(Otfile *f, int indent, Otf *o, Coverage2 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "rangeCount", v->rangeCount);
for(int i = 0; i < v->rangeCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "rangeRecords", i);
print_RangeRecord(f, indent+indentΔ, o, &v->rangeRecords[i]);
}
USED(o);
}
int
read_Coverage(Otf *o, Coverage *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->format = b[0]<<8 | b[1];
if(v->format != 1 && v->format != 2){
werrstr("%s: invalid value: %d (%#ux)", "format", v->format, v->format);
goto err;
}
if(v->format == 1){
if(read_Coverage1(o, &v->cov1) < 0){
werrstr("%s: %r", "cov1");
goto err;
}
}
if(v->format == 2){
if(read_Coverage2(o, &v->cov2) < 0){
werrstr("%s: %r", "cov2");
goto err;
}
}
return 0;
err:
werrstr("%s: %r", "Coverage");
return -1;
}
void
print_Coverage(Otfile *f, int indent, Otf *o, Coverage *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "format", v->format);
if(v->format == 1){
f->print(f->aux, "%*s%s:\n", indent, "", "cov1");
print_Coverage1(f, indent+indentΔ, o, &v->cov1);
}
if(v->format == 2){
f->print(f->aux, "%*s%s:\n", indent, "", "cov2");
print_Coverage2(f, indent+indentΔ, o, &v->cov2);
}
USED(o);
}
int
read_MathVariants(Otf *o, MathVariants *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 10)) == nil)
goto err;
v->minConnectorOverlap = b[0]<<8 | b[1];
v->vertGlyphCoverageOffset = b[2]<<8 | b[3];
v->horizGlyphCoverageOffset = b[4]<<8 | b[5];
v->vertGlyphCount = b[6]<<8 | b[7];
v->horizGlyphCount = b[8]<<8 | b[9];
if((b = otfreadn(o, v->vertGlyphCount*2)) == nil)
goto err;
v->vertGlyphConstructionOffsets = malloc(v->vertGlyphCount*sizeof(*v->vertGlyphConstructionOffsets));
for(int i = 0; i < v->vertGlyphCount; i++)
v->vertGlyphConstructionOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
if((b = otfreadn(o, v->horizGlyphCount*2)) == nil)
goto err;
v->horizGlyphConstructionOffsets = malloc(v->horizGlyphCount*sizeof(*v->horizGlyphConstructionOffsets));
for(int i = 0; i < v->horizGlyphCount; i++)
v->horizGlyphConstructionOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
if(v->vertGlyphCoverageOffset != 0){
if(otfpushrange(o, v->vertGlyphCoverageOffset, -1) < 0)
goto err;
v->vertGlyphCoverage = calloc(1, sizeof(*v->vertGlyphCoverage));
if(read_Coverage(o, v->vertGlyphCoverage) < 0){
werrstr("%s: %r", "vertGlyphCoverage");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->horizGlyphCoverageOffset != 0){
if(otfpushrange(o, v->horizGlyphCoverageOffset, -1) < 0)
goto err;
v->horizGlyphCoverage = calloc(1, sizeof(*v->horizGlyphCoverage));
if(read_Coverage(o, v->horizGlyphCoverage) < 0){
werrstr("%s: %r", "horizGlyphCoverage");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "MathVariants");
return -1;
}
void
print_MathVariants(Otfile *f, int indent, Otf *o, MathVariants *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "minConnectorOverlap", v->minConnectorOverlap);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "vertGlyphCoverageOffset", v->vertGlyphCoverageOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "horizGlyphCoverageOffset", v->horizGlyphCoverageOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "vertGlyphCount", v->vertGlyphCount);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "horizGlyphCount", v->horizGlyphCount);
for(int i = 0; i < v->vertGlyphCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "vertGlyphConstructionOffsets", i, v->vertGlyphConstructionOffsets[i]);
for(int i = 0; i < v->horizGlyphCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "horizGlyphConstructionOffsets", i, v->horizGlyphConstructionOffsets[i]);
f->print(f->aux, "%*s%s:\n", indent, "", "vertGlyphCoverage");
if(v->vertGlyphCoverage != nil)
print_Coverage(f, indent+indentΔ, o, v->vertGlyphCoverage);
f->print(f->aux, "%*s%s:\n", indent, "", "horizGlyphCoverage");
if(v->horizGlyphCoverage != nil)
print_Coverage(f, indent+indentΔ, o, v->horizGlyphCoverage);
USED(o);
}
int
read_MathGlyphInfo(Otf *o, MathGlyphInfo *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->mathItalicsCorrectionInfoOffset = b[0]<<8 | b[1];
v->mathTopAccentAttachmentOffset = b[2]<<8 | b[3];
v->extendedShapeCoverageOffset = b[4]<<8 | b[5];
v->mathKernInfoOffset = b[6]<<8 | b[7];
if(v->mathItalicsCorrectionInfoOffset != 0){
if(otfpushrange(o, v->mathItalicsCorrectionInfoOffset, -1) < 0)
goto err;
v->mathItalicsCorrectionInfo = calloc(1, sizeof(*v->mathItalicsCorrectionInfo));
if(read_MathItalicsCorrectionInfo(o, v->mathItalicsCorrectionInfo) < 0){
werrstr("%s: %r", "mathItalicsCorrectionInfo");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->mathTopAccentAttachmentOffset != 0){
if(otfpushrange(o, v->mathTopAccentAttachmentOffset, -1) < 0)
goto err;
v->mathTopAccentAttachment = calloc(1, sizeof(*v->mathTopAccentAttachment));
if(read_MathTopAccentAttachment(o, v->mathTopAccentAttachment) < 0){
werrstr("%s: %r", "mathTopAccentAttachment");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->mathKernInfoOffset != 0){
if(otfpushrange(o, v->mathKernInfoOffset, -1) < 0)
goto err;
v->mathKernInfo = calloc(1, sizeof(*v->mathKernInfo));
if(read_MathKernInfo(o, v->mathKernInfo) < 0){
werrstr("%s: %r", "mathKernInfo");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->extendedShapeCoverageOffset != 0){
if(otfpushrange(o, v->extendedShapeCoverageOffset, -1) < 0)
goto err;
v->extendedShapeCoverage = calloc(1, sizeof(*v->extendedShapeCoverage));
if(read_Coverage(o, v->extendedShapeCoverage) < 0){
werrstr("%s: %r", "extendedShapeCoverage");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "MathGlyphInfo");
return -1;
}
void
print_MathGlyphInfo(Otfile *f, int indent, Otf *o, MathGlyphInfo *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mathItalicsCorrectionInfoOffset", v->mathItalicsCorrectionInfoOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mathTopAccentAttachmentOffset", v->mathTopAccentAttachmentOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "extendedShapeCoverageOffset", v->extendedShapeCoverageOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mathKernInfoOffset", v->mathKernInfoOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "mathItalicsCorrectionInfo");
if(v->mathItalicsCorrectionInfo != nil)
print_MathItalicsCorrectionInfo(f, indent+indentΔ, o, v->mathItalicsCorrectionInfo);
f->print(f->aux, "%*s%s:\n", indent, "", "mathTopAccentAttachment");
if(v->mathTopAccentAttachment != nil)
print_MathTopAccentAttachment(f, indent+indentΔ, o, v->mathTopAccentAttachment);
f->print(f->aux, "%*s%s:\n", indent, "", "mathKernInfo");
if(v->mathKernInfo != nil)
print_MathKernInfo(f, indent+indentΔ, o, v->mathKernInfo);
f->print(f->aux, "%*s%s:\n", indent, "", "extendedShapeCoverage");
if(v->extendedShapeCoverage != nil)
print_Coverage(f, indent+indentΔ, o, v->extendedShapeCoverage);
USED(o);
}
int
read_MathGlyphVariantRecord(Otf *o, MathGlyphVariantRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->variantGlyph = b[0]<<8 | b[1];
v->advanceMeasurement = b[2]<<8 | b[3];
return 0;
err:
werrstr("%s: %r", "MathGlyphVariantRecord");
return -1;
}
void
print_MathGlyphVariantRecord(Otfile *f, int indent, Otf *o, MathGlyphVariantRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "variantGlyph", v->variantGlyph);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "advanceMeasurement", v->advanceMeasurement);
USED(o);
}
int
read_GlyphPart(Otf *o, GlyphPart *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 10)) == nil)
goto err;
v->glyphID = b[0]<<8 | b[1];
v->startConnectorLength = b[2]<<8 | b[3];
v->endConnectorLength = b[4]<<8 | b[5];
v->fullAdvance = b[6]<<8 | b[7];
v->partFlags = b[8]<<8 | b[9];
return 0;
err:
werrstr("%s: %r", "GlyphPart");
return -1;
}
void
print_GlyphPart(Otfile *f, int indent, Otf *o, GlyphPart *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "startConnectorLength", v->startConnectorLength);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "endConnectorLength", v->endConnectorLength);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "fullAdvance", v->fullAdvance);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "partFlags", v->partFlags);
USED(o);
}
int
read_GlyphAssembly(Otf *o, GlyphAssembly *v)
{
u8int *b = nil; USED(b);
if(read_MathValueRecord(o, &v->italicsCorrection) < 0){
werrstr("%s: %r", "italicsCorrection");
goto err;
}
if((b = otfreadn(o, 2)) == nil)
goto err;
v->partCount = b[0]<<8 | b[1];
if(otfarray(o, &v->partRecords, read_GlyphPart, sizeof(GlyphPart), v->partCount) < 0){
werrstr("%s: %r", "partRecords");
goto err;
}
return 0;
err:
werrstr("%s: %r", "GlyphAssembly");
return -1;
}
void
print_GlyphAssembly(Otfile *f, int indent, Otf *o, GlyphAssembly *v)
{
f->print(f->aux, "%*s%s:\n", indent, "", "italicsCorrection");
print_MathValueRecord(f, indent+indentΔ, o, &v->italicsCorrection);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "partCount", v->partCount);
for(int i = 0; i < v->partCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "partRecords", i);
print_GlyphPart(f, indent+indentΔ, o, &v->partRecords[i]);
}
USED(o);
}
int
read_MathGlyphConstruction(Otf *o, MathGlyphConstruction *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->glyphAssemblyOffset = b[0]<<8 | b[1];
v->variantCount = b[2]<<8 | b[3];
if(otfarray(o, &v->mathGlyphVariantRecords, read_MathGlyphVariantRecord, sizeof(MathGlyphVariantRecord), v->variantCount) < 0){
werrstr("%s: %r", "mathGlyphVariantRecords");
goto err;
}
if(v->glyphAssemblyOffset != 0){
if(otfpushrange(o, v->glyphAssemblyOffset, -1) < 0)
goto err;
v->glyphAssembly = calloc(1, sizeof(*v->glyphAssembly));
if(read_GlyphAssembly(o, v->glyphAssembly) < 0){
werrstr("%s: %r", "glyphAssembly");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "MathGlyphConstruction");
return -1;
}
void
print_MathGlyphConstruction(Otfile *f, int indent, Otf *o, MathGlyphConstruction *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphAssemblyOffset", v->glyphAssemblyOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "variantCount", v->variantCount);
for(int i = 0; i < v->variantCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "mathGlyphVariantRecords", i);
print_MathGlyphVariantRecord(f, indent+indentΔ, o, &v->mathGlyphVariantRecords[i]);
}
f->print(f->aux, "%*s%s:\n", indent, "", "glyphAssembly");
if(v->glyphAssembly != nil)
print_GlyphAssembly(f, indent+indentΔ, o, v->glyphAssembly);
USED(o);
}
int
read_TableMATH(Otf *o, TableMATH *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 10)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
u16int minorVersion = b[2]<<8 | b[3];
if(minorVersion != 0){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", minorVersion, minorVersion);
goto err;
}
v->mathConstantsOffset = b[4]<<8 | b[5];
v->mathGlyphInfoOffset = b[6]<<8 | b[7];
v->mathVariantsOffset = b[8]<<8 | b[9];
if(v->mathConstantsOffset != 0){
if(otfpushrange(o, v->mathConstantsOffset, -1) < 0)
goto err;
v->mathConstants = calloc(1, sizeof(*v->mathConstants));
if(read_MathConstants(o, v->mathConstants) < 0){
werrstr("%s: %r", "mathConstants");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->mathGlyphInfoOffset != 0){
if(otfpushrange(o, v->mathGlyphInfoOffset, -1) < 0)
goto err;
v->mathGlyphInfo = calloc(1, sizeof(*v->mathGlyphInfo));
if(read_MathGlyphInfo(o, v->mathGlyphInfo) < 0){
werrstr("%s: %r", "mathGlyphInfo");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->mathVariantsOffset != 0){
if(otfpushrange(o, v->mathVariantsOffset, -1) < 0)
goto err;
v->mathVariants = calloc(1, sizeof(*v->mathVariants));
if(read_MathVariants(o, v->mathVariants) < 0){
werrstr("%s: %r", "mathVariants");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableMATH");
return -1;
}
void
print_TableMATH(Otfile *f, int indent, Otf *o, TableMATH *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mathConstantsOffset", v->mathConstantsOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mathGlyphInfoOffset", v->mathGlyphInfoOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mathVariantsOffset", v->mathVariantsOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "mathConstants");
if(v->mathConstants != nil)
print_MathConstants(f, indent+indentΔ, o, v->mathConstants);
f->print(f->aux, "%*s%s:\n", indent, "", "mathGlyphInfo");
if(v->mathGlyphInfo != nil)
print_MathGlyphInfo(f, indent+indentΔ, o, v->mathGlyphInfo);
f->print(f->aux, "%*s%s:\n", indent, "", "mathVariants");
if(v->mathVariants != nil)
print_MathVariants(f, indent+indentΔ, o, v->mathVariants);
USED(o);
}
int
read_KernPair(Otf *o, KernPair *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->left = b[0]<<8 | b[1];
v->right = b[2]<<8 | b[3];
v->value = b[4]<<8 | b[5];
return 0;
err:
werrstr("%s: %r", "KernPair");
return -1;
}
void
print_KernPair(Otfile *f, int indent, Otf *o, KernPair *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "left", v->left);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "right", v->right);
f->print(f->aux, "%*s%s: %d\n", indent, "", "value", v->value);
USED(o);
}
int
read_KernSubtable0(Otf *o, KernSubtable0 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->nPairs = b[0]<<8 | b[1];
v->searchRange = b[2]<<8 | b[3];
v->entrySelector = b[4]<<8 | b[5];
v->rangeShift = b[6]<<8 | b[7];
if(otfarray(o, &v->kernPairs, read_KernPair, sizeof(KernPair), v->nPairs) < 0){
werrstr("%s: %r", "kernPairs");
goto err;
}
return 0;
err:
werrstr("%s: %r", "KernSubtable0");
return -1;
}
void
print_KernSubtable0(Otfile *f, int indent, Otf *o, KernSubtable0 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "nPairs", v->nPairs);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "searchRange", v->searchRange);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "entrySelector", v->entrySelector);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "rangeShift", v->rangeShift);
for(int i = 0; i < v->nPairs; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "kernPairs", i);
print_KernPair(f, indent+indentΔ, o, &v->kernPairs[i]);
}
USED(o);
}
int
read_KernClass(Otf *o, KernClass *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->firstGlyph = b[0]<<8 | b[1];
v->nGlyphs = b[2]<<8 | b[3];
if((b = otfreadn(o, v->nGlyphs*2)) == nil)
goto err;
v->values = malloc(v->nGlyphs*sizeof(*v->values));
for(int i = 0; i < v->nGlyphs; i++)
v->values[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "KernClass");
return -1;
}
void
print_KernClass(Otfile *f, int indent, Otf *o, KernClass *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "firstGlyph", v->firstGlyph);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "nGlyphs", v->nGlyphs);
for(int i = 0; i < v->nGlyphs; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "values", i, v->values[i]);
USED(o);
}
int
read_KernSubtable2(Otf *o, KernSubtable2 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->rowWidth = b[0]<<8 | b[1];
v->leftClassOffset = b[2]<<8 | b[3];
v->rightClassOffset = b[4]<<8 | b[5];
v->kerningArrayOffset = b[6]<<8 | b[7];
if(v->leftClassOffset != 0){
if(otfpushrange(o, v->leftClassOffset, -1) < 0)
goto err;
v->leftClass = calloc(1, sizeof(*v->leftClass));
if(read_KernClass(o, v->leftClass) < 0){
werrstr("%s: %r", "leftClass");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->rightClassOffset != 0){
if(otfpushrange(o, v->rightClassOffset, -1) < 0)
goto err;
v->rightClass = calloc(1, sizeof(*v->rightClass));
if(read_KernClass(o, v->rightClass) < 0){
werrstr("%s: %r", "rightClass");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if((b = otfreadn(o, (v->rowWidth/2)*2)) == nil)
goto err;
v->kerningArray = malloc((v->rowWidth/2)*sizeof(*v->kerningArray));
for(int i = 0; i < (v->rowWidth/2); i++)
v->kerningArray[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "KernSubtable2");
return -1;
}
void
print_KernSubtable2(Otfile *f, int indent, Otf *o, KernSubtable2 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "rowWidth", v->rowWidth);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "leftClassOffset", v->leftClassOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "rightClassOffset", v->rightClassOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "kerningArrayOffset", v->kerningArrayOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "leftClass");
if(v->leftClass != nil)
print_KernClass(f, indent+indentΔ, o, v->leftClass);
f->print(f->aux, "%*s%s:\n", indent, "", "rightClass");
if(v->rightClass != nil)
print_KernClass(f, indent+indentΔ, o, v->rightClass);
for(int i = 0; i < (v->rowWidth/2); i++)
f->print(f->aux, "%*s%s[%d]: %d\n", indent, "", "kerningArray", i, v->kerningArray[i]);
USED(o);
}
int
read_KernSubtable(Otf *o, KernSubtable *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
u16int version = b[0]<<8 | b[1];
if(version != 0){
werrstr("%s: invalid value: %d (%#ux)", "version", version, version);
goto err;
}
v->length = b[2]<<8 | b[3];
if(v->length < 6){
werrstr("%s: invalid value: %d (%#ux)", "length", v->length, v->length);
goto err;
}
v->coverage = b[4]<<8 | b[5];
return 0;
err:
werrstr("%s: %r", "KernSubtable");
return -1;
}
void
print_KernSubtable(Otfile *f, int indent, Otf *o, KernSubtable *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "coverage", v->coverage);
USED(o);
}
int
read_TableKern(Otf *o, TableKern *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
u16int version = b[0]<<8 | b[1];
if(version != 0){
werrstr("%s: invalid value: %d (%#ux)", "version", version, version);
goto err;
}
v->nTables = b[2]<<8 | b[3];
if(otfarray(o, &v->subtables, read_KernSubtable, sizeof(KernSubtable), v->nTables) < 0){
werrstr("%s: %r", "subtables");
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableKern");
return -1;
}
void
print_TableKern(Otfile *f, int indent, Otf *o, TableKern *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "nTables", v->nTables);
for(int i = 0; i < v->nTables; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "subtables", i);
print_KernSubtable(f, indent+indentΔ, o, &v->subtables[i]);
}
USED(o);
}
int
read_TableLoca(Otf *o, TableLoca *v)
{
u8int *b = nil; USED(b);
if(o->indexToLocFormat == 0){
if((b = otfreadn(o, (o->numGlyphs+1)*2)) == nil)
goto err;
v->shortOffsets = malloc((o->numGlyphs+1)*sizeof(*v->shortOffsets));
for(int i = 0; i < (o->numGlyphs+1); i++)
v->shortOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
}
if(o->indexToLocFormat == 1){
if((b = otfreadn(o, (o->numGlyphs+1)*4)) == nil)
goto err;
v->longOffsets = malloc((o->numGlyphs+1)*sizeof(*v->longOffsets));
for(int i = 0; i < (o->numGlyphs+1); i++)
v->longOffsets[i] = b[0+i*4]<<24 | b[1+i*4]<<16 | b[2+i*4]<<8 | b[3+i*4];
}
return 0;
err:
werrstr("%s: %r", "TableLoca");
return -1;
}
void
print_TableLoca(Otfile *f, int indent, Otf *o, TableLoca *v)
{
if(o->indexToLocFormat == 0){
for(int i = 0; i < (o->numGlyphs+1); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "shortOffsets", i, v->shortOffsets[i]);
}
if(o->indexToLocFormat == 1){
for(int i = 0; i < (o->numGlyphs+1); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "longOffsets", i, v->longOffsets[i]);
}
USED(o);
}
int
read_VariationAxisRecord(Otf *o, VariationAxisRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 20)) == nil)
goto err;
v->axisTag = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->minValue = (b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7])/65536.0f;
v->defaultValue = (b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11])/65536.0f;
v->maxValue = (b[12]<<24 | b[13]<<16 | b[14]<<8 | b[15])/65536.0f;
v->flags = b[16]<<8 | b[17];
v->axisNameID = b[18]<<8 | b[19];
return 0;
err:
werrstr("%s: %r", "VariationAxisRecord");
return -1;
}
void
print_VariationAxisRecord(Otfile *f, int indent, Otf *o, VariationAxisRecord *v)
{
f->print(f->aux, "%*s%s: %c%c%c%c\n", indent, "", "axisTag", v->axisTag>>24, v->axisTag>>16, v->axisTag>>8, v->axisTag>>0);
f->print(f->aux, "%*s%s: %g\n", indent, "", "minValue", v->minValue);
f->print(f->aux, "%*s%s: %g\n", indent, "", "defaultValue", v->defaultValue);
f->print(f->aux, "%*s%s: %g\n", indent, "", "maxValue", v->maxValue);
f->print(f->aux, "%*s%s: %#ux%s\n", indent, "", "flags", v->flags, (v->flags&VARIATIONAXISRECORD_FL_HIDDEN_AXIS)?" VARIATIONAXISRECORD_FL_HIDDEN_AXIS":"");
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisNameID", v->axisNameID);
USED(o);
}
int
read_UserTuple(Otf *o, UserTuple *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, o->axisCount*4)) == nil)
goto err;
v->coordinates = malloc(o->axisCount*sizeof(*v->coordinates));
for(int i = 0; i < o->axisCount; i++)
v->coordinates[i] = (b[0+i*4]<<24 | b[1+i*4]<<16 | b[2+i*4]<<8 | b[3+i*4])/65536.0f;
return 0;
err:
werrstr("%s: %r", "UserTuple");
return -1;
}
void
print_UserTuple(Otfile *f, int indent, Otf *o, UserTuple *v)
{
for(int i = 0; i < o->axisCount; i++)
f->print(f->aux, "%*s%s[%d]: %g\n", indent, "", "coordinates", i, v->coordinates[i]);
USED(o);
}
int
read_InstanceRecord(Otf *o, InstanceRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->subfamilyNameID = b[0]<<8 | b[1];
if(read_UserTuple(o, &v->coordinates) < 0){
werrstr("%s: %r", "coordinates");
goto err;
}
if((o->instanceSize==((o->axisCount*4)+6))){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->postScriptNameID = b[0]<<8 | b[1];
}
return 0;
err:
werrstr("%s: %r", "InstanceRecord");
return -1;
}
void
print_InstanceRecord(Otfile *f, int indent, Otf *o, InstanceRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "subfamilyNameID", v->subfamilyNameID);
f->print(f->aux, "%*s%s:\n", indent, "", "coordinates");
print_UserTuple(f, indent+indentΔ, o, &v->coordinates);
if((o->instanceSize==((o->axisCount*4)+6)))
f->print(f->aux, "%*s%s: %ud\n", indent, "", "postScriptNameID", v->postScriptNameID);
USED(o);
}
int
read_AxisInstances(Otf *o, AxisInstances *v)
{
u8int *b = nil; USED(b);
if(otfarray(o, &v->axes, read_VariationAxisRecord, sizeof(VariationAxisRecord), o->axisCount) < 0){
werrstr("%s: %r", "axes");
goto err;
}
if(otfarray(o, &v->instaces, read_InstanceRecord, sizeof(InstanceRecord), o->instanceCount) < 0){
werrstr("%s: %r", "instaces");
goto err;
}
return 0;
err:
werrstr("%s: %r", "AxisInstances");
return -1;
}
void
print_AxisInstances(Otfile *f, int indent, Otf *o, AxisInstances *v)
{
for(int i = 0; i < o->axisCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "axes", i);
print_VariationAxisRecord(f, indent+indentΔ, o, &v->axes[i]);
}
for(int i = 0; i < o->instanceCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "instaces", i);
print_InstanceRecord(f, indent+indentΔ, o, &v->instaces[i]);
}
USED(o);
}
int
read_TableFvar(Otf *o, TableFvar *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 16)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
u16int minorVersion = b[2]<<8 | b[3];
if(minorVersion != 0){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", minorVersion, minorVersion);
goto err;
}
v->axesArrayOffset = b[4]<<8 | b[5];
v->axisCount = b[8]<<8 | b[9];
o->axisCount = v->axisCount;
u16int axisSize = b[10]<<8 | b[11];
if(axisSize != 20){
werrstr("%s: invalid value: %d (%#ux)", "axisSize", axisSize, axisSize);
goto err;
}
v->instanceCount = b[12]<<8 | b[13];
o->instanceCount = v->instanceCount;
v->instanceSize = b[14]<<8 | b[15];
o->instanceSize = v->instanceSize;
if(v->axesArrayOffset != 0){
if(otfpushrange(o, v->axesArrayOffset, -1) < 0)
goto err;
v->axisInstances = calloc(1, sizeof(*v->axisInstances));
if(read_AxisInstances(o, v->axisInstances) < 0){
werrstr("%s: %r", "axisInstances");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableFvar");
return -1;
}
void
print_TableFvar(Otfile *f, int indent, Otf *o, TableFvar *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axesArrayOffset", v->axesArrayOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisCount", v->axisCount);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "instanceCount", v->instanceCount);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "instanceSize", v->instanceSize);
f->print(f->aux, "%*s%s:\n", indent, "", "axisInstances");
if(v->axisInstances != nil)
print_AxisInstances(f, indent+indentΔ, o, v->axisInstances);
USED(o);
}
int
read_RegionAxisCoordinates(Otf *o, RegionAxisCoordinates *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->startCoord = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
v->peakCoord = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
v->endCoord = (b[4]<<8 | b[5]>>14)+(b[4]<<8 | b[5]&((1<<14)-1))/16384.0;
return 0;
err:
werrstr("%s: %r", "RegionAxisCoordinates");
return -1;
}
void
print_RegionAxisCoordinates(Otfile *f, int indent, Otf *o, RegionAxisCoordinates *v)
{
f->print(f->aux, "%*s%s: %g\n", indent, "", "startCoord", v->startCoord);
f->print(f->aux, "%*s%s: %g\n", indent, "", "peakCoord", v->peakCoord);
f->print(f->aux, "%*s%s: %g\n", indent, "", "endCoord", v->endCoord);
USED(o);
}
int
read_VariationRegion(Otf *o, VariationRegion *v)
{
u8int *b = nil; USED(b);
if(otfarray(o, &v->regionAxes, read_RegionAxisCoordinates, sizeof(RegionAxisCoordinates), o->axisCount) < 0){
werrstr("%s: %r", "regionAxes");
goto err;
}
return 0;
err:
werrstr("%s: %r", "VariationRegion");
return -1;
}
void
print_VariationRegion(Otfile *f, int indent, Otf *o, VariationRegion *v)
{
for(int i = 0; i < o->axisCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "regionAxes", i);
print_RegionAxisCoordinates(f, indent+indentΔ, o, &v->regionAxes[i]);
}
USED(o);
}
int
read_VariationRegionList(Otf *o, VariationRegionList *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->axisCount = b[0]<<8 | b[1];
v->regionCount = b[2]<<8 | b[3];
if(otfarray(o, &v->variationRegion, read_VariationRegion, sizeof(VariationRegion), v->regionCount) < 0){
werrstr("%s: %r", "variationRegion");
goto err;
}
return 0;
err:
werrstr("%s: %r", "VariationRegionList");
return -1;
}
void
print_VariationRegionList(Otfile *f, int indent, Otf *o, VariationRegionList *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisCount", v->axisCount);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "regionCount", v->regionCount);
for(int i = 0; i < v->regionCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "variationRegion", i);
print_VariationRegion(f, indent+indentΔ, o, &v->variationRegion[i]);
}
USED(o);
}
int
read_ItemVariationData(Otf *o, ItemVariationData *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 6)) == nil)
goto err;
v->itemCount = b[0]<<8 | b[1];
v->wordDeltaCount = b[2]<<8 | b[3];
v->regionIndexCount = b[4]<<8 | b[5];
if((b = otfreadn(o, v->regionIndexCount*2)) == nil)
goto err;
v->regionIndexes = malloc(v->regionIndexCount*sizeof(*v->regionIndexes));
for(int i = 0; i < v->regionIndexCount; i++)
v->regionIndexes[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "ItemVariationData");
return -1;
}
void
print_ItemVariationData(Otfile *f, int indent, Otf *o, ItemVariationData *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "itemCount", v->itemCount);
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "wordDeltaCount", v->wordDeltaCount);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "regionIndexCount", v->regionIndexCount);
for(int i = 0; i < v->regionIndexCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "regionIndexes", i, v->regionIndexes[i]);
USED(o);
}
int
read_ItemVariationStore(Otf *o, ItemVariationStore *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
u16int format = b[0]<<8 | b[1];
if(format != 1){
werrstr("%s: invalid value: %d (%#ux)", "format", format, format);
goto err;
}
v->variationRegionListOffset = b[2]<<24 | b[3]<<16 | b[4]<<8 | b[5];
v->itemVariationDataCount = b[6]<<8 | b[7];
if((b = otfreadn(o, v->itemVariationDataCount*4)) == nil)
goto err;
v->itemVariationDataOffsets = malloc(v->itemVariationDataCount*sizeof(*v->itemVariationDataOffsets));
for(int i = 0; i < v->itemVariationDataCount; i++)
v->itemVariationDataOffsets[i] = b[0+i*4]<<24 | b[1+i*4]<<16 | b[2+i*4]<<8 | b[3+i*4];
return 0;
err:
werrstr("%s: %r", "ItemVariationStore");
return -1;
}
void
print_ItemVariationStore(Otfile *f, int indent, Otf *o, ItemVariationStore *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "variationRegionListOffset", v->variationRegionListOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "itemVariationDataCount", v->itemVariationDataCount);
for(int i = 0; i < v->itemVariationDataCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "itemVariationDataOffsets", i, v->itemVariationDataOffsets[i]);
USED(o);
}
int
read_DeltaSetIndexMap(Otf *o, DeltaSetIndexMap *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->format = b[0];
if(v->format != 0 && v->format != 1){
werrstr("%s: invalid value: %d (%#ux)", "format", v->format, v->format);
goto err;
}
v->entryFormat = b[1];
if(v->format == 0){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->mapCount0 = b[0]<<8 | b[1];
}
if(v->format == 1){
if((b = otfreadn(o, 4)) == nil)
goto err;
v->mapCount1 = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
}
if((b = otfreadn(o, 1)) == nil)
goto err;
v->mapData = b[0];
return 0;
err:
werrstr("%s: %r", "DeltaSetIndexMap");
return -1;
}
void
print_DeltaSetIndexMap(Otfile *f, int indent, Otf *o, DeltaSetIndexMap *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "format", v->format);
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "entryFormat", v->entryFormat);
if(v->format == 0)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mapCount0", v->mapCount0);
if(v->format == 1)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mapCount1", v->mapCount1);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "mapData", v->mapData);
USED(o);
}
int
read_TableHVAR(Otf *o, TableHVAR *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 20)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
u16int minorVersion = b[2]<<8 | b[3];
if(minorVersion != 0){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", minorVersion, minorVersion);
goto err;
}
v->itemVariationStoreOffset = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
v->advanceWidthMappingOffset = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11];
v->lsbMappingOffset = b[12]<<24 | b[13]<<16 | b[14]<<8 | b[15];
v->rsbMappingOffset = b[16]<<24 | b[17]<<16 | b[18]<<8 | b[19];
if(v->itemVariationStoreOffset != 0){
if(otfpushrange(o, v->itemVariationStoreOffset, -1) < 0)
goto err;
v->itemVariationStore = calloc(1, sizeof(*v->itemVariationStore));
if(read_ItemVariationStore(o, v->itemVariationStore) < 0){
werrstr("%s: %r", "itemVariationStore");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->advanceWidthMappingOffset != 0){
if(otfpushrange(o, v->advanceWidthMappingOffset, -1) < 0)
goto err;
v->advanceWidthMapping = calloc(1, sizeof(*v->advanceWidthMapping));
if(read_DeltaSetIndexMap(o, v->advanceWidthMapping) < 0){
werrstr("%s: %r", "advanceWidthMapping");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->lsbMappingOffset != 0){
if(otfpushrange(o, v->lsbMappingOffset, -1) < 0)
goto err;
v->lsbMapping = calloc(1, sizeof(*v->lsbMapping));
if(read_DeltaSetIndexMap(o, v->lsbMapping) < 0){
werrstr("%s: %r", "lsbMapping");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
if(v->rsbMappingOffset != 0){
if(otfpushrange(o, v->rsbMappingOffset, -1) < 0)
goto err;
v->rsbMapping = calloc(1, sizeof(*v->rsbMapping));
if(read_DeltaSetIndexMap(o, v->rsbMapping) < 0){
werrstr("%s: %r", "rsbMapping");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableHVAR");
return -1;
}
void
print_TableHVAR(Otfile *f, int indent, Otf *o, TableHVAR *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "itemVariationStoreOffset", v->itemVariationStoreOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "advanceWidthMappingOffset", v->advanceWidthMappingOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lsbMappingOffset", v->lsbMappingOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "rsbMappingOffset", v->rsbMappingOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "itemVariationStore");
if(v->itemVariationStore != nil)
print_ItemVariationStore(f, indent+indentΔ, o, v->itemVariationStore);
f->print(f->aux, "%*s%s:\n", indent, "", "advanceWidthMapping");
if(v->advanceWidthMapping != nil)
print_DeltaSetIndexMap(f, indent+indentΔ, o, v->advanceWidthMapping);
f->print(f->aux, "%*s%s:\n", indent, "", "lsbMapping");
if(v->lsbMapping != nil)
print_DeltaSetIndexMap(f, indent+indentΔ, o, v->lsbMapping);
f->print(f->aux, "%*s%s:\n", indent, "", "rsbMapping");
if(v->rsbMapping != nil)
print_DeltaSetIndexMap(f, indent+indentΔ, o, v->rsbMapping);
USED(o);
}
int
read_TableFFTM(Otf *o, TableFFTM *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->version = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(v->version == 1){
if((b = otfreadn(o, 24)) == nil)
goto err;
v->fontforge = ((s64int)b[0]<<56 | (s64int)b[1]<<48 | (s64int)b[2]<<40 | (s64int)b[3]<<32 | b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7]) - 2082844800LL;
v->created = ((s64int)b[8]<<56 | (s64int)b[9]<<48 | (s64int)b[10]<<40 | (s64int)b[11]<<32 | b[12]<<24 | b[13]<<16 | b[14]<<8 | b[15]) - 2082844800LL;
v->modified = ((s64int)b[16]<<56 | (s64int)b[17]<<48 | (s64int)b[18]<<40 | (s64int)b[19]<<32 | b[20]<<24 | b[21]<<16 | b[22]<<8 | b[23]) - 2082844800LL;
}
return 0;
err:
werrstr("%s: %r", "TableFFTM");
return -1;
}
void
print_TableFFTM(Otfile *f, int indent, Otf *o, TableFFTM *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "version", v->version);
if(v->version == 1)
f->print(f->aux, "%*s%s: %τ\n", indent, "", "fontforge", fmttime(v->fontforge));
if(v->version == 1)
f->print(f->aux, "%*s%s: %τ\n", indent, "", "created", fmttime(v->created));
if(v->version == 1)
f->print(f->aux, "%*s%s: %τ\n", indent, "", "modified", fmttime(v->modified));
USED(o);
}
int
read_SignatureBlock1(Otf *o, SignatureBlock1 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->signatureLength = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
if((b = otfreadn(o, v->signatureLength*1)) == nil)
goto err;
v->signature = malloc(v->signatureLength*sizeof(*v->signature));
for(int i = 0; i < v->signatureLength; i++)
v->signature[i] = b[0+i*1];
return 0;
err:
werrstr("%s: %r", "SignatureBlock1");
return -1;
}
void
print_SignatureBlock1(Otfile *f, int indent, Otf *o, SignatureBlock1 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "signatureLength", v->signatureLength);
for(int i = 0; i < v->signatureLength; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "signature", i, v->signature[i]);
USED(o);
}
int
read_SignatureRecord(Otf *o, SignatureRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 12)) == nil)
goto err;
v->format = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->length = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
v->signatureBlockOffset = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11];
if(v->format == 1){
if(v->signatureBlockOffset != 0){
if(otfpushrange(o, v->signatureBlockOffset, -1) < 0)
goto err;
v->signatureBlock1 = calloc(1, sizeof(*v->signatureBlock1));
if(read_SignatureBlock1(o, v->signatureBlock1) < 0){
werrstr("%s: %r", "signatureBlock1");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
}
return 0;
err:
werrstr("%s: %r", "SignatureRecord");
return -1;
}
void
print_SignatureRecord(Otfile *f, int indent, Otf *o, SignatureRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "format", v->format);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "signatureBlockOffset", v->signatureBlockOffset);
if(v->format == 1){
f->print(f->aux, "%*s%s:\n", indent, "", "signatureBlock1");
if(v->signatureBlock1 != nil)
print_SignatureBlock1(f, indent+indentΔ, o, v->signatureBlock1);
}
USED(o);
}
int
read_TableDSIG(Otf *o, TableDSIG *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
u32int version = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(version != 1){
werrstr("%s: invalid value: %d (%#ux)", "version", version, version);
goto err;
}
v->numSignatures = b[4]<<8 | b[5];
v->flags = b[6]<<8 | b[7];
if(otfarray(o, &v->signatureRecords, read_SignatureRecord, sizeof(SignatureRecord), v->numSignatures) < 0){
werrstr("%s: %r", "signatureRecords");
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableDSIG");
return -1;
}
void
print_TableDSIG(Otfile *f, int indent, Otf *o, TableDSIG *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numSignatures", v->numSignatures);
f->print(f->aux, "%*s%s: %#ux%s\n", indent, "", "flags", v->flags, (v->flags&DSIG_CANNOT_BE_RESIGNED)?" DSIG_CANNOT_BE_RESIGNED":"");
for(int i = 0; i < v->numSignatures; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "signatureRecords", i);
print_SignatureRecord(f, indent+indentΔ, o, &v->signatureRecords[i]);
}
USED(o);
}
int
read_AxisRecord(Otf *o, AxisRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
v->axisTag = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->axisNameID = b[4]<<8 | b[5];
v->axisOrdering = b[6]<<8 | b[7];
if((b = otfreadn(o, (o->designAxisSize-8)*1)) == nil)
goto err;
USED(b);
return 0;
err:
werrstr("%s: %r", "AxisRecord");
return -1;
}
void
print_AxisRecord(Otfile *f, int indent, Otf *o, AxisRecord *v)
{
f->print(f->aux, "%*s%s: %c%c%c%c\n", indent, "", "axisTag", v->axisTag>>24, v->axisTag>>16, v->axisTag>>8, v->axisTag>>0);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisNameID", v->axisNameID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisOrdering", v->axisOrdering);
USED(o);
}
int
read_DesignAxes(Otf *o, DesignAxes *v)
{
u8int *b = nil; USED(b);
if(otfarray(o, &v->designAxes, read_AxisRecord, sizeof(AxisRecord), o->designAxisCount) < 0){
werrstr("%s: %r", "designAxes");
goto err;
}
if((b = otfreadn(o, o->axisValueCount*2)) == nil)
goto err;
v->axisValueOffsets = malloc(o->axisValueCount*sizeof(*v->axisValueOffsets));
for(int i = 0; i < o->axisValueCount; i++)
v->axisValueOffsets[i] = b[0+i*2]<<8 | b[1+i*2];
return 0;
err:
werrstr("%s: %r", "DesignAxes");
return -1;
}
void
print_DesignAxes(Otfile *f, int indent, Otf *o, DesignAxes *v)
{
for(int i = 0; i < o->designAxisCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "designAxes", i);
print_AxisRecord(f, indent+indentΔ, o, &v->designAxes[i]);
}
for(int i = 0; i < o->axisValueCount; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "axisValueOffsets", i, v->axisValueOffsets[i]);
USED(o);
}
int
read_TableSTAT(Otf *o, TableSTAT *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 18)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
v->minorVersion = b[2]<<8 | b[3];
if(v->minorVersion != 0 && v->minorVersion != 1 && v->minorVersion != 2){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", v->minorVersion, v->minorVersion);
goto err;
}
v->designAxisSize = b[4]<<8 | b[5];
o->designAxisSize = v->designAxisSize;
v->designAxisCount = b[6]<<8 | b[7];
o->designAxisCount = v->designAxisCount;
v->designAxesOffset = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11];
v->axisValueCount = b[12]<<8 | b[13];
o->axisValueCount = v->axisValueCount;
v->offsetToAxisValueOffsets = b[14]<<24 | b[15]<<16 | b[16]<<8 | b[17];
if(v->minorVersion > 0){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->elidedFallbackNameID = b[0]<<8 | b[1];
}
if(v->designAxesOffset != 0){
if(otfpushrange(o, v->designAxesOffset, -1) < 0)
goto err;
v->designAxes = calloc(1, sizeof(*v->designAxes));
if(read_DesignAxes(o, v->designAxes) < 0){
werrstr("%s: %r", "designAxes");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableSTAT");
return -1;
}
void
print_TableSTAT(Otfile *f, int indent, Otf *o, TableSTAT *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "designAxisSize", v->designAxisSize);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "designAxisCount", v->designAxisCount);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "designAxesOffset", v->designAxesOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisValueCount", v->axisValueCount);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "offsetToAxisValueOffsets", v->offsetToAxisValueOffsets);
if(v->minorVersion > 0)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "elidedFallbackNameID", v->elidedFallbackNameID);
f->print(f->aux, "%*s%s:\n", indent, "", "designAxes");
if(v->designAxes != nil)
print_DesignAxes(f, indent+indentΔ, o, v->designAxes);
USED(o);
}
int
read_GaspRange(Otf *o, GaspRange *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->rangeMaxPPEM = b[0]<<8 | b[1];
v->rangeGaspBehavior = b[2]<<8 | b[3];
return 0;
err:
werrstr("%s: %r", "GaspRange");
return -1;
}
void
print_GaspRange(Otfile *f, int indent, Otf *o, GaspRange *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "rangeMaxPPEM", v->rangeMaxPPEM);
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "rangeGaspBehavior", v->rangeGaspBehavior);
USED(o);
}
int
read_TableGasp(Otf *o, TableGasp *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->version = b[0]<<8 | b[1];
if(v->version != 0 && v->version != 1){
werrstr("%s: invalid value: %d (%#ux)", "version", v->version, v->version);
goto err;
}
v->numRanges = b[2]<<8 | b[3];
if(otfarray(o, &v->gaspRanges, read_GaspRange, sizeof(GaspRange), v->numRanges) < 0){
werrstr("%s: %r", "gaspRanges");
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableGasp");
return -1;
}
void
print_TableGasp(Otfile *f, int indent, Otf *o, TableGasp *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "version", v->version);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numRanges", v->numRanges);
for(int i = 0; i < v->numRanges; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "gaspRanges", i);
print_GaspRange(f, indent+indentΔ, o, &v->gaspRanges[i]);
}
USED(o);
}
int
read_Tuple(Otf *o, Tuple *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, o->axisCount*2)) == nil)
goto err;
v->coordinates = malloc(o->axisCount*sizeof(*v->coordinates));
for(int i = 0; i < o->axisCount; i++)
v->coordinates[i] = (b[0+i*2]<<8 | b[1+i*2]>>14)+(b[0+i*2]<<8 | b[1+i*2]&((1<<14)-1))/16384.0;
return 0;
err:
werrstr("%s: %r", "Tuple");
return -1;
}
void
print_Tuple(Otfile *f, int indent, Otf *o, Tuple *v)
{
for(int i = 0; i < o->axisCount; i++)
f->print(f->aux, "%*s%s[%d]: %g\n", indent, "", "coordinates", i, v->coordinates[i]);
USED(o);
}
int
read_TupleVariationHeader(Otf *o, TupleVariationHeader *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->variationDataSize = b[0]<<8 | b[1];
v->tupleIndex = b[2]<<8 | b[3];
if(read_Tuple(o, &v->peakTuple) < 0){
werrstr("%s: %r", "peakTuple");
goto err;
}
if(read_Tuple(o, &v->intermediateStartTuple) < 0){
werrstr("%s: %r", "intermediateStartTuple");
goto err;
}
if(read_Tuple(o, &v->intermediateEndTuple) < 0){
werrstr("%s: %r", "intermediateEndTuple");
goto err;
}
return 0;
err:
werrstr("%s: %r", "TupleVariationHeader");
return -1;
}
void
print_TupleVariationHeader(Otfile *f, int indent, Otf *o, TupleVariationHeader *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "variationDataSize", v->variationDataSize);
f->print(f->aux, "%*s%s: %ud%s%s%s\n", indent, "", "tupleIndex", v->tupleIndex, (v->tupleIndex&TUPLEINDEX_FL_PRIVATE_POINT_NUMBERS)?" TUPLEINDEX_FL_PRIVATE_POINT_NUMBERS":"", (v->tupleIndex&TUPLEINDEX_FL_INTERMEDIATE_REGION)?" TUPLEINDEX_FL_INTERMEDIATE_REGION":"", (v->tupleIndex&TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE)?" TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE":"");
f->print(f->aux, "%*s%s:\n", indent, "", "peakTuple");
print_Tuple(f, indent+indentΔ, o, &v->peakTuple);
f->print(f->aux, "%*s%s:\n", indent, "", "intermediateStartTuple");
print_Tuple(f, indent+indentΔ, o, &v->intermediateStartTuple);
f->print(f->aux, "%*s%s:\n", indent, "", "intermediateEndTuple");
print_Tuple(f, indent+indentΔ, o, &v->intermediateEndTuple);
USED(o);
}
int
read_GlyphVariationData(Otf *o, GlyphVariationData *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->tupleVariationCount = b[0]<<8 | b[1];
v->dataOffset = b[2]<<8 | b[3];
if(otfarray(o, &v->tupleVariationHeaders, read_TupleVariationHeader, sizeof(TupleVariationHeader), (v->tupleVariationCount&4095)) < 0){
werrstr("%s: %r", "tupleVariationHeaders");
goto err;
}
return 0;
err:
werrstr("%s: %r", "GlyphVariationData");
return -1;
}
void
print_GlyphVariationData(Otfile *f, int indent, Otf *o, GlyphVariationData *v)
{
f->print(f->aux, "%*s%s: %ud%s\n", indent, "", "tupleVariationCount", v->tupleVariationCount, (v->tupleVariationCount&COUNT_FL_SHARED_POINT_NUMBERS)?" COUNT_FL_SHARED_POINT_NUMBERS":"");
f->print(f->aux, "%*s%s: %ud\n", indent, "", "dataOffset", v->dataOffset);
for(int i = 0; i < (v->tupleVariationCount&4095); i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "tupleVariationHeaders", i);
print_TupleVariationHeader(f, indent+indentΔ, o, &v->tupleVariationHeaders[i]);
}
USED(o);
}
int
read_TableGvar(Otf *o, TableGvar *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 20)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
u16int minorVersion = b[2]<<8 | b[3];
if(minorVersion != 0){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", minorVersion, minorVersion);
goto err;
}
v->axisCount = b[4]<<8 | b[5];
v->sharedTupleCount = b[6]<<8 | b[7];
v->sharedTuplesOffset = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11];
v->glyphCount = b[12]<<8 | b[13];
v->flags = b[14]<<8 | b[15];
v->glyphVariationDataArrayOffset = b[16]<<24 | b[17]<<16 | b[18]<<8 | b[19];
if((v->flags&GVAR_FL_LONG_OFFSETS) == 0){
if((b = otfreadn(o, (v->glyphCount+1)*2)) == nil)
goto err;
v->glyphVariationDataOffsetsShort = malloc((v->glyphCount+1)*sizeof(*v->glyphVariationDataOffsetsShort));
for(int i = 0; i < (v->glyphCount+1); i++)
v->glyphVariationDataOffsetsShort[i] = b[0+i*2]<<8 | b[1+i*2];
}
if((v->flags&GVAR_FL_LONG_OFFSETS) != 0){
if((b = otfreadn(o, (v->glyphCount+1)*4)) == nil)
goto err;
v->glyphVariationDataOffsetsLong = malloc((v->glyphCount+1)*sizeof(*v->glyphVariationDataOffsetsLong));
for(int i = 0; i < (v->glyphCount+1); i++)
v->glyphVariationDataOffsetsLong[i] = b[0+i*4]<<24 | b[1+i*4]<<16 | b[2+i*4]<<8 | b[3+i*4];
}
if(v->sharedTuplesOffset != 0){
if(otfpushrange(o, v->sharedTuplesOffset, -1) < 0)
goto err;
if(otfarray(o, &v->sharedTuples, read_Tuple, sizeof(Tuple), v->sharedTupleCount) < 0){
werrstr("%s: %r", "sharedTuples");
goto err;
}
if(otfpoprange(o) < 0)
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableGvar");
return -1;
}
void
print_TableGvar(Otfile *f, int indent, Otf *o, TableGvar *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisCount", v->axisCount);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "sharedTupleCount", v->sharedTupleCount);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "sharedTuplesOffset", v->sharedTuplesOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphCount", v->glyphCount);
f->print(f->aux, "%*s%s: %#ux%s\n", indent, "", "flags", v->flags, (v->flags&GVAR_FL_LONG_OFFSETS)?" GVAR_FL_LONG_OFFSETS":"");
f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphVariationDataArrayOffset", v->glyphVariationDataArrayOffset);
if((v->flags&GVAR_FL_LONG_OFFSETS) == 0){
for(int i = 0; i < (v->glyphCount+1); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "glyphVariationDataOffsetsShort", i, v->glyphVariationDataOffsetsShort[i]);
}
if((v->flags&GVAR_FL_LONG_OFFSETS) != 0){
for(int i = 0; i < (v->glyphCount+1); i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "glyphVariationDataOffsetsLong", i, v->glyphVariationDataOffsetsLong[i]);
}
for(int i = 0; i < v->sharedTupleCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "sharedTuples", i);
print_Tuple(f, indent+indentΔ, o, &v->sharedTuples[i]);
}
USED(o);
}
int
read_AxisValueMap(Otf *o, AxisValueMap *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 4)) == nil)
goto err;
v->fromCoordinate = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
v->toCoordinate = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
return 0;
err:
werrstr("%s: %r", "AxisValueMap");
return -1;
}
void
print_AxisValueMap(Otfile *f, int indent, Otf *o, AxisValueMap *v)
{
f->print(f->aux, "%*s%s: %g\n", indent, "", "fromCoordinate", v->fromCoordinate);
f->print(f->aux, "%*s%s: %g\n", indent, "", "toCoordinate", v->toCoordinate);
USED(o);
}
int
read_SegmentMaps(Otf *o, SegmentMaps *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 2)) == nil)
goto err;
v->positionMapCount = b[0]<<8 | b[1];
if(otfarray(o, &v->axisValueMaps, read_AxisValueMap, sizeof(AxisValueMap), v->positionMapCount) < 0){
werrstr("%s: %r", "axisValueMaps");
goto err;
}
return 0;
err:
werrstr("%s: %r", "SegmentMaps");
return -1;
}
void
print_SegmentMaps(Otfile *f, int indent, Otf *o, SegmentMaps *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "positionMapCount", v->positionMapCount);
for(int i = 0; i < v->positionMapCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "axisValueMaps", i);
print_AxisValueMap(f, indent+indentΔ, o, &v->axisValueMaps[i]);
}
USED(o);
}
int
read_TableAvar(Otf *o, TableAvar *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 8)) == nil)
goto err;
u16int majorVersion = b[0]<<8 | b[1];
if(majorVersion != 1){
werrstr("%s: invalid value: %d (%#ux)", "majorVersion", majorVersion, majorVersion);
goto err;
}
u16int minorVersion = b[2]<<8 | b[3];
if(minorVersion != 0){
werrstr("%s: invalid value: %d (%#ux)", "minorVersion", minorVersion, minorVersion);
goto err;
}
v->axisCount = b[6]<<8 | b[7];
if(otfarray(o, &v->axisSegmentMaps, read_SegmentMaps, sizeof(SegmentMaps), v->axisCount) < 0){
werrstr("%s: %r", "axisSegmentMaps");
goto err;
}
return 0;
err:
werrstr("%s: %r", "TableAvar");
return -1;
}
void
print_TableAvar(Otfile *f, int indent, Otf *o, TableAvar *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisCount", v->axisCount);
for(int i = 0; i < v->axisCount; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "axisSegmentMaps", i);
print_SegmentMaps(f, indent+indentΔ, o, &v->axisSegmentMaps[i]);
}
USED(o);
}
int
read_TableOS∕2(Otf *o, TableOS∕2 *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 78)) == nil)
goto err;
v->version = b[0]<<8 | b[1];
if(v->version > 5){
werrstr("%s: invalid value: %d (%#ux)", "version", v->version, v->version);
goto err;
}
v->xAvgCharWidth = b[2]<<8 | b[3];
v->usWeightClass = b[4]<<8 | b[5];
v->usWidthClass = b[6]<<8 | b[7];
v->fsType = b[8]<<8 | b[9];
v->ySubscriptXSize = b[10]<<8 | b[11];
v->ySubscriptYSize = b[12]<<8 | b[13];
v->ySubscriptXOffset = b[14]<<8 | b[15];
v->ySubscriptYOffset = b[16]<<8 | b[17];
v->ySuperscriptXSize = b[18]<<8 | b[19];
v->ySuperscriptYSize = b[20]<<8 | b[21];
v->ySuperscriptXOffset = b[22]<<8 | b[23];
v->ySuperscriptYOffset = b[24]<<8 | b[25];
v->yStrikeoutSize = b[26]<<8 | b[27];
v->yStrikeoutPosition = b[28]<<8 | b[29];
v->sFamilyClass = b[30]<<8 | b[31];
for(int i = 0; i < 10; i++)
v->panose[i] = b[32+i*1];
v->ulUnicodeRange1 = b[42]<<24 | b[43]<<16 | b[44]<<8 | b[45];
v->ulUnicodeRange2 = b[46]<<24 | b[47]<<16 | b[48]<<8 | b[49];
v->ulUnicodeRange3 = b[50]<<24 | b[51]<<16 | b[52]<<8 | b[53];
v->ulUnicodeRange4 = b[54]<<24 | b[55]<<16 | b[56]<<8 | b[57];
v->achVendID = b[58]<<24 | b[59]<<16 | b[60]<<8 | b[61];
v->fsSelection = b[62]<<8 | b[63];
v->usFirstCharIndex = b[64]<<8 | b[65];
v->usLastCharIndex = b[66]<<8 | b[67];
v->sTypoAscender = b[68]<<8 | b[69];
v->sTypoDescender = b[70]<<8 | b[71];
v->sTypoLineGap = b[72]<<8 | b[73];
v->usWinAscent = b[74]<<8 | b[75];
v->usWinDescent = b[76]<<8 | b[77];
if(v->version >= 1){
if((b = otfreadn(o, 8)) == nil)
goto err;
v->ulCodePageRange1 = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->ulCodePageRange2 = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
}
if(v->version >= 2){
if((b = otfreadn(o, 10)) == nil)
goto err;
v->sxHeight = b[0]<<8 | b[1];
v->sCapHeight = b[2]<<8 | b[3];
v->usDefaultChar = b[4]<<8 | b[5];
v->usBreakChar = b[6]<<8 | b[7];
v->usMaxContext = b[8]<<8 | b[9];
}
if(v->version >= 5){
if((b = otfreadn(o, 4)) == nil)
goto err;
v->usLowerOpticalPointSize = b[0]<<8 | b[1];
v->usUpperOpticalPointSize = b[2]<<8 | b[3];
}
return 0;
err:
werrstr("%s: %r", "TableOS∕2");
return -1;
}
void
print_TableOS∕2(Otfile *f, int indent, Otf *o, TableOS∕2 *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "version", v->version);
f->print(f->aux, "%*s%s: %d\n", indent, "", "xAvgCharWidth", v->xAvgCharWidth);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "usWeightClass", v->usWeightClass);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "usWidthClass", v->usWidthClass);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "fsType", v->fsType);
f->print(f->aux, "%*s%s: %d\n", indent, "", "ySubscriptXSize", v->ySubscriptXSize);
f->print(f->aux, "%*s%s: %d\n", indent, "", "ySubscriptYSize", v->ySubscriptYSize);
f->print(f->aux, "%*s%s: %d\n", indent, "", "ySubscriptXOffset", v->ySubscriptXOffset);
f->print(f->aux, "%*s%s: %d\n", indent, "", "ySubscriptYOffset", v->ySubscriptYOffset);
f->print(f->aux, "%*s%s: %d\n", indent, "", "ySuperscriptXSize", v->ySuperscriptXSize);
f->print(f->aux, "%*s%s: %d\n", indent, "", "ySuperscriptYSize", v->ySuperscriptYSize);
f->print(f->aux, "%*s%s: %d\n", indent, "", "ySuperscriptXOffset", v->ySuperscriptXOffset);
f->print(f->aux, "%*s%s: %d\n", indent, "", "ySuperscriptYOffset", v->ySuperscriptYOffset);
f->print(f->aux, "%*s%s: %d\n", indent, "", "yStrikeoutSize", v->yStrikeoutSize);
f->print(f->aux, "%*s%s: %d\n", indent, "", "yStrikeoutPosition", v->yStrikeoutPosition);
f->print(f->aux, "%*s%s: %d\n", indent, "", "sFamilyClass", v->sFamilyClass);
for(int i = 0; i < 10; i++)
f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "panose", i, v->panose[i]);
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "ulUnicodeRange1", v->ulUnicodeRange1);
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "ulUnicodeRange2", v->ulUnicodeRange2);
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "ulUnicodeRange3", v->ulUnicodeRange3);
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "ulUnicodeRange4", v->ulUnicodeRange4);
f->print(f->aux, "%*s%s: %c%c%c%c\n", indent, "", "achVendID", v->achVendID>>24, v->achVendID>>16, v->achVendID>>8, v->achVendID>>0);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "fsSelection", v->fsSelection);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "usFirstCharIndex", v->usFirstCharIndex);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "usLastCharIndex", v->usLastCharIndex);
f->print(f->aux, "%*s%s: %d\n", indent, "", "sTypoAscender", v->sTypoAscender);
f->print(f->aux, "%*s%s: %d\n", indent, "", "sTypoDescender", v->sTypoDescender);
f->print(f->aux, "%*s%s: %d\n", indent, "", "sTypoLineGap", v->sTypoLineGap);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "usWinAscent", v->usWinAscent);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "usWinDescent", v->usWinDescent);
if(v->version >= 1)
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "ulCodePageRange1", v->ulCodePageRange1);
if(v->version >= 1)
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "ulCodePageRange2", v->ulCodePageRange2);
if(v->version >= 2)
f->print(f->aux, "%*s%s: %d\n", indent, "", "sxHeight", v->sxHeight);
if(v->version >= 2)
f->print(f->aux, "%*s%s: %d\n", indent, "", "sCapHeight", v->sCapHeight);
if(v->version >= 2)
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "usDefaultChar", v->usDefaultChar);
if(v->version >= 2)
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "usBreakChar", v->usBreakChar);
if(v->version >= 2)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "usMaxContext", v->usMaxContext);
if(v->version >= 5)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "usLowerOpticalPointSize", v->usLowerOpticalPointSize);
if(v->version >= 5)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "usUpperOpticalPointSize", v->usUpperOpticalPointSize);
USED(o);
}
int
read_TableRecord(Otf *o, TableRecord *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 16)) == nil)
goto err;
v->tableTag = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
v->offset = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11];
v->length = b[12]<<24 | b[13]<<16 | b[14]<<8 | b[15];
return 0;
err:
werrstr("%s: %r", "TableRecord");
return -1;
}
void
print_TableRecord(Otfile *f, int indent, Otf *o, TableRecord *v)
{
f->print(f->aux, "%*s%s: %c%c%c%c\n", indent, "", "tableTag", v->tableTag>>24, v->tableTag>>16, v->tableTag>>8, v->tableTag>>0);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "offset", v->offset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "length", v->length);
if(v->print != nil && v->parsed != nil)
v->print(f, indent+indentΔ, o, v->parsed);
USED(o);
}
int
read_TableDirectory(Otf *o, TableDirectory *v)
{
u8int *b = nil; USED(b);
if((b = otfreadn(o, 12)) == nil)
goto err;
v->sfntVersion = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
if(v->sfntVersion != 0x10000 && v->sfntVersion != 0x4f54544f){
werrstr("%s: invalid value: %d (%#ux)", "sfntVersion", v->sfntVersion, v->sfntVersion);
goto err;
}
v->numTables = b[4]<<8 | b[5];
v->searchRange = b[6]<<8 | b[7];
v->entrySelector = b[8]<<8 | b[9];
v->rangeShift = b[10]<<8 | b[11];
if(otfarray(o, &v->tableRecords, read_TableRecord, sizeof(TableRecord), v->numTables) < 0){
werrstr("%s: %r", "tableRecords");
goto err;
}
int retry = 0;
do{
for(int i = 0; i < v->numTables; i++){
TableRecord *rec = &v->tableRecords[i];
if(rec->length == 0)
continue;
if(otfpushrange(o, rec->offset, rec->length) < 0)
goto err;
switch(rec->tableTag){
case (u32int)('c'<<24|'m'<<16|'a'<<8|'p'):
if(v->cmap != nil)
break;
v->cmap = calloc(1, sizeof(TableCmap));
if(read_TableCmap(o, v->cmap) < 0){
free(v->cmap);
goto err;
}
rec->parsed = v->cmap;
rec->print = (void*)print_TableCmap;
break;
case (u32int)('h'<<24|'e'<<16|'a'<<8|'d'):
if(v->head != nil)
break;
v->head = calloc(1, sizeof(TableHead));
if(read_TableHead(o, v->head) < 0){
free(v->head);
goto err;
}
rec->parsed = v->head;
rec->print = (void*)print_TableHead;
break;
case (u32int)('h'<<24|'h'<<16|'e'<<8|'a'):
if(v->hhea != nil)
break;
v->hhea = calloc(1, sizeof(TableHhea));
if(read_TableHhea(o, v->hhea) < 0){
free(v->hhea);
goto err;
}
rec->parsed = v->hhea;
rec->print = (void*)print_TableHhea;
break;
case (u32int)('m'<<24|'a'<<16|'x'<<8|'p'):
if(v->maxp != nil)
break;
v->maxp = calloc(1, sizeof(TableMaxp));
if(read_TableMaxp(o, v->maxp) < 0){
free(v->maxp);
goto err;
}
rec->parsed = v->maxp;
rec->print = (void*)print_TableMaxp;
break;
case (u32int)('h'<<24|'m'<<16|'t'<<8|'x'):
{
static int retried = 0;
if(v->hhea == nil || v->maxp == nil){
if(retried){
werrstr("%s: deps missing", "TableHmtx");
goto err;
}
retried = 1;
retry++;
break;
}
if(retried)
retry--;
}
if(v->hmtx != nil)
break;
v->hmtx = calloc(1, sizeof(TableHmtx));
if(read_TableHmtx(o, v->hmtx) < 0){
free(v->hmtx);
goto err;
}
rec->parsed = v->hmtx;
rec->print = (void*)print_TableHmtx;
break;
case (u32int)('p'<<24|'o'<<16|'s'<<8|'t'):
if(v->post != nil)
break;
v->post = calloc(1, sizeof(TablePost));
if(read_TablePost(o, v->post) < 0){
free(v->post);
goto err;
}
rec->parsed = v->post;
rec->print = (void*)print_TablePost;
break;
case (u32int)('n'<<24|'a'<<16|'m'<<8|'e'):
if(v->name != nil)
break;
v->name = calloc(1, sizeof(TableName));
if(read_TableName(o, v->name) < 0){
free(v->name);
goto err;
}
rec->parsed = v->name;
rec->print = (void*)print_TableName;
break;
case (u32int)('E'<<24|'B'<<16|'D'<<8|'T'):
if(v->ebdt != nil)
break;
v->ebdt = calloc(1, sizeof(TableEBDT));
if(read_TableEBDT(o, v->ebdt) < 0){
free(v->ebdt);
goto err;
}
rec->parsed = v->ebdt;
rec->print = (void*)print_TableEBDT;
break;
case (u32int)('E'<<24|'B'<<16|'L'<<8|'C'):
if(v->eblc != nil)
break;
v->eblc = calloc(1, sizeof(TableEBLC));
if(read_TableEBLC(o, v->eblc) < 0){
free(v->eblc);
goto err;
}
rec->parsed = v->eblc;
rec->print = (void*)print_TableEBLC;
break;
case (u32int)('G'<<24|'D'<<16|'E'<<8|'F'):
if(v->gdef != nil)
break;
v->gdef = calloc(1, sizeof(TableGDEF));
if(read_TableGDEF(o, v->gdef) < 0){
free(v->gdef);
goto err;
}
rec->parsed = v->gdef;
rec->print = (void*)print_TableGDEF;
break;
case (u32int)('G'<<24|'P'<<16|'O'<<8|'S'):
if(v->gpos != nil)
break;
v->gpos = calloc(1, sizeof(TableGPOS));
if(read_TableGPOS(o, v->gpos) < 0){
free(v->gpos);
goto err;
}
rec->parsed = v->gpos;
rec->print = (void*)print_TableGPOS;
break;
case (u32int)('G'<<24|'S'<<16|'U'<<8|'B'):
if(v->gsub != nil)
break;
v->gsub = calloc(1, sizeof(TableGSUB));
if(read_TableGSUB(o, v->gsub) < 0){
free(v->gsub);
goto err;
}
rec->parsed = v->gsub;
rec->print = (void*)print_TableGSUB;
break;
case (u32int)('M'<<24|'A'<<16|'T'<<8|'H'):
if(v->math != nil)
break;
v->math = calloc(1, sizeof(TableMATH));
if(read_TableMATH(o, v->math) < 0){
free(v->math);
goto err;
}
rec->parsed = v->math;
rec->print = (void*)print_TableMATH;
break;
case (u32int)('k'<<24|'e'<<16|'r'<<8|'n'):
if(v->kern != nil)
break;
v->kern = calloc(1, sizeof(TableKern));
if(read_TableKern(o, v->kern) < 0){
free(v->kern);
goto err;
}
rec->parsed = v->kern;
rec->print = (void*)print_TableKern;
break;
case (u32int)('l'<<24|'o'<<16|'c'<<8|'a'):
{
static int retried = 0;
if(v->head == nil || v->maxp == nil){
if(retried){
werrstr("%s: deps missing", "TableLoca");
goto err;
}
retried = 1;
retry++;
break;
}
if(retried)
retry--;
}
if(v->loca != nil)
break;
v->loca = calloc(1, sizeof(TableLoca));
if(read_TableLoca(o, v->loca) < 0){
free(v->loca);
goto err;
}
rec->parsed = v->loca;
rec->print = (void*)print_TableLoca;
break;
case (u32int)('f'<<24|'v'<<16|'a'<<8|'r'):
if(v->fvar != nil)
break;
v->fvar = calloc(1, sizeof(TableFvar));
if(read_TableFvar(o, v->fvar) < 0){
free(v->fvar);
goto err;
}
rec->parsed = v->fvar;
rec->print = (void*)print_TableFvar;
break;
case (u32int)('H'<<24|'V'<<16|'A'<<8|'R'):
{
static int retried = 0;
if(v->fvar == nil){
if(retried){
werrstr("%s: deps missing", "TableHVAR");
goto err;
}
retried = 1;
retry++;
break;
}
if(retried)
retry--;
}
if(v->hvar != nil)
break;
v->hvar = calloc(1, sizeof(TableHVAR));
if(read_TableHVAR(o, v->hvar) < 0){
free(v->hvar);
goto err;
}
rec->parsed = v->hvar;
rec->print = (void*)print_TableHVAR;
break;
case (u32int)('F'<<24|'F'<<16|'T'<<8|'M'):
if(v->fftm != nil)
break;
v->fftm = calloc(1, sizeof(TableFFTM));
if(read_TableFFTM(o, v->fftm) < 0){
free(v->fftm);
goto err;
}
rec->parsed = v->fftm;
rec->print = (void*)print_TableFFTM;
break;
case (u32int)('D'<<24|'S'<<16|'I'<<8|'G'):
if(v->dsig != nil)
break;
v->dsig = calloc(1, sizeof(TableDSIG));
if(read_TableDSIG(o, v->dsig) < 0){
free(v->dsig);
goto err;
}
rec->parsed = v->dsig;
rec->print = (void*)print_TableDSIG;
break;
case (u32int)('S'<<24|'T'<<16|'A'<<8|'T'):
if(v->stat != nil)
break;
v->stat = calloc(1, sizeof(TableSTAT));
if(read_TableSTAT(o, v->stat) < 0){
free(v->stat);
goto err;
}
rec->parsed = v->stat;
rec->print = (void*)print_TableSTAT;
break;
case (u32int)('g'<<24|'a'<<16|'s'<<8|'p'):
if(v->gasp != nil)
break;
v->gasp = calloc(1, sizeof(TableGasp));
if(read_TableGasp(o, v->gasp) < 0){
free(v->gasp);
goto err;
}
rec->parsed = v->gasp;
rec->print = (void*)print_TableGasp;
break;
case (u32int)('g'<<24|'v'<<16|'a'<<8|'r'):
{
static int retried = 0;
if(v->fvar == nil){
if(retried){
werrstr("%s: deps missing", "TableGvar");
goto err;
}
retried = 1;
retry++;
break;
}
if(retried)
retry--;
}
if(v->gvar != nil)
break;
v->gvar = calloc(1, sizeof(TableGvar));
if(read_TableGvar(o, v->gvar) < 0){
free(v->gvar);
goto err;
}
rec->parsed = v->gvar;
rec->print = (void*)print_TableGvar;
break;
case (u32int)('a'<<24|'v'<<16|'a'<<8|'r'):
if(v->avar != nil)
break;
v->avar = calloc(1, sizeof(TableAvar));
if(read_TableAvar(o, v->avar) < 0){
free(v->avar);
goto err;
}
rec->parsed = v->avar;
rec->print = (void*)print_TableAvar;
break;
case (u32int)('O'<<24|'S'<<16|'/'<<8|'2'):
if(v->os∕2 != nil)
break;
v->os∕2 = calloc(1, sizeof(TableOS∕2));
if(read_TableOS∕2(o, v->os∕2) < 0){
free(v->os∕2);
goto err;
}
rec->parsed = v->os∕2;
rec->print = (void*)print_TableOS∕2;
break;
default:
// FIXME fprint(2, "no parser for \"%t\"\n", rec->tableTag);
break;
}
if(otfpoprange(o) < 0)
goto err;
}
}while(retry > 0);
return 0;
err:
werrstr("%s: %r", "TableDirectory");
return -1;
}
void
print_TableDirectory(Otfile *f, int indent, Otf *o, TableDirectory *v)
{
f->print(f->aux, "%*s%s: %#ux\n", indent, "", "sfntVersion", v->sfntVersion);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numTables", v->numTables);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "searchRange", v->searchRange);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "entrySelector", v->entrySelector);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "rangeShift", v->rangeShift);
for(int i = 0; i < v->numTables; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "tableRecords", i);
print_TableRecord(f, indent+indentΔ, o, &v->tableRecords[i]);
}
USED(o);
}