ref: 2cfe3c2c1cb0de08ef9a4dca2d22dac286736b09
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); }