ref: f152a7fbaefb8b7f2dee22e4e3d54ed1afedd301
dir: /otf.c/
/* this file is generated. do not modify. */ #include <u.h> #include <libc.h> #include <bio.h> #include "otf.h" typedef struct Range Range; struct Otf { Biobuf *f; Range *r; u8int *buf; int bufsz; int off; /* extra fields to simplify parsing */ s16int indexToLocFormat; u16int numberOfHMetrics; u16int numGlyphs; u16int firstGlyphIndex; u16int lastGlyphIndex; }; struct Range { int start; int len; int prevoff; Range *par; }; Otf * otfopen(char *path) { Otf *o; Biobuf *f; if((f = Bopen(path, OREAD)) == nil) return nil; if((o = calloc(1, sizeof(*o))) == nil){ werrstr("no memory"); Bterm(f); }else{ o->f = f; } return o; } 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 = Bseek(o->f, 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 = Bseek(o->f, 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 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 = Bread(o->f, 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; } int read_SubHeader(Otf *o, SubHeader *v) { u8int *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(Biobuf *f, int indent, Otf *o, SubHeader *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "firstCode", v->firstCode); Bprint(f, "%*s%s: %ud\n", indent, "", "entryCode", v->entryCode); Bprint(f, "%*s%s: %d\n", indent, "", "idDelta", v->idDelta); Bprint(f, "%*s%s: %ud\n", indent, "", "idRangeOffset", v->idRangeOffset); USED(o); } int read_MapGroup(Otf *o, MapGroup *v) { u8int *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(Biobuf *f, int indent, Otf *o, MapGroup *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "startCharCode", v->startCharCode); Bprint(f, "%*s%s: %ud\n", indent, "", "endCharCode", v->endCharCode); Bprint(f, "%*s%s: %ud\n", indent, "", "startGlyphID", v->startGlyphID); USED(o); } int read_SubtableCmap0(Otf *o, SubtableCmap0 *v) { u8int *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(Biobuf *f, int indent, Otf *o, SubtableCmap0 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "language", v->language); for(int i = 0; i < 256; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "glyphIdArray", i, v->glyphIdArray[i]); USED(o); } int read_SubtableCmap2(Otf *o, SubtableCmap2 *v) { u8int *b; if((b = otfreadn(o, 516)) == 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->subHeaderKeys[i] = b[4+i*2]<<8 | b[5+i*2]; return 0; err: werrstr("%s: %r", "SubtableCmap2"); return -1; } void print_SubtableCmap2(Biobuf *f, int indent, Otf *o, SubtableCmap2 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "language", v->language); for(int i = 0; i < 256; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "subHeaderKeys", i, v->subHeaderKeys[i]); USED(o); } int read_SubtableCmap4(Otf *o, SubtableCmap4 *v) { u8int *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]; 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]; return 0; err: werrstr("%s: %r", "SubtableCmap4"); return -1; } void print_SubtableCmap4(Biobuf *f, int indent, Otf *o, SubtableCmap4 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "language", v->language); Bprint(f, "%*s%s: %ud\n", indent, "", "segCountX2", v->segCountX2); Bprint(f, "%*s%s: %ud\n", indent, "", "searchRange", v->searchRange); Bprint(f, "%*s%s: %ud\n", indent, "", "entrySelector", v->entrySelector); Bprint(f, "%*s%s: %ud\n", indent, "", "rangeShift", v->rangeShift); for(int i = 0; i < (v->segCountX2/2); i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "endCode", i, v->endCode[i]); for(int i = 0; i < (v->segCountX2/2); i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "startCode", i, v->startCode[i]); for(int i = 0; i < (v->segCountX2/2); i++) Bprint(f, "%*s%s[%d]: %d\n", indent, "", "idDelta", i, v->idDelta[i]); for(int i = 0; i < (v->segCountX2/2); i++) Bprint(f, "%*s%s[%d]: %d\n", indent, "", "idRangeOffset", i, v->idRangeOffset[i]); USED(o); } int read_SubtableCmap6(Otf *o, SubtableCmap6 *v) { u8int *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(Biobuf *f, int indent, Otf *o, SubtableCmap6 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "language", v->language); Bprint(f, "%*s%s: %ud\n", indent, "", "firstCode", v->firstCode); Bprint(f, "%*s%s: %ud\n", indent, "", "entryCount", v->entryCount); for(int i = 0; i < v->entryCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "glyphIdArray", i, v->glyphIdArray[i]); USED(o); } int read_SubtableCmap8(Otf *o, SubtableCmap8 *v) { u8int *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(Biobuf *f, int indent, Otf *o, SubtableCmap8 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "language", v->language); for(int i = 0; i < 8192; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "is32", i, v->is32[i]); Bprint(f, "%*s%s: %ud\n", indent, "", "numGroups", v->numGroups); for(int i = 0; i < v->numGroups; i++){ Bprint(f, "%*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; 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]; return 0; err: werrstr("%s: %r", "SubtableCmap10"); return -1; } void print_SubtableCmap10(Biobuf *f, int indent, Otf *o, SubtableCmap10 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "reserved", v->reserved); Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "language", v->language); Bprint(f, "%*s%s: %ud\n", indent, "", "startCharCode", v->startCharCode); Bprint(f, "%*s%s: %ud\n", indent, "", "numChars", v->numChars); USED(o); } int read_SubtableCmap12or13(Otf *o, SubtableCmap12or13 *v) { u8int *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(Biobuf *f, int indent, Otf *o, SubtableCmap12or13 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "reserved", v->reserved); Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "language", v->language); Bprint(f, "%*s%s: %ud\n", indent, "", "numGroups", v->numGroups); for(int i = 0; i < v->numGroups; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, UnicodeRange *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "startUnicodeValue", v->startUnicodeValue); Bprint(f, "%*s%s: %ud\n", indent, "", "additionalCount", v->additionalCount); USED(o); } int read_DefaultUVS(Otf *o, DefaultUVS *v) { u8int *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(Biobuf *f, int indent, Otf *o, DefaultUVS *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "numUnicodeValueRanges", v->numUnicodeValueRanges); for(int i = 0; i < v->numUnicodeValueRanges; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, UVSMapping *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "unicodeValue", v->unicodeValue); Bprint(f, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID); USED(o); } int read_NonDefaultUVS(Otf *o, NonDefaultUVS *v) { u8int *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(Biobuf *f, int indent, Otf *o, NonDefaultUVS *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "numUVSMappings", v->numUVSMappings); for(int i = 0; i < v->numUVSMappings; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, VariationSelector *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "varSelector", v->varSelector); Bprint(f, "%*s%s: %ud\n", indent, "", "defaultUVSOffset", v->defaultUVSOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "nonDefaultUVSOffset", v->nonDefaultUVSOffset); Bprint(f, "%*s%s:\n", indent, "", "defaultUVS"); if(v->defaultUVS != nil) print_DefaultUVS(f, indent+indentΔ, o, v->defaultUVS); Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, SubtableCmap14 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "numVarSelectorRecords", v->numVarSelectorRecords); for(int i = 0; i < v->numVarSelectorRecords; i++){ Bprint(f, "%*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; 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 (0x%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(Biobuf *f, int indent, Otf *o, SubtableCmap *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "format", v->format); if(v->format == 0){ Bprint(f, "%*s%s:\n", indent, "", "sub0"); print_SubtableCmap0(f, indent+indentΔ, o, &v->sub0); } if(v->format == 2){ Bprint(f, "%*s%s:\n", indent, "", "sub2"); print_SubtableCmap2(f, indent+indentΔ, o, &v->sub2); } if(v->format == 4){ Bprint(f, "%*s%s:\n", indent, "", "sub4"); print_SubtableCmap4(f, indent+indentΔ, o, &v->sub4); } if(v->format == 6){ Bprint(f, "%*s%s:\n", indent, "", "sub6"); print_SubtableCmap6(f, indent+indentΔ, o, &v->sub6); } if(v->format == 8){ Bprint(f, "%*s%s:\n", indent, "", "sub8"); print_SubtableCmap8(f, indent+indentΔ, o, &v->sub8); } if(v->format == 10){ Bprint(f, "%*s%s:\n", indent, "", "sub10"); print_SubtableCmap10(f, indent+indentΔ, o, &v->sub10); } if(v->format == 12 || v->format == 13){ Bprint(f, "%*s%s:\n", indent, "", "sub12or13"); print_SubtableCmap12or13(f, indent+indentΔ, o, &v->sub12or13); } if(v->format == 14){ Bprint(f, "%*s%s:\n", indent, "", "sub14"); print_SubtableCmap14(f, indent+indentΔ, o, &v->sub14); } USED(o); } int read_EncodingRecord(Otf *o, EncodingRecord *v) { u8int *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 (0x%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(Biobuf *f, int indent, Otf *o, EncodingRecord *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "platformID", v->platformID); Bprint(f, "%*s%s: %ud\n", indent, "", "encodingID", v->encodingID); Bprint(f, "%*s%s: %ud\n", indent, "", "subtableOffset", v->subtableOffset); Bprint(f, "%*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; if((b = otfreadn(o, 4)) == nil) goto err; u16int version = b[0]<<8 | b[1]; if(version != 0){ werrstr("%s: invalid value: %d (0x%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; } return 0; err: werrstr("%s: %r", "TableCmap"); return -1; } void print_TableCmap(Biobuf *f, int indent, Otf *o, TableCmap *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "numTables", v->numTables); for(int i = 0; i < v->numTables; i++){ Bprint(f, "%*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; if((b = otfreadn(o, 54)) == nil) goto err; u16int majorVersion = b[0]<<8 | b[1]; if(majorVersion != 1){ werrstr("%s: invalid value: %d (0x%ux)", "majorVersion", majorVersion, majorVersion); goto err; } u16int minorVersion = b[2]<<8 | b[3]; if(minorVersion != 0){ werrstr("%s: invalid value: %d (0x%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 (0x%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 (0x%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 (0x%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 (0x%ux)", "indexToLocFormat", v->indexToLocFormat, v->indexToLocFormat); goto err; } s16int glyphDataFormat = b[52]<<8 | b[53]; if(glyphDataFormat != 0){ werrstr("%s: invalid value: %d (0x%ux)", "glyphDataFormat", glyphDataFormat, glyphDataFormat); goto err; } return 0; err: werrstr("%s: %r", "TableHead"); return -1; } void print_TableHead(Biobuf *f, int indent, Otf *o, TableHead *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "flags", v->flags); Bprint(f, "%*s%s: %ud\n", indent, "", "unitsPerEm", v->unitsPerEm); Bprint(f, "%*s%s: %T\n", indent, "", "created", v->created); Bprint(f, "%*s%s: %T\n", indent, "", "modified", v->modified); Bprint(f, "%*s%s: %d\n", indent, "", "xMin", v->xMin); Bprint(f, "%*s%s: %d\n", indent, "", "yMin", v->yMin); Bprint(f, "%*s%s: %d\n", indent, "", "xMax", v->xMax); Bprint(f, "%*s%s: %d\n", indent, "", "yMax", v->yMax); Bprint(f, "%*s%s: %ud\n", indent, "", "macStyle", v->macStyle); Bprint(f, "%*s%s: %ud\n", indent, "", "lowestRecPPEM", v->lowestRecPPEM); Bprint(f, "%*s%s: %d\n", indent, "", "indexToLocFormat", v->indexToLocFormat); USED(o); } int read_TableHhea(Otf *o, TableHhea *v) { u8int *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 (0x%ux)", "majorVersion", v->majorVersion, v->majorVersion); goto err; } v->minorVersion = b[2]<<8 | b[3]; if(v->minorVersion != 0){ werrstr("%s: invalid value: %d (0x%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 (0x%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(Biobuf *f, int indent, Otf *o, TableHhea *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "majorVersion", v->majorVersion); Bprint(f, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion); Bprint(f, "%*s%s: %d\n", indent, "", "ascender", v->ascender); Bprint(f, "%*s%s: %d\n", indent, "", "descender", v->descender); Bprint(f, "%*s%s: %d\n", indent, "", "lineGap", v->lineGap); Bprint(f, "%*s%s: %ud\n", indent, "", "advanceWidthMax", v->advanceWidthMax); Bprint(f, "%*s%s: %d\n", indent, "", "minLeftSideBearing", v->minLeftSideBearing); Bprint(f, "%*s%s: %d\n", indent, "", "minRightSideBearing", v->minRightSideBearing); Bprint(f, "%*s%s: %d\n", indent, "", "xMaxExtent", v->xMaxExtent); Bprint(f, "%*s%s: %d\n", indent, "", "caretSlopeRise", v->caretSlopeRise); Bprint(f, "%*s%s: %d\n", indent, "", "caretSlopeRun", v->caretSlopeRun); Bprint(f, "%*s%s: %d\n", indent, "", "caretOffset", v->caretOffset); Bprint(f, "%*s%s: %d\n", indent, "", "metricDataFormat", v->metricDataFormat); Bprint(f, "%*s%s: %ud\n", indent, "", "numberOfHMetrics", v->numberOfHMetrics); USED(o); } int read_LongHorMetric(Otf *o, LongHorMetric *v) { u8int *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(Biobuf *f, int indent, Otf *o, LongHorMetric *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "advanceWidth", v->advanceWidth); Bprint(f, "%*s%s: %d\n", indent, "", "lsb", v->lsb); USED(o); } int read_TableMaxp(Otf *o, TableMaxp *v) { u8int *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 (0x%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(Biobuf *f, int indent, Otf *o, TableMaxp *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "numGlyphs", v->numGlyphs); USED(o); } int read_TableHmtx(Otf *o, TableHmtx *v) { u8int *b; if(otfarray(o, &v->hMetrics, read_LongHorMetric, sizeof(LongHorMetric), (o->numberOfHMetrics+0)) < 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(Biobuf *f, int indent, Otf *o, TableHmtx *v) { for(int i = 0; i < (o->numberOfHMetrics+0); i++){ Bprint(f, "%*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++) Bprint(f, "%*s%s[%d]: %d\n", indent, "", "leftSideBearings", i, v->leftSideBearings[i]); USED(o); } int read_TablePost(Otf *o, TablePost *v) { u8int *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 (0x%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(Biobuf *f, int indent, Otf *o, TablePost *v) { Bprint(f, "%*s%s: %g\n", indent, "", "italicAngle", v->italicAngle); Bprint(f, "%*s%s: %d\n", indent, "", "underlinePosition", v->underlinePosition); Bprint(f, "%*s%s: %d\n", indent, "", "underlineThickness", v->underlineThickness); Bprint(f, "%*s%s: %ud\n", indent, "", "isFixedPitch", v->isFixedPitch); USED(o); } int read_NameRecord(Otf *o, NameRecord *v) { u8int *b; if((b = otfreadn(o, 12)) == nil) goto err; v->platformID = b[0]<<8 | b[1]; v->encodingID = b[2]<<8 | b[3]; v->languageID = b[4]<<8 | b[5]; v->nameID = b[6]<<8 | b[7]; v->length = b[8]<<8 | b[9]; v->stringOffset = b[10]<<8 | b[11]; return 0; err: werrstr("%s: %r", "NameRecord"); return -1; } void print_NameRecord(Biobuf *f, int indent, Otf *o, NameRecord *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "platformID", v->platformID); Bprint(f, "%*s%s: %ud\n", indent, "", "encodingID", v->encodingID); Bprint(f, "%*s%s: %ud\n", indent, "", "languageID", v->languageID); Bprint(f, "%*s%s: %ud\n", indent, "", "nameID", v->nameID); Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "stringOffset", v->stringOffset); USED(o); } int read_LangTagRecord(Otf *o, LangTagRecord *v) { u8int *b; if((b = otfreadn(o, 4)) == nil) goto err; v->length = b[0]<<8 | b[1]; v->langTagOffset = b[2]<<8 | b[3]; return 0; err: werrstr("%s: %r", "LangTagRecord"); return -1; } void print_LangTagRecord(Biobuf *f, int indent, Otf *o, LangTagRecord *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "langTagOffset", v->langTagOffset); USED(o); } int read_TableName(Otf *o, TableName *v) { u8int *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 (0x%ux)", "version", v->version, v->version); goto err; } v->count = b[2]<<8 | b[3]; v->storageOffset = b[4]<<8 | b[5]; 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(Biobuf *f, int indent, Otf *o, TableName *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "version", v->version); Bprint(f, "%*s%s: %ud\n", indent, "", "count", v->count); Bprint(f, "%*s%s: %ud\n", indent, "", "storageOffset", v->storageOffset); for(int i = 0; i < v->count; i++){ Bprint(f, "%*s%s[%d]:\n", indent, "", "nameRecord", i); print_NameRecord(f, indent+indentΔ, o, &v->nameRecord[i]); } if(v->version >= 1) Bprint(f, "%*s%s: %ud\n", indent, "", "langTagCount", v->langTagCount); if(v->version >= 1){ for(int i = 0; i < v->langTagCount; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, BigGlyphMetrics *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "height", v->height); Bprint(f, "%*s%s: %ud\n", indent, "", "width", v->width); Bprint(f, "%*s%s: %d\n", indent, "", "horiBearingX", v->horiBearingX); Bprint(f, "%*s%s: %d\n", indent, "", "horiBearingY", v->horiBearingY); Bprint(f, "%*s%s: %ud\n", indent, "", "horiAdvance", v->horiAdvance); Bprint(f, "%*s%s: %d\n", indent, "", "vertBearingX", v->vertBearingX); Bprint(f, "%*s%s: %d\n", indent, "", "vertBearingY", v->vertBearingY); Bprint(f, "%*s%s: %ud\n", indent, "", "vertAdvance", v->vertAdvance); USED(o); } int read_SmallGlyphMetrics(Otf *o, SmallGlyphMetrics *v) { u8int *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(Biobuf *f, int indent, Otf *o, SmallGlyphMetrics *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "height", v->height); Bprint(f, "%*s%s: %ud\n", indent, "", "width", v->width); Bprint(f, "%*s%s: %d\n", indent, "", "bearingX", v->bearingX); Bprint(f, "%*s%s: %d\n", indent, "", "bearingY", v->bearingY); Bprint(f, "%*s%s: %ud\n", indent, "", "advance", v->advance); USED(o); } int read_SbitLineMetrics(Otf *o, SbitLineMetrics *v) { u8int *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(Biobuf *f, int indent, Otf *o, SbitLineMetrics *v) { Bprint(f, "%*s%s: %d\n", indent, "", "ascender", v->ascender); Bprint(f, "%*s%s: %d\n", indent, "", "descender", v->descender); Bprint(f, "%*s%s: %ud\n", indent, "", "widthMax", v->widthMax); Bprint(f, "%*s%s: %d\n", indent, "", "caretSlopeNumerator", v->caretSlopeNumerator); Bprint(f, "%*s%s: %d\n", indent, "", "caretSlopeDenumerator", v->caretSlopeDenumerator); Bprint(f, "%*s%s: %d\n", indent, "", "caretOffset", v->caretOffset); Bprint(f, "%*s%s: %d\n", indent, "", "minOriginSB", v->minOriginSB); Bprint(f, "%*s%s: %d\n", indent, "", "minAdvanceSB", v->minAdvanceSB); Bprint(f, "%*s%s: %d\n", indent, "", "maxBeforeBL", v->maxBeforeBL); Bprint(f, "%*s%s: %d\n", indent, "", "minAfterBL", v->minAfterBL); USED(o); } int read_IndexSubtable1(Otf *o, IndexSubtable1 *v) { u8int *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(Biobuf *f, int indent, Otf *o, IndexSubtable1 *v) { for(int i = 0; i < ((o->lastGlyphIndex-o->firstGlyphIndex)+2); i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "sbitOffsets", i, v->sbitOffsets[i]); USED(o); } int read_IndexSubtable2(Otf *o, IndexSubtable2 *v) { u8int *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(Biobuf *f, int indent, Otf *o, IndexSubtable2 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "imageSize", v->imageSize); Bprint(f, "%*s%s:\n", indent, "", "bigMetrics"); print_BigGlyphMetrics(f, indent+indentΔ, o, &v->bigMetrics); USED(o); } int read_IndexSubtable3(Otf *o, IndexSubtable3 *v) { u8int *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(Biobuf *f, int indent, Otf *o, IndexSubtable3 *v) { for(int i = 0; i < ((o->lastGlyphIndex-o->firstGlyphIndex)+2); i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "sbitOffsets", i, v->sbitOffsets[i]); USED(o); } int read_GlyphIdOffsetPair(Otf *o, GlyphIdOffsetPair *v) { u8int *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(Biobuf *f, int indent, Otf *o, GlyphIdOffsetPair *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID); Bprint(f, "%*s%s: %ud\n", indent, "", "sbitOffset", v->sbitOffset); USED(o); } int read_IndexSubtable4(Otf *o, IndexSubtable4 *v) { u8int *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(Biobuf *f, int indent, Otf *o, IndexSubtable4 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "numGlyphs", v->numGlyphs); for(int i = 0; i < (v->numGlyphs+1); i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, IndexSubtable5 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "imageSize", v->imageSize); Bprint(f, "%*s%s:\n", indent, "", "bigMetrics"); print_BigGlyphMetrics(f, indent+indentΔ, o, &v->bigMetrics); Bprint(f, "%*s%s: %ud\n", indent, "", "numGlyphs", v->numGlyphs); for(int i = 0; i < v->numGlyphs; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "glyphIdArray", i, v->glyphIdArray[i]); USED(o); } int read_IndexSubtable(Otf *o, IndexSubtable *v) { u8int *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 (0x%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(Biobuf *f, int indent, Otf *o, IndexSubtable *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "indexFormat", v->indexFormat); Bprint(f, "%*s%s: %ud\n", indent, "", "imageFormat", v->imageFormat); Bprint(f, "%*s%s: %ud\n", indent, "", "imageDataOffset", v->imageDataOffset); if(v->indexFormat == 1){ Bprint(f, "%*s%s:\n", indent, "", "sub1"); print_IndexSubtable1(f, indent+indentΔ, o, &v->sub1); } if(v->indexFormat == 2){ Bprint(f, "%*s%s:\n", indent, "", "sub2"); print_IndexSubtable2(f, indent+indentΔ, o, &v->sub2); } if(v->indexFormat == 3){ Bprint(f, "%*s%s:\n", indent, "", "sub3"); print_IndexSubtable3(f, indent+indentΔ, o, &v->sub3); } if(v->indexFormat == 4){ Bprint(f, "%*s%s:\n", indent, "", "sub4"); print_IndexSubtable4(f, indent+indentΔ, o, &v->sub4); } if(v->indexFormat == 5){ Bprint(f, "%*s%s:\n", indent, "", "sub5"); print_IndexSubtable5(f, indent+indentΔ, o, &v->sub5); } USED(o); } int read_IndexSubtableRecord(Otf *o, IndexSubtableRecord *v) { u8int *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(Biobuf *f, int indent, Otf *o, IndexSubtableRecord *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "firstGlyphIndex", v->firstGlyphIndex); Bprint(f, "%*s%s: %ud\n", indent, "", "lastGlyphIndex", v->lastGlyphIndex); Bprint(f, "%*s%s: %ud\n", indent, "", "indexSubtableOffset", v->indexSubtableOffset); Bprint(f, "%*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; if((b = otfreadn(o, 16)) == nil) goto err; v->indexSubtableListOffset = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3]; v->indexSubtableListSize = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7]; v->numberOfIndexSubtables = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11]; if(read_SbitLineMetrics(o, &v->hori) < 0){ werrstr("%s: %r", "hori"); goto err; } if(read_SbitLineMetrics(o, &v->vert) < 0){ werrstr("%s: %r", "vert"); goto err; } if((b = otfreadn(o, 8)) == nil) goto err; v->startGlyphIndex = b[0]<<8 | b[1]; v->endGlyphIndex = b[2]<<8 | b[3]; v->ppemX = b[4]; v->ppemY = b[5]; v->bitDepth = b[6]; v->flags = b[7]; if(v->indexSubtableListOffset != 0){ if(otfpushrange(o, v->indexSubtableListOffset, -1) < 0) goto err; if(otfarray(o, &v->indexSubtableList, read_IndexSubtableRecord, sizeof(IndexSubtableRecord), v->numberOfIndexSubtables) < 0){ werrstr("%s: %r", "indexSubtableList"); goto err; } if(otfpoprange(o) < 0) goto err; } return 0; err: werrstr("%s: %r", "BitmapSize"); return -1; } void print_BitmapSize(Biobuf *f, int indent, Otf *o, BitmapSize *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "indexSubtableListOffset", v->indexSubtableListOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "indexSubtableListSize", v->indexSubtableListSize); Bprint(f, "%*s%s: %ud\n", indent, "", "numberOfIndexSubtables", v->numberOfIndexSubtables); Bprint(f, "%*s%s:\n", indent, "", "hori"); print_SbitLineMetrics(f, indent+indentΔ, o, &v->hori); Bprint(f, "%*s%s:\n", indent, "", "vert"); print_SbitLineMetrics(f, indent+indentΔ, o, &v->vert); Bprint(f, "%*s%s: %ud\n", indent, "", "startGlyphIndex", v->startGlyphIndex); Bprint(f, "%*s%s: %ud\n", indent, "", "endGlyphIndex", v->endGlyphIndex); Bprint(f, "%*s%s: %ud\n", indent, "", "ppemX", v->ppemX); Bprint(f, "%*s%s: %ud\n", indent, "", "ppemY", v->ppemY); Bprint(f, "%*s%s: %ud\n", indent, "", "bitDepth", v->bitDepth); Bprint(f, "%*s%s: %d\n", indent, "", "flags", v->flags); for(int i = 0; i < v->numberOfIndexSubtables; i++){ Bprint(f, "%*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; if((b = otfreadn(o, 4)) == nil) goto err; v->majorVersion = b[0]<<8 | b[1]; if(v->majorVersion != 2){ werrstr("%s: invalid value: %d (0x%ux)", "majorVersion", v->majorVersion, v->majorVersion); goto err; } u16int minorVersion = b[2]<<8 | b[3]; if(minorVersion != 0){ werrstr("%s: invalid value: %d (0x%ux)", "minorVersion", minorVersion, minorVersion); goto err; } return 0; err: werrstr("%s: %r", "TableEBDT"); return -1; } void print_TableEBDT(Biobuf *f, int indent, Otf *o, TableEBDT *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "majorVersion", v->majorVersion); USED(o); } int read_TableEBLC(Otf *o, TableEBLC *v) { u8int *b; if((b = otfreadn(o, 8)) == nil) goto err; u16int majorVersion = b[0]<<8 | b[1]; if(majorVersion != 2){ werrstr("%s: invalid value: %d (0x%ux)", "majorVersion", majorVersion, majorVersion); goto err; } u16int minorVersion = b[2]<<8 | b[3]; if(minorVersion != 0){ werrstr("%s: invalid value: %d (0x%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(Biobuf *f, int indent, Otf *o, TableEBLC *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "numSizes", v->numSizes); for(int i = 0; i < v->numSizes; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, AttachList *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "coverageOffset", v->coverageOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "glyphCount", v->glyphCount); for(int i = 0; i < v->glyphCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "attachPointOffsets", i, v->attachPointOffsets[i]); USED(o); } int read_AttachPoint(Otf *o, AttachPoint *v) { u8int *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(Biobuf *f, int indent, Otf *o, AttachPoint *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "pointCount", v->pointCount); for(int i = 0; i < v->pointCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "pointIndices", i, v->pointIndices[i]); USED(o); } int read_LigCaretList(Otf *o, LigCaretList *v) { u8int *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(Biobuf *f, int indent, Otf *o, LigCaretList *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "coverageOffset", v->coverageOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "ligGlyphCount", v->ligGlyphCount); for(int i = 0; i < v->ligGlyphCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "ligGlyphOffsets", i, v->ligGlyphOffsets[i]); USED(o); } int read_LigGlyph(Otf *o, LigGlyph *v) { u8int *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(Biobuf *f, int indent, Otf *o, LigGlyph *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "caretCount", v->caretCount); for(int i = 0; i < v->caretCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "caretValueOffsets", i, v->caretValueOffsets[i]); USED(o); } int read_CaretValue(Otf *o, CaretValue *v) { u8int *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 (0x%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(Biobuf *f, int indent, Otf *o, CaretValue *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "format", v->format); if(v->format == 1 || v->format == 3) Bprint(f, "%*s%s: %d\n", indent, "", "coordinate", v->coordinate); if(v->format == 2) Bprint(f, "%*s%s: %ud\n", indent, "", "caretValuePointIndex", v->caretValuePointIndex); if(v->format == 3) Bprint(f, "%*s%s: %ud\n", indent, "", "deviceOffset", v->deviceOffset); USED(o); } int read_ValueRecord(Otf *o, ValueRecord *v) { u8int *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(Biobuf *f, int indent, Otf *o, ValueRecord *v) { Bprint(f, "%*s%s: %d\n", indent, "", "xPlacement", v->xPlacement); Bprint(f, "%*s%s: %d\n", indent, "", "yPlacement", v->yPlacement); Bprint(f, "%*s%s: %d\n", indent, "", "xAdvance", v->xAdvance); Bprint(f, "%*s%s: %d\n", indent, "", "yAdvance", v->yAdvance); Bprint(f, "%*s%s: %ud\n", indent, "", "xPlaDeviceOffset", v->xPlaDeviceOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "yPlaDeviceOffset", v->yPlaDeviceOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "xAdvDeviceOffset", v->xAdvDeviceOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "yAdvDeviceOffset", v->yAdvDeviceOffset); USED(o); } int read_SinglePos(Otf *o, SinglePos *v) { u8int *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 (0x%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(Biobuf *f, int indent, Otf *o, SinglePos *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "format", v->format); Bprint(f, "%*s%s: %ud\n", indent, "", "coverageOffset", v->coverageOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "valueFormat", v->valueFormat); if(v->format == 1){ Bprint(f, "%*s%s:\n", indent, "", "valueRecord"); print_ValueRecord(f, indent+indentΔ, o, &v->valueRecord); } if(v->format == 2) Bprint(f, "%*s%s: %ud\n", indent, "", "valueCount", v->valueCount); if(v->format == 2){ for(int i = 0; i < v->valueCount; i++){ Bprint(f, "%*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; if((b = otfreadn(o, 12)) == nil) goto err; u16int majorVersion = b[0]<<8 | b[1]; if(majorVersion != 1){ werrstr("%s: invalid value: %d (0x%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 (0x%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(Biobuf *f, int indent, Otf *o, TableGDEF *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion); Bprint(f, "%*s%s: %ud\n", indent, "", "glyphClassDefOffset", v->glyphClassDefOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "attachListOffset", v->attachListOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "ligCaretListOffset", v->ligCaretListOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "markAttachClassDefOffset", v->markAttachClassDefOffset); if(v->minorVersion >= 2) Bprint(f, "%*s%s: %ud\n", indent, "", "markGlyphSetsDefOffset", v->markGlyphSetsDefOffset); if(v->minorVersion >= 3) Bprint(f, "%*s%s: %ud\n", indent, "", "itemVarStoreOffset", v->itemVarStoreOffset); USED(o); } int read_LangSys(Otf *o, LangSys *v) { u8int *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(Biobuf *f, int indent, Otf *o, LangSys *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "requiredFeatureIndex", v->requiredFeatureIndex); Bprint(f, "%*s%s: %ud\n", indent, "", "featureIndexCount", v->featureIndexCount); for(int i = 0; i < v->featureIndexCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "featureIndices", i, v->featureIndices[i]); USED(o); } int read_LangSysRecord(Otf *o, LangSysRecord *v) { u8int *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(Biobuf *f, int indent, Otf *o, LangSysRecord *v) { Bprint(f, "%*s%s: %t\n", indent, "", "langSysTag", v->langSysTag); Bprint(f, "%*s%s: %ud\n", indent, "", "langSysOffset", v->langSysOffset); Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, Script *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "defaultLangSysOffset", v->defaultLangSysOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "langSysCount", v->langSysCount); for(int i = 0; i < v->langSysCount; i++){ Bprint(f, "%*s%s[%d]:\n", indent, "", "langSysRecords", i); print_LangSysRecord(f, indent+indentΔ, o, &v->langSysRecords[i]); } Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, ScriptRecord *v) { Bprint(f, "%*s%s: %t\n", indent, "", "scriptTag", v->scriptTag); Bprint(f, "%*s%s: %ud\n", indent, "", "scriptOffset", v->scriptOffset); Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, ScriptList *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "scriptCount", v->scriptCount); for(int i = 0; i < v->scriptCount; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, Feature *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "featureParamsOffset", v->featureParamsOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "lookupIndexCount", v->lookupIndexCount); for(int i = 0; i < v->lookupIndexCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "lookupListIndices", i, v->lookupListIndices[i]); USED(o); } int read_FeatureRecord(Otf *o, FeatureRecord *v) { u8int *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(Biobuf *f, int indent, Otf *o, FeatureRecord *v) { Bprint(f, "%*s%s: %t\n", indent, "", "featureTag", v->featureTag); Bprint(f, "%*s%s: %ud\n", indent, "", "featureOffset", v->featureOffset); Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, FeatureList *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "featureCount", v->featureCount); for(int i = 0; i < v->featureCount; i++){ Bprint(f, "%*s%s[%d]:\n", indent, "", "featureRecords", i); print_FeatureRecord(f, indent+indentΔ, o, &v->featureRecords[i]); } USED(o); } int read_Lookup(Otf *o, Lookup *v) { u8int *b; if((b = otfreadn(o, 6)) == nil) goto err; v->lookupType = b[0]<<8 | b[1]; v->lookupFlag = b[2]<<8 | b[3]; v->subTableCount = b[4]<<8 | b[5]; if((b = otfreadn(o, v->subTableCount*2)) == nil) goto err; v->subtableOffsets = malloc(v->subTableCount*sizeof(*v->subtableOffsets)); for(int i = 0; i < v->subTableCount; i++) v->subtableOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if((b = otfreadn(o, 2)) == nil) goto err; v->markFilteringSet = b[0]<<8 | b[1]; return 0; err: werrstr("%s: %r", "Lookup"); return -1; } void print_Lookup(Biobuf *f, int indent, Otf *o, Lookup *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "lookupType", v->lookupType); Bprint(f, "%*s%s: %ud\n", indent, "", "lookupFlag", v->lookupFlag); Bprint(f, "%*s%s: %ud\n", indent, "", "subTableCount", v->subTableCount); for(int i = 0; i < v->subTableCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "subtableOffsets", i, v->subtableOffsets[i]); Bprint(f, "%*s%s: %ud\n", indent, "", "markFilteringSet", v->markFilteringSet); USED(o); } int read_LookupList(Otf *o, LookupList *v) { u8int *b; if((b = otfreadn(o, 2)) == nil) goto err; v->lookupCount = b[0]<<8 | b[1]; if((b = otfreadn(o, v->lookupCount*2)) == nil) goto err; v->lookupOffsets = malloc(v->lookupCount*sizeof(*v->lookupOffsets)); for(int i = 0; i < v->lookupCount; i++) v->lookupOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; return 0; err: werrstr("%s: %r", "LookupList"); return -1; } void print_LookupList(Biobuf *f, int indent, Otf *o, LookupList *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "lookupCount", v->lookupCount); for(int i = 0; i < v->lookupCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "lookupOffsets", i, v->lookupOffsets[i]); USED(o); } int read_TableGPOS(Otf *o, TableGPOS *v) { u8int *b; if((b = otfreadn(o, 10)) == nil) goto err; u16int majorVersion = b[0]<<8 | b[1]; if(majorVersion != 1){ werrstr("%s: invalid value: %d (0x%ux)", "majorVersion", majorVersion, majorVersion); goto err; } v->minorVersion = b[2]<<8 | b[3]; if(v->minorVersion > 1){ werrstr("%s: invalid value: %d (0x%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(Biobuf *f, int indent, Otf *o, TableGPOS *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion); Bprint(f, "%*s%s: %ud\n", indent, "", "scriptListOffset", v->scriptListOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "featureListOffset", v->featureListOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "lookupListOffset", v->lookupListOffset); if(v->minorVersion == 1) Bprint(f, "%*s%s: %ud\n", indent, "", "featureVariationsOffset", v->featureVariationsOffset); Bprint(f, "%*s%s:\n", indent, "", "scriptList"); if(v->scriptList != nil) print_ScriptList(f, indent+indentΔ, o, v->scriptList); Bprint(f, "%*s%s:\n", indent, "", "featureList"); if(v->featureList != nil) print_FeatureList(f, indent+indentΔ, o, v->featureList); Bprint(f, "%*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; if((b = otfreadn(o, 10)) == nil) goto err; u16int majorVersion = b[0]<<8 | b[1]; if(majorVersion != 1){ werrstr("%s: invalid value: %d (0x%ux)", "majorVersion", majorVersion, majorVersion); goto err; } v->minorVersion = b[2]<<8 | b[3]; if(v->minorVersion > 1){ werrstr("%s: invalid value: %d (0x%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(Biobuf *f, int indent, Otf *o, TableGSUB *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion); Bprint(f, "%*s%s: %ud\n", indent, "", "scriptListOffset", v->scriptListOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "featureListOffset", v->featureListOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "lookupListOffset", v->lookupListOffset); if(v->minorVersion == 1) Bprint(f, "%*s%s: %ud\n", indent, "", "featureVariationsOffset", v->featureVariationsOffset); Bprint(f, "%*s%s:\n", indent, "", "scriptList"); if(v->scriptList != nil) print_ScriptList(f, indent+indentΔ, o, v->scriptList); Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, MathValueRecord *v) { Bprint(f, "%*s%s: %d\n", indent, "", "value", v->value); Bprint(f, "%*s%s: %ud\n", indent, "", "deviceOffset", v->deviceOffset); USED(o); } int read_MathConstants(Otf *o, MathConstants *v) { u8int *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(Biobuf *f, int indent, Otf *o, MathConstants *v) { Bprint(f, "%*s%s: %d\n", indent, "", "scriptPercentScaleDown", v->scriptPercentScaleDown); Bprint(f, "%*s%s: %d\n", indent, "", "scriptScriptPercentScaleDown", v->scriptScriptPercentScaleDown); Bprint(f, "%*s%s: %ud\n", indent, "", "delimitedSubFormulaMinHeight", v->delimitedSubFormulaMinHeight); Bprint(f, "%*s%s: %ud\n", indent, "", "displayOperatorMinHeight", v->displayOperatorMinHeight); Bprint(f, "%*s%s:\n", indent, "", "mathLeading"); print_MathValueRecord(f, indent+indentΔ, o, &v->mathLeading); Bprint(f, "%*s%s:\n", indent, "", "axisHeight"); print_MathValueRecord(f, indent+indentΔ, o, &v->axisHeight); Bprint(f, "%*s%s:\n", indent, "", "accentBaseHeight"); print_MathValueRecord(f, indent+indentΔ, o, &v->accentBaseHeight); Bprint(f, "%*s%s:\n", indent, "", "flattenedAccentBaseHeight"); print_MathValueRecord(f, indent+indentΔ, o, &v->flattenedAccentBaseHeight); Bprint(f, "%*s%s:\n", indent, "", "subscriptShiftDown"); print_MathValueRecord(f, indent+indentΔ, o, &v->subscriptShiftDown); Bprint(f, "%*s%s:\n", indent, "", "subscriptTopMax"); print_MathValueRecord(f, indent+indentΔ, o, &v->subscriptTopMax); Bprint(f, "%*s%s:\n", indent, "", "subscriptBaselineDropMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->subscriptBaselineDropMin); Bprint(f, "%*s%s:\n", indent, "", "superscriptShiftUp"); print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptShiftUp); Bprint(f, "%*s%s:\n", indent, "", "superscriptShiftUpCramped"); print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptShiftUpCramped); Bprint(f, "%*s%s:\n", indent, "", "superscriptBottomMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptBottomMin); Bprint(f, "%*s%s:\n", indent, "", "superscriptBaselineDropMax"); print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptBaselineDropMax); Bprint(f, "%*s%s:\n", indent, "", "subSuperscriptGapMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->subSuperscriptGapMin); Bprint(f, "%*s%s:\n", indent, "", "superscriptBottomMaxWithSubscript"); print_MathValueRecord(f, indent+indentΔ, o, &v->superscriptBottomMaxWithSubscript); Bprint(f, "%*s%s:\n", indent, "", "spaceAfterScript"); print_MathValueRecord(f, indent+indentΔ, o, &v->spaceAfterScript); Bprint(f, "%*s%s:\n", indent, "", "upperLimitGapMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->upperLimitGapMin); Bprint(f, "%*s%s:\n", indent, "", "upperLimitBaselineRiseMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->upperLimitBaselineRiseMin); Bprint(f, "%*s%s:\n", indent, "", "lowerLimitGapMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->lowerLimitGapMin); Bprint(f, "%*s%s:\n", indent, "", "lowerLimitBaselineDropMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->lowerLimitBaselineDropMin); Bprint(f, "%*s%s:\n", indent, "", "stackTopShiftUp"); print_MathValueRecord(f, indent+indentΔ, o, &v->stackTopShiftUp); Bprint(f, "%*s%s:\n", indent, "", "stackTopDisplayStyleShiftUp"); print_MathValueRecord(f, indent+indentΔ, o, &v->stackTopDisplayStyleShiftUp); Bprint(f, "%*s%s:\n", indent, "", "stackBottomShiftDown"); print_MathValueRecord(f, indent+indentΔ, o, &v->stackBottomShiftDown); Bprint(f, "%*s%s:\n", indent, "", "stackBottomDisplayStyleShiftDown"); print_MathValueRecord(f, indent+indentΔ, o, &v->stackBottomDisplayStyleShiftDown); Bprint(f, "%*s%s:\n", indent, "", "stackGapMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->stackGapMin); Bprint(f, "%*s%s:\n", indent, "", "stackDisplayStyleGapMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->stackDisplayStyleGapMin); Bprint(f, "%*s%s:\n", indent, "", "stretchStackTopShiftUp"); print_MathValueRecord(f, indent+indentΔ, o, &v->stretchStackTopShiftUp); Bprint(f, "%*s%s:\n", indent, "", "stretchStackBottomShiftDown"); print_MathValueRecord(f, indent+indentΔ, o, &v->stretchStackBottomShiftDown); Bprint(f, "%*s%s:\n", indent, "", "stretchStackGapAboveMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->stretchStackGapAboveMin); Bprint(f, "%*s%s:\n", indent, "", "stretchStackGapBelowMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->stretchStackGapBelowMin); Bprint(f, "%*s%s:\n", indent, "", "fractionNumeratorShiftUp"); print_MathValueRecord(f, indent+indentΔ, o, &v->fractionNumeratorShiftUp); Bprint(f, "%*s%s:\n", indent, "", "fractionNumeratorDisplayStyleShiftUp"); print_MathValueRecord(f, indent+indentΔ, o, &v->fractionNumeratorDisplayStyleShiftUp); Bprint(f, "%*s%s:\n", indent, "", "fractionDenominatorShiftDown"); print_MathValueRecord(f, indent+indentΔ, o, &v->fractionDenominatorShiftDown); Bprint(f, "%*s%s:\n", indent, "", "fractionDenominatorDisplayStyleShiftDown"); print_MathValueRecord(f, indent+indentΔ, o, &v->fractionDenominatorDisplayStyleShiftDown); Bprint(f, "%*s%s:\n", indent, "", "fractionNumeratorGapMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->fractionNumeratorGapMin); Bprint(f, "%*s%s:\n", indent, "", "fractionNumDisplayStyleGapMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->fractionNumDisplayStyleGapMin); Bprint(f, "%*s%s:\n", indent, "", "fractionRuleThickness"); print_MathValueRecord(f, indent+indentΔ, o, &v->fractionRuleThickness); Bprint(f, "%*s%s:\n", indent, "", "fractionDenominatorGapMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->fractionDenominatorGapMin); Bprint(f, "%*s%s:\n", indent, "", "fractionDenomDisplayStyleGapMin"); print_MathValueRecord(f, indent+indentΔ, o, &v->fractionDenomDisplayStyleGapMin); Bprint(f, "%*s%s:\n", indent, "", "skewedFractionHorizontalGap"); print_MathValueRecord(f, indent+indentΔ, o, &v->skewedFractionHorizontalGap); Bprint(f, "%*s%s:\n", indent, "", "skewedFractionVerticalGap"); print_MathValueRecord(f, indent+indentΔ, o, &v->skewedFractionVerticalGap); Bprint(f, "%*s%s:\n", indent, "", "overbarVerticalGap"); print_MathValueRecord(f, indent+indentΔ, o, &v->overbarVerticalGap); Bprint(f, "%*s%s:\n", indent, "", "overbarRuleThickness"); print_MathValueRecord(f, indent+indentΔ, o, &v->overbarRuleThickness); Bprint(f, "%*s%s:\n", indent, "", "overbarExtraAscender"); print_MathValueRecord(f, indent+indentΔ, o, &v->overbarExtraAscender); Bprint(f, "%*s%s:\n", indent, "", "underbarVerticalGap"); print_MathValueRecord(f, indent+indentΔ, o, &v->underbarVerticalGap); Bprint(f, "%*s%s:\n", indent, "", "underbarRuleThickness"); print_MathValueRecord(f, indent+indentΔ, o, &v->underbarRuleThickness); Bprint(f, "%*s%s:\n", indent, "", "underbarExtraDescender"); print_MathValueRecord(f, indent+indentΔ, o, &v->underbarExtraDescender); Bprint(f, "%*s%s:\n", indent, "", "radicalVerticalGap"); print_MathValueRecord(f, indent+indentΔ, o, &v->radicalVerticalGap); Bprint(f, "%*s%s:\n", indent, "", "radicalDisplayStyleVerticalGap"); print_MathValueRecord(f, indent+indentΔ, o, &v->radicalDisplayStyleVerticalGap); Bprint(f, "%*s%s:\n", indent, "", "radicalRuleThickness"); print_MathValueRecord(f, indent+indentΔ, o, &v->radicalRuleThickness); Bprint(f, "%*s%s:\n", indent, "", "radicalExtraAscender"); print_MathValueRecord(f, indent+indentΔ, o, &v->radicalExtraAscender); Bprint(f, "%*s%s:\n", indent, "", "radicalKernBeforeDegree"); print_MathValueRecord(f, indent+indentΔ, o, &v->radicalKernBeforeDegree); Bprint(f, "%*s%s:\n", indent, "", "radicalKernAfterDegree"); print_MathValueRecord(f, indent+indentΔ, o, &v->radicalKernAfterDegree); Bprint(f, "%*s%s: %d\n", indent, "", "radicalDegreeBottomRaisePercent", v->radicalDegreeBottomRaisePercent); USED(o); } int read_MathItalicsCorrectionInfo(Otf *o, MathItalicsCorrectionInfo *v) { u8int *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(Biobuf *f, int indent, Otf *o, MathItalicsCorrectionInfo *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "italicsCorrectionCoverageOffset", v->italicsCorrectionCoverageOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "italicsCorrectionCount", v->italicsCorrectionCount); for(int i = 0; i < v->italicsCorrectionCount; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, MathTopAccentAttachment *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "topAccentCoverageOffset", v->topAccentCoverageOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "topAccentAttachmentCount", v->topAccentAttachmentCount); for(int i = 0; i < v->topAccentAttachmentCount; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, MathKernInfoRecord *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "topRightMathKernOffset", v->topRightMathKernOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "topLeftMathKernOffset", v->topLeftMathKernOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "bottomRightMathKernOffset", v->bottomRightMathKernOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "bottomLeftMathKernOffset", v->bottomLeftMathKernOffset); USED(o); } int read_MathKernInfo(Otf *o, MathKernInfo *v) { u8int *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(Biobuf *f, int indent, Otf *o, MathKernInfo *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "mathKernCoverageOffset", v->mathKernCoverageOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "mathKernCount", v->mathKernCount); for(int i = 0; i < v->mathKernCount; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, MathKern *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "heightCount", v->heightCount); for(int i = 0; i < v->heightCount; i++){ Bprint(f, "%*s%s[%d]:\n", indent, "", "correctionHeight", i); print_MathValueRecord(f, indent+indentΔ, o, &v->correctionHeight[i]); } for(int i = 0; i < v->heightCount; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, Coverage1 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "glyphCount", v->glyphCount); for(int i = 0; i < v->glyphCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "glyphArray", i, v->glyphArray[i]); USED(o); } int read_RangeRecord(Otf *o, RangeRecord *v) { u8int *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(Biobuf *f, int indent, Otf *o, RangeRecord *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "startGlyphID", v->startGlyphID); Bprint(f, "%*s%s: %ud\n", indent, "", "endGlyphID", v->endGlyphID); Bprint(f, "%*s%s: %ud\n", indent, "", "startCoverageIndex", v->startCoverageIndex); USED(o); } int read_Coverage2(Otf *o, Coverage2 *v) { u8int *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(Biobuf *f, int indent, Otf *o, Coverage2 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "rangeCount", v->rangeCount); for(int i = 0; i < v->rangeCount; i++){ Bprint(f, "%*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; 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 (0x%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(Biobuf *f, int indent, Otf *o, Coverage *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "format", v->format); if(v->format == 1){ Bprint(f, "%*s%s:\n", indent, "", "cov1"); print_Coverage1(f, indent+indentΔ, o, &v->cov1); } if(v->format == 2){ Bprint(f, "%*s%s:\n", indent, "", "cov2"); print_Coverage2(f, indent+indentΔ, o, &v->cov2); } USED(o); } int read_MathVariants(Otf *o, MathVariants *v) { u8int *b; if((b = otfreadn(o, 10)) == nil) goto err; v->minConnectorOverlap = b[0]<<8 | b[1]; v->vertGlyphCoverageOffset = b[2]<<8 | b[3]; v->horizGlyphCoverageOffset = b[4]<<8 | b[5]; v->vertGlyphCount = b[6]<<8 | b[7]; v->horizGlyphCount = b[8]<<8 | b[9]; if((b = otfreadn(o, v->vertGlyphCount*2)) == nil) goto err; v->vertGlyphConstructionOffsets = malloc(v->vertGlyphCount*sizeof(*v->vertGlyphConstructionOffsets)); for(int i = 0; i < v->vertGlyphCount; i++) v->vertGlyphConstructionOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if((b = otfreadn(o, v->horizGlyphCount*2)) == nil) goto err; v->horizGlyphConstructionOffsets = malloc(v->horizGlyphCount*sizeof(*v->horizGlyphConstructionOffsets)); for(int i = 0; i < v->horizGlyphCount; i++) v->horizGlyphConstructionOffsets[i] = b[0+i*2]<<8 | b[1+i*2]; if(v->vertGlyphCoverageOffset != 0){ if(otfpushrange(o, v->vertGlyphCoverageOffset, -1) < 0) goto err; v->vertGlyphCoverage = calloc(1, sizeof(*v->vertGlyphCoverage)); if(read_Coverage(o, v->vertGlyphCoverage) < 0){ werrstr("%s: %r", "vertGlyphCoverage"); goto err; } if(otfpoprange(o) < 0) goto err; } if(v->horizGlyphCoverageOffset != 0){ if(otfpushrange(o, v->horizGlyphCoverageOffset, -1) < 0) goto err; v->horizGlyphCoverage = calloc(1, sizeof(*v->horizGlyphCoverage)); if(read_Coverage(o, v->horizGlyphCoverage) < 0){ werrstr("%s: %r", "horizGlyphCoverage"); goto err; } if(otfpoprange(o) < 0) goto err; } return 0; err: werrstr("%s: %r", "MathVariants"); return -1; } void print_MathVariants(Biobuf *f, int indent, Otf *o, MathVariants *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "minConnectorOverlap", v->minConnectorOverlap); Bprint(f, "%*s%s: %ud\n", indent, "", "vertGlyphCoverageOffset", v->vertGlyphCoverageOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "horizGlyphCoverageOffset", v->horizGlyphCoverageOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "vertGlyphCount", v->vertGlyphCount); Bprint(f, "%*s%s: %ud\n", indent, "", "horizGlyphCount", v->horizGlyphCount); for(int i = 0; i < v->vertGlyphCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "vertGlyphConstructionOffsets", i, v->vertGlyphConstructionOffsets[i]); for(int i = 0; i < v->horizGlyphCount; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "horizGlyphConstructionOffsets", i, v->horizGlyphConstructionOffsets[i]); Bprint(f, "%*s%s:\n", indent, "", "vertGlyphCoverage"); if(v->vertGlyphCoverage != nil) print_Coverage(f, indent+indentΔ, o, v->vertGlyphCoverage); Bprint(f, "%*s%s:\n", indent, "", "horizGlyphCoverage"); if(v->horizGlyphCoverage != nil) print_Coverage(f, indent+indentΔ, o, v->horizGlyphCoverage); USED(o); } int read_MathGlyphInfo(Otf *o, MathGlyphInfo *v) { u8int *b; 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(Biobuf *f, int indent, Otf *o, MathGlyphInfo *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "mathItalicsCorrectionInfoOffset", v->mathItalicsCorrectionInfoOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "mathTopAccentAttachmentOffset", v->mathTopAccentAttachmentOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "extendedShapeCoverageOffset", v->extendedShapeCoverageOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "mathKernInfoOffset", v->mathKernInfoOffset); Bprint(f, "%*s%s:\n", indent, "", "mathItalicsCorrectionInfo"); if(v->mathItalicsCorrectionInfo != nil) print_MathItalicsCorrectionInfo(f, indent+indentΔ, o, v->mathItalicsCorrectionInfo); Bprint(f, "%*s%s:\n", indent, "", "mathTopAccentAttachment"); if(v->mathTopAccentAttachment != nil) print_MathTopAccentAttachment(f, indent+indentΔ, o, v->mathTopAccentAttachment); Bprint(f, "%*s%s:\n", indent, "", "mathKernInfo"); if(v->mathKernInfo != nil) print_MathKernInfo(f, indent+indentΔ, o, v->mathKernInfo); Bprint(f, "%*s%s:\n", indent, "", "extendedShapeCoverage"); if(v->extendedShapeCoverage != nil) print_Coverage(f, indent+indentΔ, o, v->extendedShapeCoverage); USED(o); } int read_MathGlyphVariantRecord(Otf *o, MathGlyphVariantRecord *v) { u8int *b; 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(Biobuf *f, int indent, Otf *o, MathGlyphVariantRecord *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "variantGlyph", v->variantGlyph); Bprint(f, "%*s%s: %ud\n", indent, "", "advanceMeasurement", v->advanceMeasurement); USED(o); } int read_GlyphPart(Otf *o, GlyphPart *v) { u8int *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(Biobuf *f, int indent, Otf *o, GlyphPart *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID); Bprint(f, "%*s%s: %ud\n", indent, "", "startConnectorLength", v->startConnectorLength); Bprint(f, "%*s%s: %ud\n", indent, "", "endConnectorLength", v->endConnectorLength); Bprint(f, "%*s%s: %ud\n", indent, "", "fullAdvance", v->fullAdvance); Bprint(f, "%*s%s: %ud\n", indent, "", "partFlags", v->partFlags); USED(o); } int read_GlyphAssembly(Otf *o, GlyphAssembly *v) { u8int *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(Biobuf *f, int indent, Otf *o, GlyphAssembly *v) { Bprint(f, "%*s%s:\n", indent, "", "italicsCorrection"); print_MathValueRecord(f, indent+indentΔ, o, &v->italicsCorrection); Bprint(f, "%*s%s: %ud\n", indent, "", "partCount", v->partCount); for(int i = 0; i < v->partCount; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, MathGlyphConstruction *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "glyphAssemblyOffset", v->glyphAssemblyOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "variantCount", v->variantCount); for(int i = 0; i < v->variantCount; i++){ Bprint(f, "%*s%s[%d]:\n", indent, "", "mathGlyphVariantRecords", i); print_MathGlyphVariantRecord(f, indent+indentΔ, o, &v->mathGlyphVariantRecords[i]); } Bprint(f, "%*s%s:\n", indent, "", "glyphAssembly"); if(v->glyphAssembly != nil) print_GlyphAssembly(f, indent+indentΔ, o, v->glyphAssembly); USED(o); } int read_TableMATH(Otf *o, TableMATH *v) { u8int *b; if((b = otfreadn(o, 10)) == nil) goto err; u16int majorVersion = b[0]<<8 | b[1]; if(majorVersion != 1){ werrstr("%s: invalid value: %d (0x%ux)", "majorVersion", majorVersion, majorVersion); goto err; } u16int minorVersion = b[2]<<8 | b[3]; if(minorVersion != 0){ werrstr("%s: invalid value: %d (0x%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(Biobuf *f, int indent, Otf *o, TableMATH *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "mathConstantsOffset", v->mathConstantsOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "mathGlyphInfoOffset", v->mathGlyphInfoOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "mathVariantsOffset", v->mathVariantsOffset); Bprint(f, "%*s%s:\n", indent, "", "mathConstants"); if(v->mathConstants != nil) print_MathConstants(f, indent+indentΔ, o, v->mathConstants); Bprint(f, "%*s%s:\n", indent, "", "mathGlyphInfo"); if(v->mathGlyphInfo != nil) print_MathGlyphInfo(f, indent+indentΔ, o, v->mathGlyphInfo); Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, KernPair *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "left", v->left); Bprint(f, "%*s%s: %ud\n", indent, "", "right", v->right); Bprint(f, "%*s%s: %d\n", indent, "", "value", v->value); USED(o); } int read_KernSubtable0(Otf *o, KernSubtable0 *v) { u8int *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(Biobuf *f, int indent, Otf *o, KernSubtable0 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "nPairs", v->nPairs); Bprint(f, "%*s%s: %ud\n", indent, "", "searchRange", v->searchRange); Bprint(f, "%*s%s: %ud\n", indent, "", "entrySelector", v->entrySelector); Bprint(f, "%*s%s: %ud\n", indent, "", "rangeShift", v->rangeShift); for(int i = 0; i < v->nPairs; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, KernClass *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "firstGlyph", v->firstGlyph); Bprint(f, "%*s%s: %ud\n", indent, "", "nGlyphs", v->nGlyphs); for(int i = 0; i < v->nGlyphs; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "values", i, v->values[i]); USED(o); } int read_KernSubtable2(Otf *o, KernSubtable2 *v) { u8int *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(Biobuf *f, int indent, Otf *o, KernSubtable2 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "rowWidth", v->rowWidth); Bprint(f, "%*s%s: %ud\n", indent, "", "leftClassOffset", v->leftClassOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "rightClassOffset", v->rightClassOffset); Bprint(f, "%*s%s: %ud\n", indent, "", "kerningArrayOffset", v->kerningArrayOffset); Bprint(f, "%*s%s:\n", indent, "", "leftClass"); if(v->leftClass != nil) print_KernClass(f, indent+indentΔ, o, v->leftClass); Bprint(f, "%*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++) Bprint(f, "%*s%s[%d]: %d\n", indent, "", "kerningArray", i, v->kerningArray[i]); USED(o); } int read_KernSubtable(Otf *o, KernSubtable *v) { u8int *b; if((b = otfreadn(o, 6)) == nil) goto err; u16int version = b[0]<<8 | b[1]; if(version != 0){ werrstr("%s: invalid value: %d (0x%ux)", "version", version, version); goto err; } v->length = b[2]<<8 | b[3]; if(v->length < 6){ werrstr("%s: invalid value: %d (0x%ux)", "length", v->length, v->length); goto err; } v->coverage = b[4]<<8 | b[5]; return 0; err: werrstr("%s: %r", "KernSubtable"); return -1; } void print_KernSubtable(Biobuf *f, int indent, Otf *o, KernSubtable *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "length", v->length); Bprint(f, "%*s%s: %ud\n", indent, "", "coverage", v->coverage); USED(o); } int read_TableKern(Otf *o, TableKern *v) { u8int *b; if((b = otfreadn(o, 4)) == nil) goto err; u16int version = b[0]<<8 | b[1]; if(version != 0){ werrstr("%s: invalid value: %d (0x%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(Biobuf *f, int indent, Otf *o, TableKern *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "nTables", v->nTables); for(int i = 0; i < v->nTables; i++){ Bprint(f, "%*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; 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(Biobuf *f, int indent, Otf *o, TableLoca *v) { if(o->indexToLocFormat == 0){ for(int i = 0; i < (o->numGlyphs+1); i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "shortOffsets", i, v->shortOffsets[i]); } if(o->indexToLocFormat == 1){ for(int i = 0; i < (o->numGlyphs+1); i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "longOffsets", i, v->longOffsets[i]); } USED(o); } int read_TableOS∕2(Otf *o, TableOS∕2 *v) { u8int *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 (0x%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(Biobuf *f, int indent, Otf *o, TableOS∕2 *v) { Bprint(f, "%*s%s: %ud\n", indent, "", "version", v->version); Bprint(f, "%*s%s: %d\n", indent, "", "xAvgCharWidth", v->xAvgCharWidth); Bprint(f, "%*s%s: %ud\n", indent, "", "usWeightClass", v->usWeightClass); Bprint(f, "%*s%s: %ud\n", indent, "", "usWidthClass", v->usWidthClass); Bprint(f, "%*s%s: %ud\n", indent, "", "fsType", v->fsType); Bprint(f, "%*s%s: %d\n", indent, "", "ySubscriptXSize", v->ySubscriptXSize); Bprint(f, "%*s%s: %d\n", indent, "", "ySubscriptYSize", v->ySubscriptYSize); Bprint(f, "%*s%s: %d\n", indent, "", "ySubscriptXOffset", v->ySubscriptXOffset); Bprint(f, "%*s%s: %d\n", indent, "", "ySubscriptYOffset", v->ySubscriptYOffset); Bprint(f, "%*s%s: %d\n", indent, "", "ySuperscriptXSize", v->ySuperscriptXSize); Bprint(f, "%*s%s: %d\n", indent, "", "ySuperscriptYSize", v->ySuperscriptYSize); Bprint(f, "%*s%s: %d\n", indent, "", "ySuperscriptXOffset", v->ySuperscriptXOffset); Bprint(f, "%*s%s: %d\n", indent, "", "ySuperscriptYOffset", v->ySuperscriptYOffset); Bprint(f, "%*s%s: %d\n", indent, "", "yStrikeoutSize", v->yStrikeoutSize); Bprint(f, "%*s%s: %d\n", indent, "", "yStrikeoutPosition", v->yStrikeoutPosition); Bprint(f, "%*s%s: %d\n", indent, "", "sFamilyClass", v->sFamilyClass); for(int i = 0; i < 10; i++) Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "panose", i, v->panose[i]); Bprint(f, "%*s%s: %#ux\n", indent, "", "ulUnicodeRange1", v->ulUnicodeRange1); Bprint(f, "%*s%s: %#ux\n", indent, "", "ulUnicodeRange2", v->ulUnicodeRange2); Bprint(f, "%*s%s: %#ux\n", indent, "", "ulUnicodeRange3", v->ulUnicodeRange3); Bprint(f, "%*s%s: %#ux\n", indent, "", "ulUnicodeRange4", v->ulUnicodeRange4); Bprint(f, "%*s%s: %t\n", indent, "", "achVendID", v->achVendID); Bprint(f, "%*s%s: %ud\n", indent, "", "fsSelection", v->fsSelection); Bprint(f, "%*s%s: %ud\n", indent, "", "usFirstCharIndex", v->usFirstCharIndex); Bprint(f, "%*s%s: %ud\n", indent, "", "usLastCharIndex", v->usLastCharIndex); Bprint(f, "%*s%s: %d\n", indent, "", "sTypoAscender", v->sTypoAscender); Bprint(f, "%*s%s: %d\n", indent, "", "sTypoDescender", v->sTypoDescender); Bprint(f, "%*s%s: %d\n", indent, "", "sTypoLineGap", v->sTypoLineGap); Bprint(f, "%*s%s: %ud\n", indent, "", "usWinAscent", v->usWinAscent); Bprint(f, "%*s%s: %ud\n", indent, "", "usWinDescent", v->usWinDescent); if(v->version >= 1) Bprint(f, "%*s%s: %#ux\n", indent, "", "ulCodePageRange1", v->ulCodePageRange1); if(v->version >= 1) Bprint(f, "%*s%s: %#ux\n", indent, "", "ulCodePageRange2", v->ulCodePageRange2); if(v->version >= 2) Bprint(f, "%*s%s: %d\n", indent, "", "sxHeight", v->sxHeight); if(v->version >= 2) Bprint(f, "%*s%s: %d\n", indent, "", "sCapHeight", v->sCapHeight); if(v->version >= 2) Bprint(f, "%*s%s: %#ux\n", indent, "", "usDefaultChar", v->usDefaultChar); if(v->version >= 2) Bprint(f, "%*s%s: %#ux\n", indent, "", "usBreakChar", v->usBreakChar); if(v->version >= 2) Bprint(f, "%*s%s: %ud\n", indent, "", "usMaxContext", v->usMaxContext); if(v->version >= 5) Bprint(f, "%*s%s: %ud\n", indent, "", "usLowerOpticalPointSize", v->usLowerOpticalPointSize); if(v->version >= 5) Bprint(f, "%*s%s: %ud\n", indent, "", "usUpperOpticalPointSize", v->usUpperOpticalPointSize); USED(o); } int read_TableRecord(Otf *o, TableRecord *v) { u8int *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(Biobuf *f, int indent, Otf *o, TableRecord *v) { Bprint(f, "%*s%s: %t\n", indent, "", "tableTag", v->tableTag); Bprint(f, "%*s%s: %ud\n", indent, "", "offset", v->offset); Bprint(f, "%*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; 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 (0x%ux)", "sfntVersion", v->sfntVersion, v->sfntVersion); goto err; } v->numTables = b[4]<<8 | b[5]; v->searchRange = b[6]<<8 | b[7]; v->entrySelector = b[8]<<8 | b[9]; v->rangeShift = b[10]<<8 | b[11]; if(otfarray(o, &v->tableRecords, read_TableRecord, sizeof(TableRecord), v->numTables) < 0){ werrstr("%s: %r", "tableRecords"); goto err; } int retry = 0; do{ for(int i = 0; i < v->numTables; i++){ TableRecord *rec = &v->tableRecords[i]; if(rec->length == 0) continue; if(otfpushrange(o, rec->offset, rec->length) < 0) goto err; switch(rec->tableTag){ case (u32int)('c'<<24|'m'<<16|'a'<<8|'p'): if(v->cmap != nil) break; v->cmap = calloc(1, sizeof(TableCmap)); if(read_TableCmap(o, v->cmap) < 0){ free(v->cmap); goto err; } rec->parsed = v->cmap; rec->print = (void*)print_TableCmap; break; case (u32int)('h'<<24|'e'<<16|'a'<<8|'d'): if(v->head != nil) break; v->head = calloc(1, sizeof(TableHead)); if(read_TableHead(o, v->head) < 0){ free(v->head); goto err; } rec->parsed = v->head; rec->print = (void*)print_TableHead; break; case (u32int)('h'<<24|'h'<<16|'e'<<8|'a'): if(v->hhea != nil) break; v->hhea = calloc(1, sizeof(TableHhea)); if(read_TableHhea(o, v->hhea) < 0){ free(v->hhea); goto err; } rec->parsed = v->hhea; rec->print = (void*)print_TableHhea; break; case (u32int)('m'<<24|'a'<<16|'x'<<8|'p'): if(v->maxp != nil) break; v->maxp = calloc(1, sizeof(TableMaxp)); if(read_TableMaxp(o, v->maxp) < 0){ free(v->maxp); goto err; } rec->parsed = v->maxp; rec->print = (void*)print_TableMaxp; break; case (u32int)('h'<<24|'m'<<16|'t'<<8|'x'): { static int retried = 0; if(v->hhea == nil || v->maxp == nil){ if(retried){ werrstr("%s: deps missing", "TableHmtx"); goto err; } retried = 1; retry++; break; } if(retried) retry--; } if(v->hmtx != nil) break; v->hmtx = calloc(1, sizeof(TableHmtx)); if(read_TableHmtx(o, v->hmtx) < 0){ free(v->hmtx); goto err; } rec->parsed = v->hmtx; rec->print = (void*)print_TableHmtx; break; case (u32int)('p'<<24|'o'<<16|'s'<<8|'t'): if(v->post != nil) break; v->post = calloc(1, sizeof(TablePost)); if(read_TablePost(o, v->post) < 0){ free(v->post); goto err; } rec->parsed = v->post; rec->print = (void*)print_TablePost; break; case (u32int)('n'<<24|'a'<<16|'m'<<8|'e'): if(v->name != nil) break; v->name = calloc(1, sizeof(TableName)); if(read_TableName(o, v->name) < 0){ free(v->name); goto err; } rec->parsed = v->name; rec->print = (void*)print_TableName; break; case (u32int)('E'<<24|'B'<<16|'D'<<8|'T'): if(v->ebdt != nil) break; v->ebdt = calloc(1, sizeof(TableEBDT)); if(read_TableEBDT(o, v->ebdt) < 0){ free(v->ebdt); goto err; } rec->parsed = v->ebdt; rec->print = (void*)print_TableEBDT; break; case (u32int)('E'<<24|'B'<<16|'L'<<8|'C'): if(v->eblc != nil) break; v->eblc = calloc(1, sizeof(TableEBLC)); if(read_TableEBLC(o, v->eblc) < 0){ free(v->eblc); goto err; } rec->parsed = v->eblc; rec->print = (void*)print_TableEBLC; break; case (u32int)('G'<<24|'D'<<16|'E'<<8|'F'): if(v->gdef != nil) break; v->gdef = calloc(1, sizeof(TableGDEF)); if(read_TableGDEF(o, v->gdef) < 0){ free(v->gdef); goto err; } rec->parsed = v->gdef; rec->print = (void*)print_TableGDEF; break; case (u32int)('G'<<24|'P'<<16|'O'<<8|'S'): if(v->gpos != nil) break; v->gpos = calloc(1, sizeof(TableGPOS)); if(read_TableGPOS(o, v->gpos) < 0){ free(v->gpos); goto err; } rec->parsed = v->gpos; rec->print = (void*)print_TableGPOS; break; case (u32int)('G'<<24|'S'<<16|'U'<<8|'B'): if(v->gsub != nil) break; v->gsub = calloc(1, sizeof(TableGSUB)); if(read_TableGSUB(o, v->gsub) < 0){ free(v->gsub); goto err; } rec->parsed = v->gsub; rec->print = (void*)print_TableGSUB; break; case (u32int)('M'<<24|'A'<<16|'T'<<8|'H'): if(v->math != nil) break; v->math = calloc(1, sizeof(TableMATH)); if(read_TableMATH(o, v->math) < 0){ free(v->math); goto err; } rec->parsed = v->math; rec->print = (void*)print_TableMATH; break; case (u32int)('k'<<24|'e'<<16|'r'<<8|'n'): if(v->kern != nil) break; v->kern = calloc(1, sizeof(TableKern)); if(read_TableKern(o, v->kern) < 0){ free(v->kern); goto err; } rec->parsed = v->kern; rec->print = (void*)print_TableKern; break; case (u32int)('l'<<24|'o'<<16|'c'<<8|'a'): { static int retried = 0; if(v->head == nil){ if(retried){ werrstr("%s: deps missing", "TableLoca"); goto err; } retried = 1; retry++; break; } if(retried) retry--; } if(v->loca != nil) break; v->loca = calloc(1, sizeof(TableLoca)); if(read_TableLoca(o, v->loca) < 0){ free(v->loca); goto err; } rec->parsed = v->loca; rec->print = (void*)print_TableLoca; break; case (u32int)('O'<<24|'S'<<16|'/'<<8|'2'): if(v->os∕2 != nil) break; v->os∕2 = calloc(1, sizeof(TableOS∕2)); if(read_TableOS∕2(o, v->os∕2) < 0){ free(v->os∕2); goto err; } rec->parsed = v->os∕2; rec->print = (void*)print_TableOS∕2; break; } if(otfpoprange(o) < 0) goto err; } }while(retry > 0); return 0; err: werrstr("%s: %r", "TableDirectory"); return -1; } void print_TableDirectory(Biobuf *f, int indent, Otf *o, TableDirectory *v) { Bprint(f, "%*s%s: %#ux\n", indent, "", "sfntVersion", v->sfntVersion); Bprint(f, "%*s%s: %ud\n", indent, "", "numTables", v->numTables); Bprint(f, "%*s%s: %ud\n", indent, "", "searchRange", v->searchRange); Bprint(f, "%*s%s: %ud\n", indent, "", "entrySelector", v->entrySelector); Bprint(f, "%*s%s: %ud\n", indent, "", "rangeShift", v->rangeShift); for(int i = 0; i < v->numTables; i++){ Bprint(f, "%*s%s[%d]:\n", indent, "", "tableRecords", i); print_TableRecord(f, indent+indentΔ, o, &v->tableRecords[i]); } USED(o); } int indentΔ = 2; static int Tfmt(Fmt *f) { Tm t; s64int v = va_arg(f->args, s64int); return fmtprint(f, "%τ", tmfmt(tmtime(&t, v, nil), nil)); } static int Vfmt(Fmt *f) { u32int v = va_arg(f->args, u32int); return fmtprint(f, "%d.%d", v>>16, v&0xffff); } static int tfmt(Fmt *f) { u32int v = va_arg(f->args, u32int); return fmtprint(f, "%c%c%c%c", v>>24, v>>16, v>>8, v>>0); } void otfinit(void) { tmfmtinstall(); fmtinstall('V', Vfmt); fmtinstall('T', Tfmt); fmtinstall('t', tfmt); }