ref: f711b4426695620ce7646d3036f69275be73e59f
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; } void print_BitmapGlyph(Otfile *f, int indent, Otf *o, BitmapGlyph *v) { void *a = f->aux; int i; USED(o); if(v->bitDepth > 0) f->print(a, "%*s%s: %d\n", indent, "", "bitDepth", v->bitDepth); f->print(a, "%*s%s: %d\n", indent, "", "format", v->format); f->print(a, "%*s%s: %d\n", indent, "", "offset", v->offset); if(v->size > 0){ f->print(a, "%*s%s: %d\n", indent, "", "pitchBits", v->pitchBits); f->print(a, "%*s%s: %d\n", indent, "", "size", v->size); f->print(a, "%*s%s: ", indent, "", "image"); for(i = 0; i < v->size; i++) f->print(a, "%02"PRIx8, v->image[i]); f->print(a, "\n"); } f->print(a, "%*s%s: %d\n", indent, "", "ppemX", v->ppemX); f->print(a, "%*s%s: %d\n", indent, "", "ppemY", v->ppemY); if(v->numComponents > 0){ f->print(a, "%*s%s: %d\n", indent, "", "numComponents", v->numComponents); f->print(a, "%*s%s:\n", indent, "", "components"); for(i = 0; i < v->numComponents; i++){ f->print(a, "%*s%d:\n", indent+indentΔ, "", i); print_EbdtComponent(f, indent+indentΔ+indentΔ, o, v->components+i); } } } 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: %"PRId16"\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"); } } static Glyf * bitebdt(Otf *o, Glyf *g, BitmapGlyph *bg) { u8int *b; int i, n; if(o->ebdt == nil){ for(i = 0; i < o->td.numTables; i++){ TableRecord *rec = o->td.tableRecords+i; if(rec->tableTag == (u32int)('E'<<24|'B'<<16|'D'<<8|'T')){ o->ebdt = rec; break; } } if(o->ebdt == nil){ werrstr("no EBDT table"); goto err; } } if(otfpushrange(o, o->ebdt->offset, o->ebdt->length) < 0) goto err; if(otfpushrange(o, bg->offset, bg->size) < 0) goto err; if(bg->format == 1 || bg->format == 2 || bg->format == 8){ SmallGlyphMetrics sm; if(read_SmallGlyphMetrics(o, &sm) < 0) goto err; g->xMin = sm.bearingX; g->yMin = sm.bearingY - sm.height; g->xMax = sm.bearingX + sm.width; g->yMax = sm.bearingY; }else if(bg->format == 6 || bg->format == 7 || bg->format == 9){ BigGlyphMetrics bm; if(read_BigGlyphMetrics(o, &bm) < 0) goto err; /* FIXME only horizontal metrics, also this is probably wrong */ g->xMax = bm.width; g->yMax = bm.height; g->xMin = -(int)bm.horiBearingX; g->yMin = -(int)bm.horiBearingY; g->xMax += g->xMin; g->yMax += g->yMin; } bg->numComponents = 0; if(bg->format == 2 || bg->format == 5 || bg->format == 7){ /* bit-aligned - last row is padded to a full byte */ bg->pitchBits = g->xMax - g->xMin; bg->size = (bg->pitchBits*(g->yMax-g->yMin)*bg->bitDepth + 7)/8; }else{ /* byte-aligned - every row is byte-aligned */ n = ((g->xMax-g->xMin)*bg->bitDepth + 7)/8; bg->size = n * (g->yMax-g->yMin); bg->pitchBits = n * 8; } switch(bg->format){ case 8: if(otfreadn(o, 1) == nil) /* skip uint8 pad */ goto err; /* fallthrough */ case 9: if((b = otfreadn(o, 2)) == nil) goto err; bg->numComponents = b[0]<<8 | b[1]; if(otfarray(o, &bg->components, read_EbdtComponent, sizeof(EbdtComponent), bg->numComponents) < 0) goto err; /* no image, both 8 and 9 are component */ bg->pitchBits = 0; bg->size = 0; /* fallthrough */ case 1: case 2: case 5: case 6: case 7: g->bitmap = malloc(sizeof(*bg) + bg->size); memcpy(g->bitmap, bg, sizeof(*bg)); if(bg->size > 0){ if((b = otfreadn(o, bg->size)) == nil) goto err; memcpy(g->bitmap->image, b, bg->size); } break; } otfpoprange(o); otfpoprange(o); return g; err: free(g->bitmap); free(g); otfpopranges(o); return nil; } static int ppemcmp(BitmapGlyph *a, BitmapGlyph *b) { if(a->ppemX != b->ppemX) return a->ppemX - b->ppemX; if(a->ppemY != b->ppemY) return a->ppemY - b->ppemY; /* FIXME - is there anything else to compare? bit depth? */ return 0; } static Glyf * bitglyf(Otf *o, Glyf *g, RasterOpts *opts) { BitmapGlyph b, best, want; IndexSubtableRecord *isr; int i, j, k, n, r, found; IndexSubtable *is; BitmapSize *bs; want.ppemX = opts->ppemX; want.ppemY = opts->ppemY; found = 0; r = -1; g->type = GLYPH_BITMAP; bs = o->td.eblc->bitmapSizes; for(i = 0; i < (int)o->td.eblc->numSizes; i++, bs++){ if(g->index < bs->startGlyphIndex) continue; if(g->index > bs->endGlyphIndex) break; b.bitDepth = bs->bitDepth; if(b.bitDepth != 1 && b.bitDepth != 8){ werrstr("unsupported bit depth: %d", b.bitDepth); goto err; } b.ppemX = bs->ppemX; b.ppemY = bs->ppemY; isr = bs->indexSubtableList; for(j = 0; j < (int)bs->numberOfIndexSubtables; j++, isr++){ if(g->index < isr->firstGlyphIndex) break; if(g->index > isr->lastGlyphIndex || (is = isr->indexSubtable) == nil) continue; b.format = is->imageFormat; b.offset = is->imageDataOffset; n = g->index - isr->firstGlyphIndex; switch(is->indexFormat){ case 1: b.offset += is->sub1.sbitOffsets[n]; b.size = is->sub1.sbitOffsets[n+1] - is->sub1.sbitOffsets[n]; break; case 2: b.offset += n*is->sub2.imageSize; b.size = is->sub2.imageSize; /* FIXME - vertical metrics are not used here, also this is probably wrong */ g->xMin = -is->sub2.bigMetrics.horiBearingX; g->yMin = is->sub2.bigMetrics.horiBearingY - is->sub2.bigMetrics.height; g->xMax = is->sub2.bigMetrics.width + g->xMin; g->yMax = is->sub2.bigMetrics.height + g->yMin; break; case 3: b.offset += is->sub3.sbitOffsets[n]; b.size = is->sub3.sbitOffsets[n+1] - is->sub3.sbitOffsets[n]; break; case 4: n = is->sub4.numGlyphs; for(k = 0; k < n; k++){ if(is->sub4.glyphArray[k].glyphID == g->index) break; } if(k >= n) continue; b.offset += is->sub4.glyphArray[k].sbitOffset; b.size = is->sub4.glyphArray[k+1].sbitOffset - is->sub4.glyphArray[k].sbitOffset; break; case 5: n = is->sub5.numGlyphs; for(k = 0; k < n; k++){ if(is->sub5.glyphIdArray[k] == g->index) break; } if(k >= n) continue; b.offset += k*is->sub5.imageSize; b.size = is->sub5.imageSize; /* FIXME - vertical metrics are not used here, also this is probably wrong */ g->xMin = -is->sub5.bigMetrics.horiBearingX; g->yMin = is->sub5.bigMetrics.horiBearingY - is->sub5.bigMetrics.height; g->xMax = is->sub5.bigMetrics.width + g->xMin; g->yMax = is->sub5.bigMetrics.height + g->yMin; break; default: continue; } /* now try to choose the best match */ if((n = ppemcmp(&b, &want)) == 0 || found == 0){ better: memcpy(&best, &b, sizeof(b)); found = 1; if((r = n) == 0) goto done; continue; } /* both better, but the new is closer */ if(n > 0 && (r > 0 && ppemcmp(&b, &best) < 0)) goto better; /* both worse, but the new one is better so far */ if(n < 0 && (r < 0 && ppemcmp(&b, &best) > 0)) goto better; } } done: if(found) return bitebdt(o, g, &best); werrstr("no bitmap"); err: free(g); return nil; } Glyf * otfglyf(Otf *o, int index, RasterOpts *opts) { static TableRecord noGlyf; int off, len, i; Glyf *g; if(index < 0 || index >= o->numGlyphs){ werrstr("index out of range"); return nil; } if(o->td.head == nil){ werrstr("no head table"); return nil; } if((g = calloc(1, sizeof(*g))) == nil){ werrstr("no memory"); return nil; } g->index = index; if(o->glyf == nil){ 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 == nil) o->glyf = &noGlyf; } if(o->glyf != &noGlyf && o->td.loca != nil){ 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 > 0){ if(otfpushrange(o, o->glyf->offset, o->glyf->length) < 0){ err: free(g); otfpopranges(o); return nil; } if(otfpushrange(o, off, len) < 0) goto err; if(read_Glyf(o, g) < 0) goto err; otfpoprange(o); otfpoprange(o); return g; } if(o->td.eblc == nil && o->td.ebdt == nil) return g; } if(o->td.eblc != nil && o->td.ebdt != nil) return bitglyf(o, g, opts); free(g); 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); o->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); o->numberOfHMetrics = v->numberOfHMetrics; USED(o); } int read_EbdtComponent(Otf *o, EbdtComponent *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 4)) == nil) goto err; v->glyphID = b[0]<<8 | b[1]; v->xOffset = b[2]; v->yOffset = b[3]; return 0; err: werrstr("%s: %r", "EbdtComponent"); return -1; } void print_EbdtComponent(Otfile *f, int indent, Otf *o, EbdtComponent *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID); f->print(f->aux, "%*s%s: %d\n", indent, "", "xOffset", v->xOffset); f->print(f->aux, "%*s%s: %d\n", indent, "", "yOffset", v->yOffset); 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){ if(read_ComponentGlyph(o, &v->component, 0) < 0) goto err; v->type = GLYPH_COMPONENT; }else if(v->numberOfContours > 0){ if(read_SimpleGlyph(o, &v->simple) < 0) goto err; v->type = GLYPH_SIMPLE; }else if(o->td.eblc != nil && o->td.ebdt != nil) v->type = GLYPH_BITMAP; else v->type = GLYPH_EMPTY; 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); o->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->type == GLYPH_BITMAP){ f->print(f->aux, "%*s%s:\n", indent, "", "bitmap"); print_BitmapGlyph(f, indent+indentΔ, o, v->bitmap); }else if(v->type == GLYPH_COMPONENT){ f->print(f->aux, "%*s%s:\n", indent, "", "component"); print_ComponentGlyph(f, indent+indentΔ, o, v->component); }else if(v->type == GLYPH_SIMPLE){ 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); o->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); o->platformID = v->platformID; f->print(f->aux, "%*s%s: %ud\n", indent, "", "encodingID", v->encodingID); o->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); o->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); o->firstGlyphIndex = v->firstGlyphIndex; f->print(f->aux, "%*s%s: %ud\n", indent, "", "lastGlyphIndex", v->lastGlyphIndex); o->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]; if(v->bitDepth != 1 && v->bitDepth != 2 && v->bitDepth != 4 && v->bitDepth != 8){ werrstr("%s: invalid value: %d (%#ux)", "bitDepth", v->bitDepth, v->bitDepth); goto err; } 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_SequenceLookup(Otf *o, SequenceLookup *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 4)) == nil) goto err; v->sequenceIndex = b[0]<<8 | b[1]; v->lookupListIndex = b[2]<<8 | b[3]; return 0; err: werrstr("%s: %r", "SequenceLookup"); return -1; } void print_SequenceLookup(Otfile *f, int indent, Otf *o, SequenceLookup *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "sequenceIndex", v->sequenceIndex); f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookupListIndex", v->lookupListIndex); USED(o); } int read_ChainedSequenceRule(Otf *o, ChainedSequenceRule *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 2)) == nil) goto err; v->backtrackGlyphCount = b[0]<<8 | b[1]; if((b = otfreadn(o, v->backtrackGlyphCount*2)) == nil) goto err; v->backtrackSequence = malloc(v->backtrackGlyphCount*sizeof(*v->backtrackSequence)); for(int i = 0; i < v->backtrackGlyphCount; i++) v->backtrackSequence[i] = b[0+i*2]<<8 | b[1+i*2]; if((b = otfreadn(o, 2)) == nil) goto err; v->inputGlyphCount = b[0]<<8 | b[1]; if((b = otfreadn(o, (v->inputGlyphCount-1)*2)) == nil) goto err; v->inputSequence = malloc((v->inputGlyphCount-1)*sizeof(*v->inputSequence)); for(int i = 0; i < (v->inputGlyphCount-1); i++) v->inputSequence[i] = b[0+i*2]<<8 | b[1+i*2]; if((b = otfreadn(o, 2)) == nil) goto err; v->lookaheadGlyphCount = b[0]<<8 | b[1]; if((b = otfreadn(o, v->lookaheadGlyphCount*2)) == nil) goto err; v->lookaheadSequence = malloc(v->lookaheadGlyphCount*sizeof(*v->lookaheadSequence)); for(int i = 0; i < v->lookaheadGlyphCount; i++) v->lookaheadSequence[i] = b[0+i*2]<<8 | b[1+i*2]; if((b = otfreadn(o, 2)) == nil) goto err; v->seqLookupCount = b[0]<<8 | b[1]; if(otfarray(o, &v->seqLookupRecords, read_SequenceLookup, sizeof(SequenceLookup), v->seqLookupCount) < 0){ werrstr("%s: %r", "seqLookupRecords"); goto err; } return 0; err: werrstr("%s: %r", "ChainedSequenceRule"); return -1; } void print_ChainedSequenceRule(Otfile *f, int indent, Otf *o, ChainedSequenceRule *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "backtrackGlyphCount", v->backtrackGlyphCount); for(int i = 0; i < v->backtrackGlyphCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "backtrackSequence", i, v->backtrackSequence[i]); f->print(f->aux, "%*s%s: %ud\n", indent, "", "inputGlyphCount", v->inputGlyphCount); for(int i = 0; i < (v->inputGlyphCount-1); i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "inputSequence", i, v->inputSequence[i]); f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookaheadGlyphCount", v->lookaheadGlyphCount); for(int i = 0; i < v->lookaheadGlyphCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "lookaheadSequence", i, v->lookaheadSequence[i]); f->print(f->aux, "%*s%s: %ud\n", indent, "", "seqLookupCount", v->seqLookupCount); for(int i = 0; i < v->seqLookupCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "seqLookupRecords", i); print_SequenceLookup(f, indent+indentΔ, o, &v->seqLookupRecords[i]); } USED(o); } int read_ChainedSequenceRuleSet(Otf *o, ChainedSequenceRuleSet *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 2)) == nil) goto err; v->chainedSeqRuleCount = b[0]<<8 | b[1]; if((b = otfreadn(o, v->chainedSeqRuleCount*2)) == nil) goto err; v->chainedSeqRuleOffsets = malloc(v->chainedSeqRuleCount*sizeof(*v->chainedSeqRuleOffsets)); for(int i = 0; i < v->chainedSeqRuleCount; i++) v->chainedSeqRuleOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if(v->chainedSeqRuleCount > 0){ v->chainedSeqRule = calloc(v->chainedSeqRuleCount, sizeof(*v->chainedSeqRule)); for(int i = 0; i < v->chainedSeqRuleCount; i++){ if(v->chainedSeqRuleOffsets[i] == 0) continue; if(otfpushrange(o, v->chainedSeqRuleOffsets[i], -1)) goto err; int r = read_ChainedSequenceRule(o, v->chainedSeqRule+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->chainedSeqRule+i, 0, sizeof(*v->chainedSeqRule)); break; } } } return 0; err: werrstr("%s: %r", "ChainedSequenceRuleSet"); return -1; } void print_ChainedSequenceRuleSet(Otfile *f, int indent, Otf *o, ChainedSequenceRuleSet *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "chainedSeqRuleCount", v->chainedSeqRuleCount); for(int i = 0; i < v->chainedSeqRuleCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "chainedSeqRuleOffsets", i, v->chainedSeqRuleOffsets[i]); for(int i = 0; i < v->chainedSeqRuleCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "chainedSeqRule", i); print_ChainedSequenceRule(f, indent+indentΔ, o, &v->chainedSeqRule[i]); } USED(o); } int read_ChainedSequenceContextFormat1(Otf *o, ChainedSequenceContextFormat1 *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 4)) == nil) goto err; v->coverageOffset = b[0]<<8 | b[1]; v->chainedSeqRuleSetCount = b[2]<<8 | b[3]; if((b = otfreadn(o, v->chainedSeqRuleSetCount*2)) == nil) goto err; v->chainedSeqRuleSetOffsets = malloc(v->chainedSeqRuleSetCount*sizeof(*v->chainedSeqRuleSetOffsets)); for(int i = 0; i < v->chainedSeqRuleSetCount; i++) v->chainedSeqRuleSetOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if(v->chainedSeqRuleSetCount > 0){ v->chainedSeqRuleSet = calloc(v->chainedSeqRuleSetCount, sizeof(*v->chainedSeqRuleSet)); for(int i = 0; i < v->chainedSeqRuleSetCount; i++){ if(v->chainedSeqRuleSetOffsets[i] == 0) continue; if(otfpushrange(o, v->chainedSeqRuleSetOffsets[i], -1)) goto err; int r = read_ChainedSequenceRuleSet(o, v->chainedSeqRuleSet+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->chainedSeqRuleSet+i, 0, sizeof(*v->chainedSeqRuleSet)); break; } } } return 0; err: werrstr("%s: %r", "ChainedSequenceContextFormat1"); return -1; } void print_ChainedSequenceContextFormat1(Otfile *f, int indent, Otf *o, ChainedSequenceContextFormat1 *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "coverageOffset", v->coverageOffset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "chainedSeqRuleSetCount", v->chainedSeqRuleSetCount); for(int i = 0; i < v->chainedSeqRuleSetCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "chainedSeqRuleSetOffsets", i, v->chainedSeqRuleSetOffsets[i]); for(int i = 0; i < v->chainedSeqRuleSetCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "chainedSeqRuleSet", i); print_ChainedSequenceRuleSet(f, indent+indentΔ, o, &v->chainedSeqRuleSet[i]); } USED(o); } int read_ChainedClassSequenceRuleSet(Otf *o, ChainedClassSequenceRuleSet *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 2)) == nil) goto err; v->chainedClassSeqRuleCount = b[0]<<8 | b[1]; if((b = otfreadn(o, v->chainedClassSeqRuleCount*2)) == nil) goto err; v->chainedClassSeqRuleOffsets = malloc(v->chainedClassSeqRuleCount*sizeof(*v->chainedClassSeqRuleOffsets)); for(int i = 0; i < v->chainedClassSeqRuleCount; i++) v->chainedClassSeqRuleOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if(v->chainedClassSeqRuleCount > 0){ v->chainedClassSeqRules = calloc(v->chainedClassSeqRuleCount, sizeof(*v->chainedClassSeqRules)); for(int i = 0; i < v->chainedClassSeqRuleCount; i++){ if(v->chainedClassSeqRuleOffsets[i] == 0) continue; if(otfpushrange(o, v->chainedClassSeqRuleOffsets[i], -1)) goto err; int r = read_ChainedSequenceRule(o, v->chainedClassSeqRules+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->chainedClassSeqRules+i, 0, sizeof(*v->chainedClassSeqRules)); break; } } } return 0; err: werrstr("%s: %r", "ChainedClassSequenceRuleSet"); return -1; } void print_ChainedClassSequenceRuleSet(Otfile *f, int indent, Otf *o, ChainedClassSequenceRuleSet *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "chainedClassSeqRuleCount", v->chainedClassSeqRuleCount); for(int i = 0; i < v->chainedClassSeqRuleCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "chainedClassSeqRuleOffsets", i, v->chainedClassSeqRuleOffsets[i]); for(int i = 0; i < v->chainedClassSeqRuleCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "chainedClassSeqRules", i); print_ChainedSequenceRule(f, indent+indentΔ, o, &v->chainedClassSeqRules[i]); } USED(o); } int read_ChainedSequenceContextFormat2(Otf *o, ChainedSequenceContextFormat2 *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 10)) == nil) goto err; v->coverageOffset = b[0]<<8 | b[1]; v->backtrackClassDefOffset = b[2]<<8 | b[3]; v->inputClassDefOffset = b[4]<<8 | b[5]; v->lookaheadClassDefOffset = b[6]<<8 | b[7]; v->chainedClassSeqRuleSetCount = b[8]<<8 | b[9]; if((b = otfreadn(o, v->chainedClassSeqRuleSetCount*2)) == nil) goto err; v->chainedClassSeqRuleSetOffsets = malloc(v->chainedClassSeqRuleSetCount*sizeof(*v->chainedClassSeqRuleSetOffsets)); for(int i = 0; i < v->chainedClassSeqRuleSetCount; i++) v->chainedClassSeqRuleSetOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if(v->chainedClassSeqRuleSetCount > 0){ v->chainedClassSequenceRuleSets = calloc(v->chainedClassSeqRuleSetCount, sizeof(*v->chainedClassSequenceRuleSets)); for(int i = 0; i < v->chainedClassSeqRuleSetCount; i++){ if(v->chainedClassSeqRuleSetOffsets[i] == 0) continue; if(otfpushrange(o, v->chainedClassSeqRuleSetOffsets[i], -1)) goto err; int r = read_ChainedClassSequenceRuleSet(o, v->chainedClassSequenceRuleSets+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->chainedClassSequenceRuleSets+i, 0, sizeof(*v->chainedClassSequenceRuleSets)); break; } } } return 0; err: werrstr("%s: %r", "ChainedSequenceContextFormat2"); return -1; } void print_ChainedSequenceContextFormat2(Otfile *f, int indent, Otf *o, ChainedSequenceContextFormat2 *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "coverageOffset", v->coverageOffset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "backtrackClassDefOffset", v->backtrackClassDefOffset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "inputClassDefOffset", v->inputClassDefOffset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookaheadClassDefOffset", v->lookaheadClassDefOffset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "chainedClassSeqRuleSetCount", v->chainedClassSeqRuleSetCount); for(int i = 0; i < v->chainedClassSeqRuleSetCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "chainedClassSeqRuleSetOffsets", i, v->chainedClassSeqRuleSetOffsets[i]); for(int i = 0; i < v->chainedClassSeqRuleSetCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "chainedClassSequenceRuleSets", i); print_ChainedClassSequenceRuleSet(f, indent+indentΔ, o, &v->chainedClassSequenceRuleSets[i]); } USED(o); } int read_ChainedSequenceContextFormat3(Otf *o, ChainedSequenceContextFormat3 *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 2)) == nil) goto err; v->backtrackGlyphCount = b[0]<<8 | b[1]; if((b = otfreadn(o, v->backtrackGlyphCount*2)) == nil) goto err; v->backtrackCoverageOffsets = malloc(v->backtrackGlyphCount*sizeof(*v->backtrackCoverageOffsets)); for(int i = 0; i < v->backtrackGlyphCount; i++) v->backtrackCoverageOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if((b = otfreadn(o, 2)) == nil) goto err; v->inputGlyphCount = b[0]<<8 | b[1]; if((b = otfreadn(o, v->inputGlyphCount*2)) == nil) goto err; v->inputCoverageOffsets = malloc(v->inputGlyphCount*sizeof(*v->inputCoverageOffsets)); for(int i = 0; i < v->inputGlyphCount; i++) v->inputCoverageOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if((b = otfreadn(o, 2)) == nil) goto err; v->lookaheadGlyphCount = b[0]<<8 | b[1]; if((b = otfreadn(o, v->lookaheadGlyphCount*2)) == nil) goto err; v->lookaheadCoverageOffsets = malloc(v->lookaheadGlyphCount*sizeof(*v->lookaheadCoverageOffsets)); for(int i = 0; i < v->lookaheadGlyphCount; i++) v->lookaheadCoverageOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if((b = otfreadn(o, 2)) == nil) goto err; v->seqLookupCount = b[0]<<8 | b[1]; if(otfarray(o, &v->seqLookupRecords, read_SequenceLookup, sizeof(SequenceLookup), v->seqLookupCount) < 0){ werrstr("%s: %r", "seqLookupRecords"); goto err; } return 0; err: werrstr("%s: %r", "ChainedSequenceContextFormat3"); return -1; } void print_ChainedSequenceContextFormat3(Otfile *f, int indent, Otf *o, ChainedSequenceContextFormat3 *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "backtrackGlyphCount", v->backtrackGlyphCount); for(int i = 0; i < v->backtrackGlyphCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "backtrackCoverageOffsets", i, v->backtrackCoverageOffsets[i]); f->print(f->aux, "%*s%s: %ud\n", indent, "", "inputGlyphCount", v->inputGlyphCount); for(int i = 0; i < v->inputGlyphCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "inputCoverageOffsets", i, v->inputCoverageOffsets[i]); f->print(f->aux, "%*s%s: %ud\n", indent, "", "lookaheadGlyphCount", v->lookaheadGlyphCount); for(int i = 0; i < v->lookaheadGlyphCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "lookaheadCoverageOffsets", i, v->lookaheadCoverageOffsets[i]); f->print(f->aux, "%*s%s: %ud\n", indent, "", "seqLookupCount", v->seqLookupCount); for(int i = 0; i < v->seqLookupCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "seqLookupRecords", i); print_SequenceLookup(f, indent+indentΔ, o, &v->seqLookupRecords[i]); } USED(o); } int read_ChainedSequenceContext(Otf *o, ChainedSequenceContext *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){ if(read_ChainedSequenceContextFormat1(o, &v->f1) < 0){ werrstr("%s: %r", "f1"); goto err; } } if(v->format == 2){ if(read_ChainedSequenceContextFormat2(o, &v->f2) < 0){ werrstr("%s: %r", "f2"); goto err; } } if(v->format == 3){ if(read_ChainedSequenceContextFormat3(o, &v->f3) < 0){ werrstr("%s: %r", "f3"); goto err; } } return 0; err: werrstr("%s: %r", "ChainedSequenceContext"); return -1; } void print_ChainedSequenceContext(Otfile *f, int indent, Otf *o, ChainedSequenceContext *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, "", "f1"); print_ChainedSequenceContextFormat1(f, indent+indentΔ, o, &v->f1); } if(v->format == 2){ f->print(f->aux, "%*s%s:\n", indent, "", "f2"); print_ChainedSequenceContextFormat2(f, indent+indentΔ, o, &v->f2); } if(v->format == 3){ f->print(f->aux, "%*s%s:\n", indent, "", "f3"); print_ChainedSequenceContextFormat3(f, indent+indentΔ, o, &v->f3); } USED(o); } int read_PairValue(Otf *o, PairValue *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 2)) == nil) goto err; v->secondGlyph = b[0]<<8 | b[1]; if(read_ValueRecord(o, &v->valueRecord1) < 0){ werrstr("%s: %r", "valueRecord1"); goto err; } if(read_ValueRecord(o, &v->valueRecord2) < 0){ werrstr("%s: %r", "valueRecord2"); goto err; } return 0; err: werrstr("%s: %r", "PairValue"); return -1; } void print_PairValue(Otfile *f, int indent, Otf *o, PairValue *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "secondGlyph", v->secondGlyph); f->print(f->aux, "%*s%s:\n", indent, "", "valueRecord1"); print_ValueRecord(f, indent+indentΔ, o, &v->valueRecord1); f->print(f->aux, "%*s%s:\n", indent, "", "valueRecord2"); print_ValueRecord(f, indent+indentΔ, o, &v->valueRecord2); USED(o); } int read_PairSet(Otf *o, PairSet *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 2)) == nil) goto err; v->pairValueCount = b[0]<<8 | b[1]; if(otfarray(o, &v->pairValueRecords, read_PairValue, sizeof(PairValue), v->pairValueCount) < 0){ werrstr("%s: %r", "pairValueRecords"); goto err; } return 0; err: werrstr("%s: %r", "PairSet"); return -1; } void print_PairSet(Otfile *f, int indent, Otf *o, PairSet *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "pairValueCount", v->pairValueCount); for(int i = 0; i < v->pairValueCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "pairValueRecords", i); print_PairValue(f, indent+indentΔ, o, &v->pairValueRecords[i]); } USED(o); } int read_PairPosFormat1(Otf *o, PairPosFormat1 *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 2)) == nil) goto err; v->pairSetCount = b[0]<<8 | b[1]; if((b = otfreadn(o, v->pairSetCount*2)) == nil) goto err; v->pairSetOffsets = malloc(v->pairSetCount*sizeof(*v->pairSetOffsets)); for(int i = 0; i < v->pairSetCount; i++) v->pairSetOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if(v->pairSetCount > 0){ v->pairSets = calloc(v->pairSetCount, sizeof(*v->pairSets)); for(int i = 0; i < v->pairSetCount; i++){ if(v->pairSetOffsets[i] == 0) continue; if(otfpushrange(o, v->pairSetOffsets[i], -1)) goto err; int r = read_PairSet(o, v->pairSets+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->pairSets+i, 0, sizeof(*v->pairSets)); break; } } } return 0; err: werrstr("%s: %r", "PairPosFormat1"); return -1; } void print_PairPosFormat1(Otfile *f, int indent, Otf *o, PairPosFormat1 *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "pairSetCount", v->pairSetCount); for(int i = 0; i < v->pairSetCount; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "pairSetOffsets", i, v->pairSetOffsets[i]); for(int i = 0; i < v->pairSetCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "pairSets", i); print_PairSet(f, indent+indentΔ, o, &v->pairSets[i]); } USED(o); } int read_Class2(Otf *o, Class2 *v) { u8int *b = nil; USED(b); if(read_ValueRecord(o, &v->valueRecord1) < 0){ werrstr("%s: %r", "valueRecord1"); goto err; } if(read_ValueRecord(o, &v->valueRecord2) < 0){ werrstr("%s: %r", "valueRecord2"); goto err; } return 0; err: werrstr("%s: %r", "Class2"); return -1; } void print_Class2(Otfile *f, int indent, Otf *o, Class2 *v) { f->print(f->aux, "%*s%s:\n", indent, "", "valueRecord1"); print_ValueRecord(f, indent+indentΔ, o, &v->valueRecord1); f->print(f->aux, "%*s%s:\n", indent, "", "valueRecord2"); print_ValueRecord(f, indent+indentΔ, o, &v->valueRecord2); USED(o); } int read_Class1(Otf *o, Class1 *v) { u8int *b = nil; USED(b); if(otfarray(o, &v->class2Records, read_Class2, sizeof(Class2), o->class2Count) < 0){ werrstr("%s: %r", "class2Records"); goto err; } return 0; err: werrstr("%s: %r", "Class1"); return -1; } void print_Class1(Otfile *f, int indent, Otf *o, Class1 *v) { for(int i = 0; i < o->class2Count; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "class2Records", i); print_Class2(f, indent+indentΔ, o, &v->class2Records[i]); } USED(o); } int read_PairPosFormat2(Otf *o, PairPosFormat2 *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 8)) == nil) goto err; v->classDef1Offset = b[0]<<8 | b[1]; v->classDef2Offset = b[2]<<8 | b[3]; v->class1Count = b[4]<<8 | b[5]; v->class2Count = b[6]<<8 | b[7]; o->class2Count = v->class2Count; if(otfarray(o, &v->class1Records, read_Class1, sizeof(Class1), v->class1Count) < 0){ werrstr("%s: %r", "class1Records"); goto err; } return 0; err: werrstr("%s: %r", "PairPosFormat2"); return -1; } void print_PairPosFormat2(Otfile *f, int indent, Otf *o, PairPosFormat2 *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "classDef1Offset", v->classDef1Offset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "classDef2Offset", v->classDef2Offset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "class1Count", v->class1Count); f->print(f->aux, "%*s%s: %ud\n", indent, "", "class2Count", v->class2Count); o->class2Count = v->class2Count; for(int i = 0; i < v->class1Count; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "class1Records", i); print_Class1(f, indent+indentΔ, o, &v->class1Records[i]); } USED(o); } int read_PairPos(Otf *o, PairPos *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 8)) == 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->valueFormat1 = b[4]<<8 | b[5]; v->valueFormat2 = b[6]<<8 | b[7]; if(v->format == 1){ if(read_PairPosFormat1(o, &v->f1) < 0){ werrstr("%s: %r", "f1"); goto err; } } if(v->format == 2){ if(read_PairPosFormat2(o, &v->f2) < 0){ werrstr("%s: %r", "f2"); goto err; } } return 0; err: werrstr("%s: %r", "PairPos"); return -1; } void print_PairPos(Otfile *f, int indent, Otf *o, PairPos *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, "", "valueFormat1", v->valueFormat1); f->print(f->aux, "%*s%s: %ud\n", indent, "", "valueFormat2", v->valueFormat2); if(v->format == 1){ f->print(f->aux, "%*s%s:\n", indent, "", "f1"); print_PairPosFormat1(f, indent+indentΔ, o, &v->f1); } if(v->format == 2){ f->print(f->aux, "%*s%s:\n", indent, "", "f2"); print_PairPosFormat2(f, indent+indentΔ, o, &v->f2); } USED(o); } int read_EntryExit(Otf *o, EntryExit *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 4)) == nil) goto err; v->entryAnchorOffset = b[0]<<8 | b[1]; v->exitAnchorOffset = b[2]<<8 | b[3]; return 0; err: werrstr("%s: %r", "EntryExit"); return -1; } void print_EntryExit(Otfile *f, int indent, Otf *o, EntryExit *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "entryAnchorOffset", v->entryAnchorOffset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "exitAnchorOffset", v->exitAnchorOffset); USED(o); } int read_CursivePos(Otf *o, CursivePos *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 6)) == 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->coverageOffset = b[2]<<8 | b[3]; v->entryExitCount = b[4]<<8 | b[5]; if(otfarray(o, &v->entryExitRecords, read_EntryExit, sizeof(EntryExit), v->entryExitCount) < 0){ werrstr("%s: %r", "entryExitRecords"); goto err; } return 0; err: werrstr("%s: %r", "CursivePos"); return -1; } void print_CursivePos(Otfile *f, int indent, Otf *o, CursivePos *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "coverageOffset", v->coverageOffset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "entryExitCount", v->entryExitCount); for(int i = 0; i < v->entryExitCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "entryExitRecords", i); print_EntryExit(f, indent+indentΔ, o, &v->entryExitRecords[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]; if((v->lookupType==LOOKUP_TYPE_SINGLE_ADJUSTMENT)){ if(v->subTableCount > 0){ v->singleAdjustment = calloc(v->subTableCount, sizeof(*v->singleAdjustment)); for(int i = 0; i < v->subTableCount; i++){ if(v->subtableOffsets[i] == 0) continue; if(otfpushrange(o, v->subtableOffsets[i], -1)) goto err; int r = read_SinglePos(o, v->singleAdjustment+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->singleAdjustment+i, 0, sizeof(*v->singleAdjustment)); break; } } } } if((v->lookupType==LOOKUP_TYPE_PAIR_ADJUSTMENT)){ if(v->subTableCount > 0){ v->pairAdjustment = calloc(v->subTableCount, sizeof(*v->pairAdjustment)); for(int i = 0; i < v->subTableCount; i++){ if(v->subtableOffsets[i] == 0) continue; if(otfpushrange(o, v->subtableOffsets[i], -1)) goto err; int r = read_PairPos(o, v->pairAdjustment+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->pairAdjustment+i, 0, sizeof(*v->pairAdjustment)); break; } } } } if((v->lookupType==LOOKUP_TYPE_CURSIVE_ATTACHMENT)){ if(v->subTableCount > 0){ v->cursiveAttachment = calloc(v->subTableCount, sizeof(*v->cursiveAttachment)); for(int i = 0; i < v->subTableCount; i++){ if(v->subtableOffsets[i] == 0) continue; if(otfpushrange(o, v->subtableOffsets[i], -1)) goto err; int r = read_CursivePos(o, v->cursiveAttachment+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->cursiveAttachment+i, 0, sizeof(*v->cursiveAttachment)); break; } } } } if((v->lookupType==LOOKUP_TYPE_CHAINED_CONTEXTS_POSITIONING)){ if(v->subTableCount > 0){ v->chainedContextsPositioning = calloc(v->subTableCount, sizeof(*v->chainedContextsPositioning)); for(int i = 0; i < v->subTableCount; i++){ if(v->subtableOffsets[i] == 0) continue; if(otfpushrange(o, v->subtableOffsets[i], -1)) goto err; int r = read_ChainedSequenceContext(o, v->chainedContextsPositioning+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->chainedContextsPositioning+i, 0, sizeof(*v->chainedContextsPositioning)); break; } } } } 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%s\n", indent, "", "lookupType", v->lookupType, v->lookupType==LOOKUP_TYPE_SINGLE_ADJUSTMENT?" LOOKUP_TYPE_SINGLE_ADJUSTMENT": v->lookupType==LOOKUP_TYPE_PAIR_ADJUSTMENT?" LOOKUP_TYPE_PAIR_ADJUSTMENT": v->lookupType==LOOKUP_TYPE_CURSIVE_ATTACHMENT?" LOOKUP_TYPE_CURSIVE_ATTACHMENT": v->lookupType==LOOKUP_TYPE_MARK_TO_BASE_ATTACHMENT?" LOOKUP_TYPE_MARK_TO_BASE_ATTACHMENT": v->lookupType==LOOKUP_TYPE_MARK_TO_LIGATURE_ATTACHMENT?" LOOKUP_TYPE_MARK_TO_LIGATURE_ATTACHMENT": v->lookupType==LOOKUP_TYPE_MARK_TO_MARK_ATTACHMENT?" LOOKUP_TYPE_MARK_TO_MARK_ATTACHMENT": v->lookupType==LOOKUP_TYPE_CONTEXTUAL_POSITIONING?" LOOKUP_TYPE_CONTEXTUAL_POSITIONING": v->lookupType==LOOKUP_TYPE_CHAINED_CONTEXTS_POSITIONING?" LOOKUP_TYPE_CHAINED_CONTEXTS_POSITIONING": v->lookupType==LOOKUP_TYPE_POSITIONING_EXTENSION?" LOOKUP_TYPE_POSITIONING_EXTENSION":""); f->print(f->aux, "%*s%s: %#ux%s%s%s%s%s\n", indent, "", "lookupFlag", v->lookupFlag, (v->lookupFlag&LOOKUP_FL_RIGHT_TO_LEFT)?" LOOKUP_FL_RIGHT_TO_LEFT":"", (v->lookupFlag&LOOKUP_FL_IGNORE_BASE_GLYPHS)?" LOOKUP_FL_IGNORE_BASE_GLYPHS":"", (v->lookupFlag&LOOKUP_FL_IGNORE_LIGATURES)?" LOOKUP_FL_IGNORE_LIGATURES":"", (v->lookupFlag&LOOKUP_FL_IGNORE_MARKS)?" LOOKUP_FL_IGNORE_MARKS":"", (v->lookupFlag&LOOKUP_FL_USE_MARK_FILTERING_SET)?" LOOKUP_FL_USE_MARK_FILTERING_SET":""); 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); if((v->lookupType==LOOKUP_TYPE_SINGLE_ADJUSTMENT)){ for(int i = 0; i < v->subTableCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "singleAdjustment", i); print_SinglePos(f, indent+indentΔ, o, &v->singleAdjustment[i]); } } if((v->lookupType==LOOKUP_TYPE_PAIR_ADJUSTMENT)){ for(int i = 0; i < v->subTableCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "pairAdjustment", i); print_PairPos(f, indent+indentΔ, o, &v->pairAdjustment[i]); } } if((v->lookupType==LOOKUP_TYPE_CURSIVE_ATTACHMENT)){ for(int i = 0; i < v->subTableCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "cursiveAttachment", i); print_CursivePos(f, indent+indentΔ, o, &v->cursiveAttachment[i]); } } if((v->lookupType==LOOKUP_TYPE_CHAINED_CONTEXTS_POSITIONING)){ for(int i = 0; i < v->subTableCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "chainedContextsPositioning", i); print_ChainedSequenceContext(f, indent+indentΔ, o, &v->chainedContextsPositioning[i]); } } 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]; if(v->lookupCount > 0){ v->lookups = calloc(v->lookupCount, sizeof(*v->lookups)); for(int i = 0; i < v->lookupCount; i++){ if(v->lookupOffsets[i] == 0) continue; if(otfpushrange(o, v->lookupOffsets[i], -1)) goto err; int r = read_Lookup(o, v->lookups+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->lookups+i, 0, sizeof(*v->lookups)); break; } } } 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]); for(int i = 0; i < v->lookupCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "lookups", i); print_Lookup(f, indent+indentΔ, o, &v->lookups[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_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_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; } if(v->vertGlyphCount > 0){ v->vertGlyphConstruction = calloc(v->vertGlyphCount, sizeof(*v->vertGlyphConstruction)); for(int i = 0; i < v->vertGlyphCount; i++){ if(v->vertGlyphConstructionOffsets[i] == 0) continue; if(otfpushrange(o, v->vertGlyphConstructionOffsets[i], -1)) goto err; int r = read_MathGlyphConstruction(o, v->vertGlyphConstruction+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->vertGlyphConstruction+i, 0, sizeof(*v->vertGlyphConstruction)); break; } } } if(v->horizGlyphCount > 0){ v->horizGlyphConstruction = calloc(v->horizGlyphCount, sizeof(*v->horizGlyphConstruction)); for(int i = 0; i < v->horizGlyphCount; i++){ if(v->horizGlyphConstructionOffsets[i] == 0) continue; if(otfpushrange(o, v->horizGlyphConstructionOffsets[i], -1)) goto err; int r = read_MathGlyphConstruction(o, v->horizGlyphConstruction+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->horizGlyphConstruction+i, 0, sizeof(*v->horizGlyphConstruction)); break; } } } 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); for(int i = 0; i < v->vertGlyphCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "vertGlyphConstruction", i); print_MathGlyphConstruction(f, indent+indentΔ, o, &v->vertGlyphConstruction[i]); } for(int i = 0; i < v->horizGlyphCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "horizGlyphConstruction", i); print_MathGlyphConstruction(f, indent+indentΔ, o, &v->horizGlyphConstruction[i]); } 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_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]; if((v->coverage>>8) == 0){ if(read_KernSubtable0(o, &v->sub0) < 0){ werrstr("%s: %r", "sub0"); goto err; } } if((v->coverage>>8) == 2){ if(read_KernSubtable2(o, &v->sub2) < 0){ werrstr("%s: %r", "sub2"); goto err; } } 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%s%s%s%s\n", indent, "", "coverage", v->coverage, (v->coverage&KERN_FL_HORIZONTAL)?" KERN_FL_HORIZONTAL":"", (v->coverage&KERN_FL_MINIMUM)?" KERN_FL_MINIMUM":"", (v->coverage&KERN_FL_CROSS_STREAM)?" KERN_FL_CROSS_STREAM":"", (v->coverage&KERN_FL_OVERRIDE)?" KERN_FL_OVERRIDE":""); if((v->coverage>>8) == 0){ f->print(f->aux, "%*s%s:\n", indent, "", "sub0"); print_KernSubtable0(f, indent+indentΔ, o, &v->sub0); } if((v->coverage>>8) == 2){ f->print(f->aux, "%*s%s:\n", indent, "", "sub2"); print_KernSubtable2(f, indent+indentΔ, o, &v->sub2); } 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_GlyphData(Otf *o, GlyphData *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 8)) == nil) goto err; v->originOffsetX = b[0]<<8 | b[1]; v->originOffsetY = b[2]<<8 | b[3]; v->graphicType = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7]; return 0; err: werrstr("%s: %r", "GlyphData"); return -1; } void print_GlyphData(Otfile *f, int indent, Otf *o, GlyphData *v) { f->print(f->aux, "%*s%s: %d\n", indent, "", "originOffsetX", v->originOffsetX); f->print(f->aux, "%*s%s: %d\n", indent, "", "originOffsetY", v->originOffsetY); f->print(f->aux, "%*s%s: %c%c%c%c\n", indent, "", "graphicType", v->graphicType>>24, v->graphicType>>16, v->graphicType>>8, v->graphicType>>0); USED(o); } int read_SbixStrike(Otf *o, SbixStrike *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 4)) == nil) goto err; v->ppem = b[0]<<8 | b[1]; v->ppi = b[2]<<8 | b[3]; if((b = otfreadn(o, (o->numGlyphs+1)*4)) == nil) goto err; v->glyphDataOffsets = malloc((o->numGlyphs+1)*sizeof(*v->glyphDataOffsets)); for(int i = 0; i < (o->numGlyphs+1); i++) v->glyphDataOffsets[i] = b[0+i*4]<<24 | b[1+i*4]<<16 | b[2+i*4]<<8 | b[3+i*4]; if(o->numGlyphs > 0){ v->glyphData = calloc(o->numGlyphs, sizeof(*v->glyphData)); for(int i = 0; i < o->numGlyphs; i++){ if(v->glyphDataOffsets[i] == 0) continue; if(otfpushrange(o, v->glyphDataOffsets[i], -1)) goto err; int r = read_GlyphData(o, v->glyphData+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->glyphData+i, 0, sizeof(*v->glyphData)); break; } } } return 0; err: werrstr("%s: %r", "SbixStrike"); return -1; } void print_SbixStrike(Otfile *f, int indent, Otf *o, SbixStrike *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "ppem", v->ppem); f->print(f->aux, "%*s%s: %ud\n", indent, "", "ppi", v->ppi); for(int i = 0; i < (o->numGlyphs+1); i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "glyphDataOffsets", i, v->glyphDataOffsets[i]); for(int i = 0; i < o->numGlyphs; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "glyphData", i); print_GlyphData(f, indent+indentΔ, o, &v->glyphData[i]); } USED(o); } int read_TableSbix(Otf *o, TableSbix *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 8)) == nil) goto err; u16int version = b[0]<<8 | b[1]; if(version != 1){ werrstr("%s: invalid value: %d (%#ux)", "version", version, version); goto err; } v->flags = b[2]<<8 | b[3]; v->numStrikes = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7]; if((b = otfreadn(o, v->numStrikes*4)) == nil) goto err; v->strikeOffsets = malloc(v->numStrikes*sizeof(*v->strikeOffsets)); for(int i = 0; i < v->numStrikes; i++) v->strikeOffsets[i] = b[0+i*4]<<24 | b[1+i*4]<<16 | b[2+i*4]<<8 | b[3+i*4]; if(v->numStrikes > 0){ v->strikes = calloc(v->numStrikes, sizeof(*v->strikes)); for(int i = 0; i < v->numStrikes; i++){ if(v->strikeOffsets[i] == 0) continue; if(otfpushrange(o, v->strikeOffsets[i], -1)) goto err; int r = read_SbixStrike(o, v->strikes+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->strikes+i, 0, sizeof(*v->strikes)); break; } } } return 0; err: werrstr("%s: %r", "TableSbix"); return -1; } void print_TableSbix(Otfile *f, int indent, Otf *o, TableSbix *v) { f->print(f->aux, "%*s%s: %#ux%s\n", indent, "", "flags", v->flags, (v->flags&SBIX_FL_DRAW_OUTLINES)?" SBIX_FL_DRAW_OUTLINES":""); f->print(f->aux, "%*s%s: %ud\n", indent, "", "numStrikes", v->numStrikes); for(int i = 0; i < v->numStrikes; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "strikeOffsets", i, v->strikeOffsets[i]); for(int i = 0; i < v->numStrikes; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "strikes", i); print_SbixStrike(f, indent+indentΔ, o, &v->strikes[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); o->axisCount = v->axisCount; f->print(f->aux, "%*s%s: %ud\n", indent, "", "instanceCount", v->instanceCount); o->instanceCount = v->instanceCount; f->print(f->aux, "%*s%s: %ud\n", indent, "", "instanceSize", v->instanceSize); o->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]; if(v->itemVariationDataCount > 0){ v->itemVariationData = calloc(v->itemVariationDataCount, sizeof(*v->itemVariationData)); for(int i = 0; i < v->itemVariationDataCount; i++){ if(v->itemVariationDataOffsets[i] == 0) continue; if(otfpushrange(o, v->itemVariationDataOffsets[i], -1)) goto err; int r = read_ItemVariationData(o, v->itemVariationData+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->itemVariationData+i, 0, sizeof(*v->itemVariationData)); break; } } } 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]); for(int i = 0; i < v->itemVariationDataCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "itemVariationData", i); print_ItemVariationData(f, indent+indentΔ, o, &v->itemVariationData[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_AxisValueTable1(Otf *o, AxisValueTable1 *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 10)) == nil) goto err; v->axisIndex = b[0]<<8 | b[1]; v->flags = b[2]<<8 | b[3]; v->valueNameID = b[4]<<8 | b[5]; v->value = (b[6]<<24 | b[7]<<16 | b[8]<<8 | b[9])/65536.0f; return 0; err: werrstr("%s: %r", "AxisValueTable1"); return -1; } void print_AxisValueTable1(Otfile *f, int indent, Otf *o, AxisValueTable1 *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisIndex", v->axisIndex); f->print(f->aux, "%*s%s: %ud\n", indent, "", "flags", v->flags); f->print(f->aux, "%*s%s: %ud\n", indent, "", "valueNameID", v->valueNameID); f->print(f->aux, "%*s%s: %g\n", indent, "", "value", v->value); USED(o); } int read_AxisValueTable2(Otf *o, AxisValueTable2 *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 18)) == nil) goto err; v->axisIndex = b[0]<<8 | b[1]; v->flags = b[2]<<8 | b[3]; v->valueNameID = b[4]<<8 | b[5]; v->nominalValue = (b[6]<<24 | b[7]<<16 | b[8]<<8 | b[9])/65536.0f; v->rangeMinValue = (b[10]<<24 | b[11]<<16 | b[12]<<8 | b[13])/65536.0f; v->rangeMaxValue = (b[14]<<24 | b[15]<<16 | b[16]<<8 | b[17])/65536.0f; return 0; err: werrstr("%s: %r", "AxisValueTable2"); return -1; } void print_AxisValueTable2(Otfile *f, int indent, Otf *o, AxisValueTable2 *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisIndex", v->axisIndex); f->print(f->aux, "%*s%s: %ud\n", indent, "", "flags", v->flags); f->print(f->aux, "%*s%s: %ud\n", indent, "", "valueNameID", v->valueNameID); f->print(f->aux, "%*s%s: %g\n", indent, "", "nominalValue", v->nominalValue); f->print(f->aux, "%*s%s: %g\n", indent, "", "rangeMinValue", v->rangeMinValue); f->print(f->aux, "%*s%s: %g\n", indent, "", "rangeMaxValue", v->rangeMaxValue); USED(o); } int read_AxisValueTable3(Otf *o, AxisValueTable3 *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 14)) == nil) goto err; v->axisIndex = b[0]<<8 | b[1]; v->flags = b[2]<<8 | b[3]; v->valueNameID = b[4]<<8 | b[5]; v->value = (b[6]<<24 | b[7]<<16 | b[8]<<8 | b[9])/65536.0f; v->linkedValue = (b[10]<<24 | b[11]<<16 | b[12]<<8 | b[13])/65536.0f; return 0; err: werrstr("%s: %r", "AxisValueTable3"); return -1; } void print_AxisValueTable3(Otfile *f, int indent, Otf *o, AxisValueTable3 *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisIndex", v->axisIndex); f->print(f->aux, "%*s%s: %ud\n", indent, "", "flags", v->flags); f->print(f->aux, "%*s%s: %ud\n", indent, "", "valueNameID", v->valueNameID); f->print(f->aux, "%*s%s: %g\n", indent, "", "value", v->value); f->print(f->aux, "%*s%s: %g\n", indent, "", "linkedValue", v->linkedValue); USED(o); } int read_AxisValue(Otf *o, AxisValue *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 6)) == nil) goto err; v->axisIndex = b[0]<<8 | b[1]; v->value = (b[2]<<24 | b[3]<<16 | b[4]<<8 | b[5])/65536.0f; return 0; err: werrstr("%s: %r", "AxisValue"); return -1; } void print_AxisValue(Otfile *f, int indent, Otf *o, AxisValue *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisIndex", v->axisIndex); f->print(f->aux, "%*s%s: %g\n", indent, "", "value", v->value); USED(o); } int read_AxisValueTable4(Otf *o, AxisValueTable4 *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 6)) == nil) goto err; v->axisCount = b[0]<<8 | b[1]; v->flags = b[2]<<8 | b[3]; v->valueNameID = b[4]<<8 | b[5]; if(otfarray(o, &v->axisValues, read_AxisValue, sizeof(AxisValue), v->axisCount) < 0){ werrstr("%s: %r", "axisValues"); goto err; } return 0; err: werrstr("%s: %r", "AxisValueTable4"); return -1; } void print_AxisValueTable4(Otfile *f, int indent, Otf *o, AxisValueTable4 *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisCount", v->axisCount); f->print(f->aux, "%*s%s: %ud\n", indent, "", "flags", v->flags); f->print(f->aux, "%*s%s: %ud\n", indent, "", "valueNameID", v->valueNameID); for(int i = 0; i < v->axisCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "axisValues", i); print_AxisValue(f, indent+indentΔ, o, &v->axisValues[i]); } USED(o); } int read_AxisValueTable(Otf *o, AxisValueTable *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){ if(read_AxisValueTable1(o, &v->f1) < 0){ werrstr("%s: %r", "f1"); goto err; } } if(v->format == 2){ if(read_AxisValueTable2(o, &v->f2) < 0){ werrstr("%s: %r", "f2"); goto err; } } if(v->format == 3){ if(read_AxisValueTable3(o, &v->f3) < 0){ werrstr("%s: %r", "f3"); goto err; } } if(v->format == 4){ if(read_AxisValueTable3(o, &v->f4) < 0){ werrstr("%s: %r", "f4"); goto err; } } return 0; err: werrstr("%s: %r", "AxisValueTable"); return -1; } void print_AxisValueTable(Otfile *f, int indent, Otf *o, AxisValueTable *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, "", "f1"); print_AxisValueTable1(f, indent+indentΔ, o, &v->f1); } if(v->format == 2){ f->print(f->aux, "%*s%s:\n", indent, "", "f2"); print_AxisValueTable2(f, indent+indentΔ, o, &v->f2); } if(v->format == 3){ f->print(f->aux, "%*s%s:\n", indent, "", "f3"); print_AxisValueTable3(f, indent+indentΔ, o, &v->f3); } if(v->format == 4){ f->print(f->aux, "%*s%s:\n", indent, "", "f4"); print_AxisValueTable3(f, indent+indentΔ, o, &v->f4); } 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->axisValueTableOffsets = malloc(o->axisValueCount*sizeof(*v->axisValueTableOffsets)); for(int i = 0; i < o->axisValueCount; i++) v->axisValueTableOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if(o->axisValueCount > 0){ v->axisValueTables = calloc(o->axisValueCount, sizeof(*v->axisValueTables)); for(int i = 0; i < o->axisValueCount; i++){ if(v->axisValueTableOffsets[i] == 0) continue; if(otfpushrange(o, v->axisValueTableOffsets[i], -1)) goto err; int r = read_AxisValueTable(o, v->axisValueTables+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->axisValueTables+i, 0, sizeof(*v->axisValueTables)); break; } } } 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, "", "axisValueTableOffsets", i, v->axisValueTableOffsets[i]); for(int i = 0; i < o->axisValueCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "axisValueTables", i); print_AxisValueTable(f, indent+indentΔ, o, &v->axisValueTables[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); o->designAxisSize = v->designAxisSize; f->print(f->aux, "%*s%s: %ud\n", indent, "", "designAxisCount", v->designAxisCount); o->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); o->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%s%s%s%s\n", indent, "", "rangeGaspBehavior", v->rangeGaspBehavior, (v->rangeGaspBehavior&GASP_GRIDFIT)?" GASP_GRIDFIT":"", (v->rangeGaspBehavior&GASP_DOGRAY)?" GASP_DOGRAY":"", (v->rangeGaspBehavior&GASP_SYMMETRIC_GRIDFIT)?" GASP_SYMMETRIC_GRIDFIT":"", (v->rangeGaspBehavior&GASP_SYMMETRIC_SMOOTHING)?" GASP_SYMMETRIC_SMOOTHING":""); 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((v->tupleIndex&TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE) != 0){ if(read_Tuple(o, &v->peakTuple) < 0){ werrstr("%s: %r", "peakTuple"); goto err; } } if((v->tupleIndex&TUPLEINDEX_FL_INTERMEDIATE_REGION) != 0){ if(read_Tuple(o, &v->intermediateStartTuple) < 0){ werrstr("%s: %r", "intermediateStartTuple"); goto err; } } if((v->tupleIndex&TUPLEINDEX_FL_INTERMEDIATE_REGION) != 0){ 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":""); if((v->tupleIndex&TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE) != 0){ f->print(f->aux, "%*s%s:\n", indent, "", "peakTuple"); print_Tuple(f, indent+indentΔ, o, &v->peakTuple); } if((v->tupleIndex&TUPLEINDEX_FL_INTERMEDIATE_REGION) != 0){ f->print(f->aux, "%*s%s:\n", indent, "", "intermediateStartTuple"); print_Tuple(f, indent+indentΔ, o, &v->intermediateStartTuple); } if((v->tupleIndex&TUPLEINDEX_FL_INTERMEDIATE_REGION) != 0){ 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]; o->axisCount = v->axisCount; 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->flags&GVAR_FL_LONG_OFFSETS) == 0){ if(v->glyphVariationDataArrayOffset != 0 && v->glyphCount > 0){ v->glyphVariationData = calloc(v->glyphCount, sizeof(*v->glyphVariationData)); for(int i = 0; i < v->glyphCount; i++){ if(otfpushrange(o, v->glyphVariationDataArrayOffset+v->glyphVariationDataOffsetsShort[i], -1)) goto err; int r = read_GlyphVariationData(o, v->glyphVariationData+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->glyphVariationData+i, 0, sizeof(*v->glyphVariationData)); break; } } } } if((v->flags&GVAR_FL_LONG_OFFSETS) != 0){ if(v->glyphVariationDataArrayOffset != 0 && v->glyphCount > 0){ v->glyphVariationData = calloc(v->glyphCount, sizeof(*v->glyphVariationData)); for(int i = 0; i < v->glyphCount; i++){ if(otfpushrange(o, v->glyphVariationDataArrayOffset+v->glyphVariationDataOffsetsLong[i], -1)) goto err; int r = read_GlyphVariationData(o, v->glyphVariationData+i); if(otfpoprange(o) < 0) goto err; if(r < 0){ memset(v->glyphVariationData+i, 0, sizeof(*v->glyphVariationData)); break; } } } } 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); o->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]); } if((v->flags&GVAR_FL_LONG_OFFSETS) == 0){ for(int i = 0; i < v->glyphCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "glyphVariationData", i); print_GlyphVariationData(f, indent+indentΔ, o, &v->glyphVariationData[i]); } } if((v->flags&GVAR_FL_LONG_OFFSETS) != 0){ for(int i = 0; i < v->glyphCount; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "glyphVariationData", i); print_GlyphVariationData(f, indent+indentΔ, o, &v->glyphVariationData[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_BaseGlyph(Otf *o, BaseGlyph *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 6)) == nil) goto err; v->glyphID = b[0]<<8 | b[1]; v->firstLayerIndex = b[2]<<8 | b[3]; v->numLayers = b[4]<<8 | b[5]; return 0; err: werrstr("%s: %r", "BaseGlyph"); return -1; } void print_BaseGlyph(Otfile *f, int indent, Otf *o, BaseGlyph *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID); f->print(f->aux, "%*s%s: %ud\n", indent, "", "firstLayerIndex", v->firstLayerIndex); f->print(f->aux, "%*s%s: %ud\n", indent, "", "numLayers", v->numLayers); USED(o); } int read_Layer(Otf *o, Layer *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 4)) == nil) goto err; v->glyphID = b[0]<<8 | b[1]; v->paletteIndex = b[2]<<8 | b[3]; return 0; err: werrstr("%s: %r", "Layer"); return -1; } void print_Layer(Otfile *f, int indent, Otf *o, Layer *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID); f->print(f->aux, "%*s%s: %ud\n", indent, "", "paletteIndex", v->paletteIndex); USED(o); } int read_TableCOLR(Otf *o, TableCOLR *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 14)) == nil) goto err; v->version = b[0]<<8 | b[1]; if(v->version != 0){ werrstr("%s: invalid value: %d (%#ux)", "version", v->version, v->version); goto err; } v->numBaseGlyphRecords = b[2]<<8 | b[3]; v->baseGlyphRecordsOffset = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7]; v->layerRecordsOffset = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11]; v->numLayerRecords = b[12]<<8 | b[13]; if(v->baseGlyphRecordsOffset != 0){ if(otfpushrange(o, v->baseGlyphRecordsOffset, -1) < 0) goto err; if(otfarray(o, &v->baseGlyphs, read_BaseGlyph, sizeof(BaseGlyph), v->numBaseGlyphRecords) < 0){ werrstr("%s: %r", "baseGlyphs"); goto err; } if(otfpoprange(o) < 0) goto err; } if(v->layerRecordsOffset != 0){ if(otfpushrange(o, v->layerRecordsOffset, -1) < 0) goto err; if(otfarray(o, &v->layers, read_Layer, sizeof(Layer), v->numLayerRecords) < 0){ werrstr("%s: %r", "layers"); goto err; } if(otfpoprange(o) < 0) goto err; } return 0; err: werrstr("%s: %r", "TableCOLR"); return -1; } void print_TableCOLR(Otfile *f, int indent, Otf *o, TableCOLR *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "version", v->version); f->print(f->aux, "%*s%s: %ud\n", indent, "", "numBaseGlyphRecords", v->numBaseGlyphRecords); f->print(f->aux, "%*s%s: %ud\n", indent, "", "baseGlyphRecordsOffset", v->baseGlyphRecordsOffset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "layerRecordsOffset", v->layerRecordsOffset); f->print(f->aux, "%*s%s: %ud\n", indent, "", "numLayerRecords", v->numLayerRecords); for(int i = 0; i < v->numBaseGlyphRecords; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "baseGlyphs", i); print_BaseGlyph(f, indent+indentΔ, o, &v->baseGlyphs[i]); } for(int i = 0; i < v->numLayerRecords; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "layers", i); print_Layer(f, indent+indentΔ, o, &v->layers[i]); } USED(o); } int read_ColorRecord(Otf *o, ColorRecord *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 4)) == nil) goto err; v->blue = b[0]; v->greed = b[1]; v->red = b[2]; v->alpha = b[3]; return 0; err: werrstr("%s: %r", "ColorRecord"); return -1; } void print_ColorRecord(Otfile *f, int indent, Otf *o, ColorRecord *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "blue", v->blue); f->print(f->aux, "%*s%s: %ud\n", indent, "", "greed", v->greed); f->print(f->aux, "%*s%s: %ud\n", indent, "", "red", v->red); f->print(f->aux, "%*s%s: %ud\n", indent, "", "alpha", v->alpha); USED(o); } int read_TableCPAL(Otf *o, TableCPAL *v) { u8int *b = nil; USED(b); if((b = otfreadn(o, 12)) == nil) goto err; v->version = b[0]<<8 | b[1]; if(v->version != 0){ werrstr("%s: invalid value: %d (%#ux)", "version", v->version, v->version); goto err; } v->numPaletteEntries = b[2]<<8 | b[3]; v->numPalettes = b[4]<<8 | b[5]; v->numColorRecords = b[6]<<8 | b[7]; v->colorRecordsArrayOffset = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11]; if((b = otfreadn(o, v->numPalettes*2)) == nil) goto err; v->colorRecordIndices = malloc(v->numPalettes*sizeof(*v->colorRecordIndices)); for(int i = 0; i < v->numPalettes; i++) v->colorRecordIndices[i] = b[0+i*2]<<8 | b[1+i*2]; if(v->colorRecordsArrayOffset != 0){ if(otfpushrange(o, v->colorRecordsArrayOffset, -1) < 0) goto err; if(otfarray(o, &v->colorRecords, read_ColorRecord, sizeof(ColorRecord), v->numColorRecords) < 0){ werrstr("%s: %r", "colorRecords"); goto err; } if(otfpoprange(o) < 0) goto err; } return 0; err: werrstr("%s: %r", "TableCPAL"); return -1; } void print_TableCPAL(Otfile *f, int indent, Otf *o, TableCPAL *v) { f->print(f->aux, "%*s%s: %ud\n", indent, "", "version", v->version); f->print(f->aux, "%*s%s: %ud\n", indent, "", "numPaletteEntries", v->numPaletteEntries); f->print(f->aux, "%*s%s: %ud\n", indent, "", "numPalettes", v->numPalettes); f->print(f->aux, "%*s%s: %ud\n", indent, "", "numColorRecords", v->numColorRecords); f->print(f->aux, "%*s%s: %ud\n", indent, "", "colorRecordsArrayOffset", v->colorRecordsArrayOffset); for(int i = 0; i < v->numPalettes; i++) f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "colorRecordIndices", i, v->colorRecordIndices[i]); for(int i = 0; i < v->numColorRecords; i++){ f->print(f->aux, "%*s%s[%d]:\n", indent, "", "colorRecords", i); print_ColorRecord(f, indent+indentΔ, o, &v->colorRecords[i]); } 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); v->cmap = nil; 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); v->head = nil; 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); v->hhea = nil; 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); v->maxp = nil; 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); v->hmtx = nil; 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); v->post = nil; 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); v->name = nil; 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); v->ebdt = nil; 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); v->eblc = nil; 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); v->gdef = nil; 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); v->gpos = nil; 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); v->gsub = nil; 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); v->math = nil; 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); v->kern = nil; 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); v->loca = nil; break; } rec->parsed = v->loca; rec->print = (void*)print_TableLoca; break; case (u32int)('s'<<24|'b'<<16|'i'<<8|'x'): if(v->sbix != nil) break; v->sbix = calloc(1, sizeof(TableSbix)); if(read_TableSbix(o, v->sbix) < 0){ free(v->sbix); v->sbix = nil; goto err; } rec->parsed = v->sbix; rec->print = (void*)print_TableSbix; 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); v->fvar = nil; 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); v->hvar = nil; 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); v->fftm = nil; 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); v->dsig = nil; 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); v->stat = nil; 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); v->gasp = nil; 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); v->gvar = nil; 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); v->avar = nil; 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); v->os∕2 = nil; goto err; } rec->parsed = v->os∕2; rec->print = (void*)print_TableOS∕2; break; case (u32int)('C'<<24|'O'<<16|'L'<<8|'R'): if(v->colr != nil) break; v->colr = calloc(1, sizeof(TableCOLR)); if(read_TableCOLR(o, v->colr) < 0){ free(v->colr); v->colr = nil; goto err; } rec->parsed = v->colr; rec->print = (void*)print_TableCOLR; break; case (u32int)('C'<<24|'P'<<16|'A'<<8|'L'): if(v->cpal != nil) break; v->cpal = calloc(1, sizeof(TableCPAL)); if(read_TableCPAL(o, v->cpal) < 0){ free(v->cpal); v->cpal = nil; goto err; } rec->parsed = v->cpal; rec->print = (void*)print_TableCPAL; 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); }