ref: f711b4426695620ce7646d3036f69275be73e59f
dir: /otf.rkt/
; types allowed to be used as index (define-for-syntax (type-index? type) (member type '(uint16 uint32))) ; types allowed to be used as offset (define-for-syntax (type-offset? type) (member type '(Offset16 Offset24 Offset32))) ; types allowed to be used in comparisons (define-for-syntax (type-comparable? type) (member type '(uint8 int8 uint16 int16 uint24 uint32 int32 Version16Dot16))) ; types allowed to be used in comparisons (define-for-syntax (type-number? type) (member type '(uint8 int8 uint16 int16 uint24 uint32 int32 Version16Dot16 Offset16 Offset24 Offset32))) (mktype String 8 char "%s") (mktype String-UTF16 8 char "%s") (mktype uint8 8 u8int (verb-unsigned 8)) (mktype int8 8 s8int "%d") (mktype uint16 16 u16int (verb-unsigned 16)) (mktype int16 16 s16int "%d") (mktype uint24 24 u32int (verb-unsigned 32)) (mktype uint32 32 u32int (verb-unsigned 32)) (mktype int32 32 s32int "%d") (mktype FWORD 16 s16int "%d") (mktype UFWORD 16 u16int (verb-unsigned 16)) (mktype LONGDATETIME 64 s64int (cons (if (for-posix?) "%s" "%τ") (λ (v) (~a "fmttime(" v ")"))) (λ (b index [offset #f]) (~a "(" ((autoparse 64 's64int) b index offset) ") - 2082844800LL"))) (mktype Tag 32 u32int (cons "%c%c%c%c" (λ (v) (~a v ">>24, " v ">>16, " v ">>8, " v ">>0")))) (mktype Offset16 16 u16int (verb-unsigned 16)) (mktype Offset24 24 u32int (verb-unsigned 32)) (mktype Offset32 32 u32int (verb-unsigned 32)) (mktype Version16Dot16 32 u32int (cons "%d.%d" (λ (v) (~a v ">>16, " v "&0xffff")))) (mktype Fixed 32 double "%g" (λ (b index [offset #f]) (~a "(" ((type-parse int32) b index offset) ")/65536.0f"))) (mktype F2DOT14 16 double "%g" (λ (b index [offset #f]) (define x (~a ((type-parse int16) b index offset))) (~a "(" x ">>14)+(" x "&((1<<14)-1))/16384.0"))) (mkcmplx SubHeader {uint16 firstCode} {uint16 entryCode} {int16 idDelta} {uint16 idRangeOffset}) ; same type for Sequential and Constant (mkcmplx MapGroup {uint32 startCharCode} {uint32 endCharCode} {uint32 startGlyphID}) (mkcmplx SubtableCmap0 {uint16 length} {uint16 language} {uint8 glyphIdArray [256]}) ; FIXME (mkcmplx SubtableCmap2 {uint16 length} {uint16 language} #;{uint16 subHeaderKeys [256]} #;{SubHeader subHeaders [?]} #;{uint16 glyphIdArray [?]}) (mkcmplx SubtableCmap4 {uint16 length} {uint16 language} {uint16 segCountX2 (> 0)} {uint16 searchRange} {uint16 entrySelector} {uint16 rangeShift} {uint16 endCode [/ segCountX2 2]} {uint16 reservedPad unused} {uint16 startCode [/ segCountX2 2]} {int16 idDelta [/ segCountX2 2]} {int16 idRangeOffset [/ segCountX2 2]} {uint16 glyphIdArray [/ (- length (+ (* 8 2) (* segCountX2 4))) 2]}) (mkcmplx SubtableCmap6 {uint16 length} {uint16 language} {uint16 firstCode} {uint16 entryCount} {uint16 glyphIdArray [entryCount]}) (mkcmplx SubtableCmap8 {uint16 length} {uint16 language} {uint8 is32 [8192]} {uint32 numGroups} {MapGroup groups [numGroups]}) (mkcmplx SubtableCmap10 {uint16 reserved} {uint32 length} {uint32 language} {uint32 startCharCode} {uint32 numChars} {uint16 glyphIdArray [/ (- length (+ (* 2 2) (* 4 4))) 2]}) (mkcmplx SubtableCmap12or13 {uint16 reserved} {uint32 length} {uint32 language} {uint32 numGroups} {MapGroup groups [numGroups]}) (mkcmplx UnicodeRange {uint24 startUnicodeValue} {uint8 additionalCount}) (mkcmplx DefaultUVS {uint32 numUnicodeValueRanges} {UnicodeRange ranges [numUnicodeValueRanges]}) (mkcmplx UVSMapping {uint24 unicodeValue} {uint16 glyphID}) (mkcmplx NonDefaultUVS {uint32 numUVSMappings} {UVSMapping uvsMappings [numUVSMappings]}) (mkcmplx VariationSelector {uint24 varSelector} {Offset32 defaultUVSOffset} {Offset32 nonDefaultUVSOffset} {DefaultUVS defaultUVS (at defaultUVSOffset)} {NonDefaultUVS nonDefaultUVS (at nonDefaultUVSOffset)}) (mkcmplx SubtableCmap14 {uint32 length} {uint32 numVarSelectorRecords} {VariationSelector varSelector [numVarSelectorRecords]}) (mkcmplx SubtableCmap {uint16 format (== 0 2 4 6 8 10 12 13 14)} ; FIXME these fields should be put into a union automatically {SubtableCmap0 sub0 (== format 0)} {SubtableCmap2 sub2 (== format 2)} {SubtableCmap4 sub4 (== format 4)} {SubtableCmap6 sub6 (== format 6)} {SubtableCmap8 sub8 (== format 8)} {SubtableCmap10 sub10 (== format 10)} {SubtableCmap12or13 sub12or13 (== format 12 13)} {SubtableCmap14 sub14 (== format 14)}) (mkcmplx EncodingRecord {uint16 platformID (<= 4)} {uint16 encodingID} {Offset32 subtableOffset} {SubtableCmap subtable (at subtableOffset)}) (mkcmplx TableCmap {uint16 version unused (== 0)} {uint16 numTables} {EncodingRecord encodingRecords [numTables]} #:tag "cmap" #:extra (list (cons 'read (list (~a "if(otfcmap(v) < 0)") (~a " goto err;"))) (cons 'field (list (~a "RuneMapper mappers[8];") (~a "int numMappers;"))))) (define headFlags #hash((0 . HEAD_FL_BASELINE_Y_0) (1 . HEAD_FL_LEFT_SIDEBEARING_X_0) (2 . HEAD_FL_INSTR_DEP_POINT_SZ) (3 . HEAD_FL_FORCE_PPEM_INT) (4 . HEAD_FL_INSTR_ALT_ADVANCE_WIDTH) (11 . HEAD_FL_LOSSLESS) (12 . HEAD_FL_CONVERTED) (13 . HEAD_FL_CLEARTYPE) (14 . HEAD_FL_LAST_RESORT))) (mkcmplx TableHead {uint16 majorVersion unused (== 1)} {uint16 minorVersion unused (== 0)} {Fixed fontRevision unused} {uint32 checksumAdjustment unused} {uint32 magicNumber unused (== #x5f0f3cf5)} {uint16 flags hex (bits headFlags)} {uint16 unitsPerEm (>= 16) (<= 16384)} {LONGDATETIME created} {LONGDATETIME modified} {int16 xMin} {int16 yMin} {int16 xMax} {int16 yMax} {uint16 macStyle} {uint16 lowestRecPPEM} {int16 fontDirectionHint (>= -2) (<= 2) unused} {int16 indexToLocFormat ->o (<= 1)} {int16 glyphDataFormat unused (== 0)} #:tag "head") (mkcmplx TableHhea {uint16 majorVersion (== 1)} {uint16 minorVersion (== 0)} {FWORD ascender} {FWORD descender} {FWORD lineGap} {UFWORD advanceWidthMax} {FWORD minLeftSideBearing} {FWORD minRightSideBearing} {FWORD xMaxExtent} {int16 caretSlopeRise} {int16 caretSlopeRun} {int16 caretOffset} {int16 reserved [4] unused} {int16 metricDataFormat (== 0)} {uint16 numberOfHMetrics ->o} #:tag "hhea") (mkcmplx EbdtComponent {uint16 glyphID} {int8 xOffset} {int8 yOffset}) (mkcmplx Glyf {int16 numberOfContours ->o} {int16 xMin} {int16 yMin} {int16 xMax} {int16 yMax} #:extra (list (cons 'field (list (~a "int index;") (~a "int type;") (~a "union {") ; (~a " ComponentGlyph *component;") (~a " SimpleGlyph *simple;") (~a " BitmapGlyph *bitmap;") (~a "};"))) (cons 'read (list (~a "if(v->numberOfContours < 0){") (~a " if(read_ComponentGlyph(o, &v->component, 0) < 0)") (~a " goto err;") (~a " v->type = GLYPH_COMPONENT;") (~a "}else if(v->numberOfContours > 0){") (~a " if(read_SimpleGlyph(o, &v->simple) < 0)") (~a " goto err;") (~a " v->type = GLYPH_SIMPLE;") (~a "}else if(o->td.eblc != nil && o->td.ebdt != nil)") (~a " v->type = GLYPH_BITMAP;") (~a "else") (~a " v->type = GLYPH_EMPTY;"))) (cons 'print (list (~a "if(v->type == GLYPH_BITMAP){") (~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"bitmap\");") (~a " print_BitmapGlyph(f, indent+indentΔ, o, v->bitmap);") (~a "}else if(v->type == GLYPH_COMPONENT){") (~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"component\");") (~a " print_ComponentGlyph(f, indent+indentΔ, o, v->component);") (~a "}else if(v->type == GLYPH_SIMPLE){") (~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"simple\");") (~a " print_SimpleGlyph(f, indent+indentΔ, o, v->simple);") (~a "}"))))) (mkcmplx LongHorMetric {UFWORD advanceWidth} {FWORD lsb}) (mkcmplx TableMaxp {Version16Dot16 version (== #x05000 #x10000) unused} {uint16 numGlyphs ->o} ; a bunch of fields ignored here #:tag "maxp") (mkcmplx TableHmtx {LongHorMetric hMetrics [o->numberOfHMetrics]} {FWORD leftSideBearings [- o->numGlyphs o->numberOfHMetrics]} #:tag "hmtx" #:after (list TableHhea TableMaxp)) (mkcmplx TablePost {Version16Dot16 version (== #x10000 #x20000 #x25000 #x30000) unused} {Fixed italicAngle} {FWORD underlinePosition} {FWORD underlineThickness} {uint32 isFixedPitch} ; a bunch of fields ignored here #:tag "post") (mkcmplx NameRecord {uint16 platformID ->o} {uint16 encodingID ->o} {uint16 languageID} {uint16 nameID} {uint16 stringLength} {Offset16 stringOffset} {String string [stringLength] (at (+ o->storageOffset stringOffset))}) (mkcmplx LangTagRecord {uint16 length} {Offset16 langTagOffset} {String-UTF16 langTag [length] (at (+ o->storageOffset langTagOffset))}) (mkcmplx TableName {uint16 version (== 0 1)} {uint16 count} {Offset16 storageOffset ->o} {NameRecord nameRecord [count]} {uint16 langTagCount (>= version 1)} {LangTagRecord langTagRecord [langTagCount] (>= version 1)} #:tag "name") (mkcmplx BigGlyphMetrics {uint8 height} {uint8 width} {int8 horiBearingX} {int8 horiBearingY} {uint8 horiAdvance} {int8 vertBearingX} {int8 vertBearingY} {uint8 vertAdvance}) (mkcmplx SmallGlyphMetrics {uint8 height} {uint8 width} {int8 bearingX} {int8 bearingY} {uint8 advance}) (mkcmplx SbitLineMetrics {int8 ascender} {int8 descender} {uint8 widthMax} {int8 caretSlopeNumerator} {int8 caretSlopeDenumerator} {int8 caretOffset} {int8 minOriginSB} {int8 minAdvanceSB} {int8 maxBeforeBL} {int8 minAfterBL} {int8 pad [2] unused}) (mkcmplx IndexSubtable1 {Offset32 sbitOffsets [+ (- o->lastGlyphIndex o->firstGlyphIndex) 2]}) (mkcmplx IndexSubtable2 {uint32 imageSize} {BigGlyphMetrics bigMetrics}) (mkcmplx IndexSubtable3 {Offset16 sbitOffsets [+ (- o->lastGlyphIndex o->firstGlyphIndex) 2]}) (mkcmplx GlyphIdOffsetPair {uint16 glyphID} {Offset16 sbitOffset}) (mkcmplx IndexSubtable4 {uint32 numGlyphs} {GlyphIdOffsetPair glyphArray [+ numGlyphs 1]}) (mkcmplx IndexSubtable5 {uint32 imageSize} {BigGlyphMetrics bigMetrics} {uint32 numGlyphs} {uint16 glyphIdArray [numGlyphs]}) (mkcmplx IndexSubtable {uint16 indexFormat (>= 1) (<= 5)} {uint16 imageFormat} {Offset32 imageDataOffset} {IndexSubtable1 sub1 (== indexFormat 1)} {IndexSubtable2 sub2 (== indexFormat 2)} {IndexSubtable3 sub3 (== indexFormat 3)} {IndexSubtable4 sub4 (== indexFormat 4)} {IndexSubtable5 sub5 (== indexFormat 5)}) (mkcmplx IndexSubtableRecord {uint16 firstGlyphIndex ->o} {uint16 lastGlyphIndex ->o} {Offset32 indexSubtableOffset} {IndexSubtable indexSubtable (at indexSubtableOffset)}) (define bitmapSizeFlags #hash((0 . BITMAPSIZE_FL_HORIZONTAL_METRICS) (1 . BITMAPSIZE_FL_VERTICAL_METRICS))) (mkcmplx BitmapSize {Offset32 indexSubtableListOffset} {uint32 indexSubtableListSize} {uint32 numberOfIndexSubtables} {uint32 colorRef unused} {SbitLineMetrics hori} {SbitLineMetrics vert} {uint16 startGlyphIndex} {uint16 endGlyphIndex} {uint8 ppemX} {uint8 ppemY} {uint8 bitDepth (== 1 2 4 8)} {int8 flags hex (bits bitmapSizeFlags)} {IndexSubtableRecord indexSubtableList [numberOfIndexSubtables] (at indexSubtableListOffset)}) (mkcmplx TableEBDT {uint16 majorVersion (== 2)} {uint16 minorVersion (== 0) unused} #:tag "EBDT") (mkcmplx TableEBLC {uint16 majorVersion (== 2) unused} {uint16 minorVersion (== 0) unused} {uint32 numSizes} {BitmapSize bitmapSizes [numSizes]} #:tag "EBLC") (mkcmplx AttachList {Offset16 coverageOffset} {uint16 glyphCount} {Offset16 attachPointOffsets [glyphCount]}) (mkcmplx AttachPoint {uint16 pointCount} {uint16 pointIndices [pointCount]}) (mkcmplx LigCaretList {Offset16 coverageOffset} {uint16 ligGlyphCount} {Offset16 ligGlyphOffsets [ligGlyphCount]}) (mkcmplx LigGlyph {uint16 caretCount} {Offset16 caretValueOffsets [caretCount]}) (mkcmplx CaretValue {uint16 format (>= 1) (<= 3)} {int16 coordinate (== format 1 3)} {uint16 caretValuePointIndex (== format 2)} {Offset16 deviceOffset (== format 3)}) (mkcmplx ValueRecord {int16 xPlacement} {int16 yPlacement} {int16 xAdvance} {int16 yAdvance} {Offset16 xPlaDeviceOffset} {Offset16 yPlaDeviceOffset} {Offset16 xAdvDeviceOffset} {Offset16 yAdvDeviceOffset}) (mkcmplx SinglePos {uint16 format (== 1 2)} {Offset16 coverageOffset} {uint16 valueFormat} {ValueRecord valueRecord (== format 1)} {uint16 valueCount (== format 2)} {ValueRecord valueRecords [valueCount] (== format 2)}) (mkcmplx TableGDEF {uint16 majorVersion (== 1) unused} {uint16 minorVersion (== 0 2 3)} {Offset16 glyphClassDefOffset} {Offset16 attachListOffset} {Offset16 ligCaretListOffset} {Offset16 markAttachClassDefOffset} {Offset16 markGlyphSetsDefOffset (>= minorVersion 2)} {Offset32 itemVarStoreOffset (>= minorVersion 3)} #:tag "GDEF") (mkcmplx LangSys {Offset16 lookupOrderOffset unused} {uint16 requiredFeatureIndex} {uint16 featureIndexCount} {uint16 featureIndices [featureIndexCount]}) (mkcmplx LangSysRecord {Tag langSysTag} {Offset16 langSysOffset} {LangSys langSys (at langSysOffset)}) (mkcmplx Script {Offset16 defaultLangSysOffset} {uint16 langSysCount} {LangSysRecord langSysRecords [langSysCount]} {LangSys defaultLangSys (at defaultLangSysOffset)}) (mkcmplx ScriptRecord {Tag scriptTag} {Offset16 scriptOffset} {Script script (at scriptOffset)}) (mkcmplx ScriptList {uint16 scriptCount} {ScriptRecord scriptRecords [scriptCount]}) (mkcmplx Feature {Offset16 featureParamsOffset} {uint16 lookupIndexCount} {uint16 lookupListIndices [lookupIndexCount]}) (mkcmplx FeatureRecord {Tag featureTag} {Offset16 featureOffset} {Feature feature (at featureOffset)}) (mkcmplx FeatureList {uint16 featureCount} {FeatureRecord featureRecords [featureCount]}) (mkcmplx SequenceLookup {uint16 sequenceIndex} {uint16 lookupListIndex}) (mkcmplx ChainedSequenceRule {uint16 backtrackGlyphCount} {uint16 backtrackSequence [backtrackGlyphCount]} {uint16 inputGlyphCount} {uint16 inputSequence [- inputGlyphCount 1]} {uint16 lookaheadGlyphCount} {uint16 lookaheadSequence [lookaheadGlyphCount]} {uint16 seqLookupCount} {SequenceLookup seqLookupRecords [seqLookupCount]}) (mkcmplx ChainedSequenceRuleSet {uint16 chainedSeqRuleCount} {Offset16 chainedSeqRuleOffsets [chainedSeqRuleCount]} {ChainedSequenceRule chainedSeqRule [chainedSeqRuleCount] (at chainedSeqRuleOffsets)}) (mkcmplx ChainedSequenceContextFormat1 {Offset16 coverageOffset} {uint16 chainedSeqRuleSetCount} {Offset16 chainedSeqRuleSetOffsets [chainedSeqRuleSetCount]} {ChainedSequenceRuleSet chainedSeqRuleSet [chainedSeqRuleSetCount] (at chainedSeqRuleSetOffsets)}) (mkcmplx ChainedClassSequenceRuleSet {uint16 chainedClassSeqRuleCount} {Offset16 chainedClassSeqRuleOffsets [chainedClassSeqRuleCount]} {ChainedSequenceRule chainedClassSeqRules [chainedClassSeqRuleCount] (at chainedClassSeqRuleOffsets)}) (mkcmplx ChainedSequenceContextFormat2 {Offset16 coverageOffset} {Offset16 backtrackClassDefOffset} {Offset16 inputClassDefOffset} {Offset16 lookaheadClassDefOffset} {uint16 chainedClassSeqRuleSetCount} {Offset16 chainedClassSeqRuleSetOffsets [chainedClassSeqRuleSetCount]} {ChainedClassSequenceRuleSet chainedClassSequenceRuleSets [chainedClassSeqRuleSetCount] (at chainedClassSeqRuleSetOffsets)}) (mkcmplx ChainedSequenceContextFormat3 {uint16 backtrackGlyphCount} {Offset16 backtrackCoverageOffsets [backtrackGlyphCount]} {uint16 inputGlyphCount} {Offset16 inputCoverageOffsets [inputGlyphCount]} {uint16 lookaheadGlyphCount} {Offset16 lookaheadCoverageOffsets [lookaheadGlyphCount]} {uint16 seqLookupCount} {SequenceLookup seqLookupRecords [seqLookupCount]}) (mkcmplx ChainedSequenceContext {uint16 format} ; FIXME union {ChainedSequenceContextFormat1 f1 (== format 1)} {ChainedSequenceContextFormat2 f2 (== format 2)} {ChainedSequenceContextFormat3 f3 (== format 3)}) (mkcmplx PairValue {uint16 secondGlyph} {ValueRecord valueRecord1} {ValueRecord valueRecord2}) (mkcmplx PairSet {uint16 pairValueCount} {PairValue pairValueRecords [pairValueCount]}) (mkcmplx PairPosFormat1 {uint16 pairSetCount} {Offset16 pairSetOffsets [pairSetCount]} {PairSet pairSets [pairSetCount] (at pairSetOffsets)}) (mkcmplx Class2 {ValueRecord valueRecord1} {ValueRecord valueRecord2}) (mkcmplx Class1 {Class2 class2Records [o->class2Count]}) (mkcmplx PairPosFormat2 {Offset16 classDef1Offset} {Offset16 classDef2Offset} {uint16 class1Count} {uint16 class2Count ->o} {Class1 class1Records [class1Count]}) (mkcmplx PairPos {uint16 format (== 1 2)} {Offset16 coverageOffset} {uint16 valueFormat1} {uint16 valueFormat2} {PairPosFormat1 f1 (== format 1)} {PairPosFormat2 f2 (== format 2)}) (mkcmplx EntryExit {Offset16 entryAnchorOffset} {Offset16 exitAnchorOffset}) (mkcmplx CursivePos {uint16 format (== 1) unused} {Offset16 coverageOffset} {uint16 entryExitCount} {EntryExit entryExitRecords [entryExitCount]}) (define lookupFlags #hash((0 . LOOKUP_FL_RIGHT_TO_LEFT) (1 . LOOKUP_FL_IGNORE_BASE_GLYPHS) (2 . LOOKUP_FL_IGNORE_LIGATURES) (3 . LOOKUP_FL_IGNORE_MARKS) (4 . LOOKUP_FL_USE_MARK_FILTERING_SET))) ; FIXME 0xff00 is attachment class filter (define lookupTypes #hash((1 . LOOKUP_TYPE_SINGLE_ADJUSTMENT) (2 . LOOKUP_TYPE_PAIR_ADJUSTMENT) (3 . LOOKUP_TYPE_CURSIVE_ATTACHMENT) (4 . LOOKUP_TYPE_MARK_TO_BASE_ATTACHMENT) (5 . LOOKUP_TYPE_MARK_TO_LIGATURE_ATTACHMENT) (6 . LOOKUP_TYPE_MARK_TO_MARK_ATTACHMENT) (7 . LOOKUP_TYPE_CONTEXTUAL_POSITIONING) (8 . LOOKUP_TYPE_CHAINED_CONTEXTS_POSITIONING) (9 . LOOKUP_TYPE_POSITIONING_EXTENSION))) (mkcmplx Lookup {uint16 lookupType (enum lookupTypes)} {uint16 lookupFlag hex (bits lookupFlags)} {uint16 subTableCount} {Offset16 subtableOffsets [subTableCount]} {uint16 markFilteringSet} ; FIXME union {SinglePos singleAdjustment [subTableCount] (at subtableOffsets) (== lookupType LOOKUP_TYPE_SINGLE_ADJUSTMENT)} {PairPos pairAdjustment [subTableCount] (at subtableOffsets) (== lookupType LOOKUP_TYPE_PAIR_ADJUSTMENT)} {CursivePos cursiveAttachment [subTableCount] (at subtableOffsets) (== lookupType LOOKUP_TYPE_CURSIVE_ATTACHMENT)} ; FIXME add more {ChainedSequenceContext chainedContextsPositioning [subTableCount] (at subtableOffsets) (== lookupType LOOKUP_TYPE_CHAINED_CONTEXTS_POSITIONING)}) (mkcmplx LookupList {uint16 lookupCount} {Offset16 lookupOffsets [lookupCount]} {Lookup lookups [lookupCount] (at lookupOffsets)}) (mkcmplx TableGPOS {uint16 majorVersion (== 1) unused} {uint16 minorVersion (<= 1)} {Offset16 scriptListOffset} {Offset16 featureListOffset} {Offset16 lookupListOffset} {Offset32 featureVariationsOffset (== minorVersion 1)} {ScriptList scriptList (at scriptListOffset)} {FeatureList featureList (at featureListOffset)} {LookupList lookupList (at lookupListOffset)} #:tag "GPOS") (mkcmplx TableGSUB {uint16 majorVersion (== 1) unused} {uint16 minorVersion (<= 1)} {Offset16 scriptListOffset} {Offset16 featureListOffset} {Offset16 lookupListOffset} {Offset32 featureVariationsOffset (== minorVersion 1)} {ScriptList scriptList (at scriptListOffset)} {FeatureList featureList (at featureListOffset)} #:tag "GSUB") (mkcmplx MathValueRecord {FWORD value} {Offset16 deviceOffset}) (mkcmplx MathConstants {int16 scriptPercentScaleDown} {int16 scriptScriptPercentScaleDown} {UFWORD delimitedSubFormulaMinHeight} {UFWORD displayOperatorMinHeight} {MathValueRecord mathLeading} {MathValueRecord axisHeight} {MathValueRecord accentBaseHeight} {MathValueRecord flattenedAccentBaseHeight} {MathValueRecord subscriptShiftDown} {MathValueRecord subscriptTopMax} {MathValueRecord subscriptBaselineDropMin} {MathValueRecord superscriptShiftUp} {MathValueRecord superscriptShiftUpCramped} {MathValueRecord superscriptBottomMin} {MathValueRecord superscriptBaselineDropMax} {MathValueRecord subSuperscriptGapMin} {MathValueRecord superscriptBottomMaxWithSubscript} {MathValueRecord spaceAfterScript} {MathValueRecord upperLimitGapMin} {MathValueRecord upperLimitBaselineRiseMin} {MathValueRecord lowerLimitGapMin} {MathValueRecord lowerLimitBaselineDropMin} {MathValueRecord stackTopShiftUp} {MathValueRecord stackTopDisplayStyleShiftUp} {MathValueRecord stackBottomShiftDown} {MathValueRecord stackBottomDisplayStyleShiftDown} {MathValueRecord stackGapMin} {MathValueRecord stackDisplayStyleGapMin} {MathValueRecord stretchStackTopShiftUp} {MathValueRecord stretchStackBottomShiftDown} {MathValueRecord stretchStackGapAboveMin} {MathValueRecord stretchStackGapBelowMin} {MathValueRecord fractionNumeratorShiftUp} {MathValueRecord fractionNumeratorDisplayStyleShiftUp} {MathValueRecord fractionDenominatorShiftDown} {MathValueRecord fractionDenominatorDisplayStyleShiftDown} {MathValueRecord fractionNumeratorGapMin} {MathValueRecord fractionNumDisplayStyleGapMin} {MathValueRecord fractionRuleThickness} {MathValueRecord fractionDenominatorGapMin} {MathValueRecord fractionDenomDisplayStyleGapMin} {MathValueRecord skewedFractionHorizontalGap} {MathValueRecord skewedFractionVerticalGap} {MathValueRecord overbarVerticalGap} {MathValueRecord overbarRuleThickness} {MathValueRecord overbarExtraAscender} {MathValueRecord underbarVerticalGap} {MathValueRecord underbarRuleThickness} {MathValueRecord underbarExtraDescender} {MathValueRecord radicalVerticalGap} {MathValueRecord radicalDisplayStyleVerticalGap} {MathValueRecord radicalRuleThickness} {MathValueRecord radicalExtraAscender} {MathValueRecord radicalKernBeforeDegree} {MathValueRecord radicalKernAfterDegree} {int16 radicalDegreeBottomRaisePercent}) (mkcmplx MathItalicsCorrectionInfo {Offset16 italicsCorrectionCoverageOffset} {uint16 italicsCorrectionCount} {MathValueRecord italicsCorrection [italicsCorrectionCount]}) (mkcmplx MathTopAccentAttachment {Offset16 topAccentCoverageOffset} {uint16 topAccentAttachmentCount} {MathValueRecord topAccentAttachment [topAccentAttachmentCount]}) (mkcmplx MathKernInfoRecord {Offset16 topRightMathKernOffset} {Offset16 topLeftMathKernOffset} {Offset16 bottomRightMathKernOffset} {Offset16 bottomLeftMathKernOffset}) (mkcmplx MathKernInfo {Offset16 mathKernCoverageOffset} {uint16 mathKernCount} {MathKernInfoRecord mathKernInfoRecords [mathKernCount]}) (mkcmplx MathKern {uint16 heightCount} {MathValueRecord correctionHeight [heightCount]} {MathValueRecord kernValues [heightCount]}) (mkcmplx Coverage1 {uint16 glyphCount} {uint16 glyphArray [glyphCount]}) (mkcmplx RangeRecord {uint16 startGlyphID} {uint16 endGlyphID} {uint16 startCoverageIndex}) (mkcmplx Coverage2 {uint16 rangeCount} {RangeRecord rangeRecords [rangeCount]}) (mkcmplx Coverage {uint16 format (== 1 2)} {Coverage1 cov1 (== format 1)} {Coverage2 cov2 (== format 2)}) (mkcmplx MathGlyphVariantRecord {uint16 variantGlyph} {UFWORD advanceMeasurement}) (mkcmplx GlyphPart {uint16 glyphID} {UFWORD startConnectorLength} {UFWORD endConnectorLength} {UFWORD fullAdvance} {uint16 partFlags}) (mkcmplx GlyphAssembly {MathValueRecord italicsCorrection} {uint16 partCount} {GlyphPart partRecords [partCount]}) (mkcmplx MathGlyphConstruction {Offset16 glyphAssemblyOffset} {uint16 variantCount} {MathGlyphVariantRecord mathGlyphVariantRecords [variantCount]} {GlyphAssembly glyphAssembly (at glyphAssemblyOffset)}) (mkcmplx MathVariants {UFWORD minConnectorOverlap} {Offset16 vertGlyphCoverageOffset} {Offset16 horizGlyphCoverageOffset} {uint16 vertGlyphCount} {uint16 horizGlyphCount} {Offset16 vertGlyphConstructionOffsets [vertGlyphCount]} {Offset16 horizGlyphConstructionOffsets [horizGlyphCount]} {Coverage vertGlyphCoverage (at vertGlyphCoverageOffset)} {Coverage horizGlyphCoverage (at horizGlyphCoverageOffset)} {MathGlyphConstruction vertGlyphConstruction [vertGlyphCount] (at vertGlyphConstructionOffsets)} {MathGlyphConstruction horizGlyphConstruction [horizGlyphCount] (at horizGlyphConstructionOffsets)}) (mkcmplx MathGlyphInfo {Offset16 mathItalicsCorrectionInfoOffset} {Offset16 mathTopAccentAttachmentOffset} {Offset16 extendedShapeCoverageOffset} {Offset16 mathKernInfoOffset} {MathItalicsCorrectionInfo mathItalicsCorrectionInfo (at mathItalicsCorrectionInfoOffset)} {MathTopAccentAttachment mathTopAccentAttachment (at mathTopAccentAttachmentOffset)} {MathKernInfo mathKernInfo (at mathKernInfoOffset)} {Coverage extendedShapeCoverage (at extendedShapeCoverageOffset)}) (mkcmplx TableMATH {uint16 majorVersion (== 1) unused} {uint16 minorVersion (== 0) unused} {Offset16 mathConstantsOffset} {Offset16 mathGlyphInfoOffset} {Offset16 mathVariantsOffset} {MathConstants mathConstants (at mathConstantsOffset)} {MathGlyphInfo mathGlyphInfo (at mathGlyphInfoOffset)} {MathVariants mathVariants (at mathVariantsOffset)} #:tag "MATH") (mkcmplx KernPair {uint16 left} {uint16 right} {FWORD value}) (mkcmplx KernSubtable0 {uint16 nPairs} {uint16 searchRange} {uint16 entrySelector} {uint16 rangeShift} {KernPair kernPairs [nPairs]}) (mkcmplx KernClass {uint16 firstGlyph} {uint16 nGlyphs} {uint16 values [nGlyphs]}) (mkcmplx KernSubtable2 {uint16 rowWidth} {Offset16 leftClassOffset} {Offset16 rightClassOffset} {Offset16 kerningArrayOffset} {KernClass leftClass (at leftClassOffset)} {KernClass rightClass (at rightClassOffset)} {FWORD kerningArray [/ rowWidth 2]}) (define kernCoverageFlags #hash((0 . KERN_FL_HORIZONTAL) (1 . KERN_FL_MINIMUM) (2 . KERN_FL_CROSS_STREAM) (3 . KERN_FL_OVERRIDE))) (mkcmplx KernSubtable {uint16 version (== 0) unused} {uint16 length (>= 6)} ; including this header {uint16 coverage hex (bits kernCoverageFlags)} {KernSubtable0 sub0 (== (>> coverage 8) 0)} {KernSubtable2 sub2 (== (>> coverage 8) 2)}) (mkcmplx TableKern {uint16 version (== 0) unused} {uint16 nTables} {KernSubtable subtables [nTables]} #:tag "kern") (mkcmplx TableLoca {Offset16 shortOffsets [+ o->numGlyphs 1] (== o->indexToLocFormat 0)} {Offset32 longOffsets [+ o->numGlyphs 1] (== o->indexToLocFormat 1)} #:tag "loca" #:after (list TableHead TableMaxp) #:optional #t) (mkcmplx GlyphData {int16 originOffsetX} {int16 originOffsetY} {Tag graphicType}) (mkcmplx SbixStrike {uint16 ppem} {uint16 ppi} {Offset32 glyphDataOffsets [+ o->numGlyphs 1]} {GlyphData glyphData [o->numGlyphs] (at glyphDataOffsets)}) (define sbixFlags #hash((1 . SBIX_FL_DRAW_OUTLINES))) (mkcmplx TableSbix {uint16 version (== 1) unused} {uint16 flags hex (bits sbixFlags)} {uint32 numStrikes} {Offset32 strikeOffsets [numStrikes]} {SbixStrike strikes [numStrikes] (at strikeOffsets)} #:tag "sbix") (define variationAxisRecordFlags #hash((0 . VARIATIONAXISRECORD_FL_HIDDEN_AXIS))) (mkcmplx VariationAxisRecord {Tag axisTag} {Fixed minValue} {Fixed defaultValue} {Fixed maxValue} {uint16 flags hex (bits variationAxisRecordFlags)} {uint16 axisNameID}) (mkcmplx UserTuple {Fixed coordinates [o->axisCount]}) (mkcmplx InstanceRecord {uint16 subfamilyNameID} {uint16 flags hex unused} {UserTuple coordinates} {uint16 postScriptNameID (== o->instanceSize (+ (* o->axisCount 4) 6))}) (mkcmplx AxisInstances {VariationAxisRecord axes [o->axisCount]} {InstanceRecord instaces [o->instanceCount]}) (mkcmplx TableFvar {uint16 majorVersion (== 1) unused} {uint16 minorVersion (== 0) unused} {Offset16 axesArrayOffset} {uint16 reserved unused} {uint16 axisCount ->o} {uint16 axisSize (== 20) unused} {uint16 instanceCount ->o} {uint16 instanceSize ->o} {AxisInstances axisInstances (at axesArrayOffset)} #:tag "fvar") (mkcmplx RegionAxisCoordinates {F2DOT14 startCoord} {F2DOT14 peakCoord} {F2DOT14 endCoord}) ; FIXME add an #:extra validation test here? (mkcmplx VariationRegion {RegionAxisCoordinates regionAxes [o->axisCount]}) (mkcmplx VariationRegionList {uint16 axisCount #;(== o->axisCount)} ; FIXME {uint16 regionCount} {VariationRegion variationRegion [regionCount]}) (mkcmplx ItemVariationData {uint16 itemCount} {uint16 wordDeltaCount hex} ; FIXME &0x8000 LONG_WORDS, &0x7fff WORD_DELTA_COUNT_MASK {uint16 regionIndexCount} {uint16 regionIndexes [regionIndexCount]} #;{DeltaSet deltaSets [itemCount]}) ; FIXME this one's awkward (mkcmplx ItemVariationStore {uint16 format (== 1) unused} {Offset32 variationRegionListOffset} {uint16 itemVariationDataCount} {Offset32 itemVariationDataOffsets [itemVariationDataCount]} {ItemVariationData itemVariationData [itemVariationDataCount] (at itemVariationDataOffsets)}) (mkcmplx DeltaSetIndexMap {uint8 format (== 0 1)} {uint8 entryFormat hex} ; FIXME flags/masks here {uint16 mapCount0 (== format 0)} {uint32 mapCount1 (== format 1)} {uint8 mapData #;[?]}) ; FIXME here we go with even more awkward one (mkcmplx TableHVAR {uint16 majorVersion (== 1) unused} {uint16 minorVersion (== 0) unused} {Offset32 itemVariationStoreOffset} {Offset32 advanceWidthMappingOffset} {Offset32 lsbMappingOffset} {Offset32 rsbMappingOffset} {ItemVariationStore itemVariationStore (at itemVariationStoreOffset)} {DeltaSetIndexMap advanceWidthMapping (at advanceWidthMappingOffset)} {DeltaSetIndexMap lsbMapping (at lsbMappingOffset)} {DeltaSetIndexMap rsbMapping (at rsbMappingOffset)} #:tag "HVAR" #:after (list TableFvar)) ; as dep to test axisCount within matching the fvar's (mkcmplx TableFFTM {uint32 version} {LONGDATETIME fontforge (== version 1)} {LONGDATETIME created (== version 1)} {LONGDATETIME modified (== version 1)} #:tag "FFTM") (mkcmplx SignatureBlock1 {uint16 reserved1 unused} {uint16 reserved2 unused} {uint32 signatureLength} {uint8 signature [signatureLength]}) (mkcmplx SignatureRecord {uint32 format} {uint32 length} {Offset32 signatureBlockOffset} {SignatureBlock1 signatureBlock1 (at signatureBlockOffset) (== format 1)}) (define dsigFlags #hash((0 . DSIG_CANNOT_BE_RESIGNED))) (mkcmplx TableDSIG {uint32 version (== 1) unused} {uint16 numSignatures} {uint16 flags hex (bits dsigFlags)} {SignatureRecord signatureRecords [numSignatures]} #:tag "DSIG") (mkcmplx AxisRecord {Tag axisTag} {uint16 axisNameID} {uint16 axisOrdering} {uint8 unused [- o->designAxisSize 8] unused}) (mkcmplx AxisValueTable1 {uint16 axisIndex} {uint16 flags} {uint16 valueNameID} {Fixed value}) (mkcmplx AxisValueTable2 {uint16 axisIndex} {uint16 flags} {uint16 valueNameID} {Fixed nominalValue} {Fixed rangeMinValue} {Fixed rangeMaxValue}) (mkcmplx AxisValueTable3 {uint16 axisIndex} {uint16 flags} {uint16 valueNameID} {Fixed value} {Fixed linkedValue}) (mkcmplx AxisValue {uint16 axisIndex} {Fixed value}) (mkcmplx AxisValueTable4 {uint16 axisCount} {uint16 flags} {uint16 valueNameID} {AxisValue axisValues [axisCount]}) (mkcmplx AxisValueTable {uint16 format} {AxisValueTable1 f1 (== format 1)} ; FIXME should be a union {AxisValueTable2 f2 (== format 2)} {AxisValueTable3 f3 (== format 3)} {AxisValueTable3 f4 (== format 4)}) (mkcmplx DesignAxes {AxisRecord designAxes [o->designAxisCount]} {Offset16 axisValueTableOffsets [o->axisValueCount]} ; FIXME each offset is from the start of this field itself? {AxisValueTable axisValueTables [o->axisValueCount] (at axisValueTableOffsets)}) (mkcmplx TableSTAT {uint16 majorVersion (== 1) unused} {uint16 minorVersion (== 0 1 2)} ; 0 is deprecated {uint16 designAxisSize ->o} {uint16 designAxisCount ->o} {Offset32 designAxesOffset} {uint16 axisValueCount ->o} {Offset32 offsetToAxisValueOffsets} ; FIXME wtf??? {uint16 elidedFallbackNameID (> minorVersion 0)} {DesignAxes designAxes (at designAxesOffset)} #:tag "STAT") (define rangeGaspBehaviorFlags #hash((0 . GASP_GRIDFIT) (1 . GASP_DOGRAY) (2 . GASP_SYMMETRIC_GRIDFIT) (3 . GASP_SYMMETRIC_SMOOTHING))) (mkcmplx GaspRange {uint16 rangeMaxPPEM} {uint16 rangeGaspBehavior hex (bits rangeGaspBehaviorFlags)}) (mkcmplx TableGasp {uint16 version (== 0 1)} {uint16 numRanges} {GaspRange gaspRanges [numRanges]} #:tag "gasp") (mkcmplx Tuple {F2DOT14 coordinates [o->axisCount]}) (define tupleIndexFlags #hash((13 . TUPLEINDEX_FL_PRIVATE_POINT_NUMBERS) (14 . TUPLEINDEX_FL_INTERMEDIATE_REGION) (15 . TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE))) (mkcmplx TupleVariationHeader {uint16 variationDataSize} {uint16 tupleIndex (bits tupleIndexFlags)} ; FIXME 0xfff is TUPLE_INDEX_MASK {Tuple peakTuple (!= (& tupleIndex TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE) 0)} {Tuple intermediateStartTuple (!= (& tupleIndex TUPLEINDEX_FL_INTERMEDIATE_REGION) 0)} {Tuple intermediateEndTuple (!= (& tupleIndex TUPLEINDEX_FL_INTERMEDIATE_REGION) 0)}) ; FIXME there is delta packed stuff here (define glyphVariationDataCountFlags #hash((15 . COUNT_FL_SHARED_POINT_NUMBERS))) (mkcmplx GlyphVariationData {uint16 tupleVariationCount (bits glyphVariationDataCountFlags)} {Offset16 dataOffset} {TupleVariationHeader tupleVariationHeaders [& tupleVariationCount #xfff]}) (define gvarFlags #hash((0 . GVAR_FL_LONG_OFFSETS))) (mkcmplx TableGvar {uint16 majorVersion (== 1) unused} {uint16 minorVersion (== 0) unused} {uint16 axisCount ->o} {uint16 sharedTupleCount} {Offset32 sharedTuplesOffset} {uint16 glyphCount} {uint16 flags hex (bits gvarFlags)} {Offset32 glyphVariationDataArrayOffset} {Offset16 glyphVariationDataOffsetsShort [+ glyphCount 1] (== (& flags GVAR_FL_LONG_OFFSETS) 0)} {Offset32 glyphVariationDataOffsetsLong [+ glyphCount 1] (!= (& flags GVAR_FL_LONG_OFFSETS) 0)} {GlyphVariationData glyphVariationData [glyphCount] (offset glyphVariationDataArrayOffset) (at glyphVariationDataOffsetsShort) (== (& flags GVAR_FL_LONG_OFFSETS) 0)} {GlyphVariationData glyphVariationData [glyphCount] (offset glyphVariationDataArrayOffset) (at glyphVariationDataOffsetsLong) (!= (& flags GVAR_FL_LONG_OFFSETS) 0)} {Tuple sharedTuples [sharedTupleCount] (at sharedTuplesOffset)} #:tag "gvar" #:after (list TableFvar)) (mkcmplx AxisValueMap {F2DOT14 fromCoordinate} {F2DOT14 toCoordinate}) (mkcmplx SegmentMaps {uint16 positionMapCount} {AxisValueMap axisValueMaps [positionMapCount]}) (mkcmplx TableAvar {uint16 majorVersion (== 1) unused} {uint16 minorVersion (== 0) unused} {uint16 reserved unused} {uint16 axisCount} ; FIXME validate to be the same as in fvar {SegmentMaps axisSegmentMaps [axisCount]} #:tag "avar") (mkcmplx TableOS/2 {uint16 version (<= 5)} {FWORD xAvgCharWidth} {uint16 usWeightClass} {uint16 usWidthClass} {uint16 fsType} {FWORD ySubscriptXSize} {FWORD ySubscriptYSize} {FWORD ySubscriptXOffset} {FWORD ySubscriptYOffset} {FWORD ySuperscriptXSize} {FWORD ySuperscriptYSize} {FWORD ySuperscriptXOffset} {FWORD ySuperscriptYOffset} {FWORD yStrikeoutSize} {FWORD yStrikeoutPosition} {int16 sFamilyClass} {uint8 panose [10]} {uint32 ulUnicodeRange1 hex} {uint32 ulUnicodeRange2 hex} {uint32 ulUnicodeRange3 hex} {uint32 ulUnicodeRange4 hex} {Tag achVendID} {uint16 fsSelection} {uint16 usFirstCharIndex} {uint16 usLastCharIndex} {FWORD sTypoAscender} {FWORD sTypoDescender} {FWORD sTypoLineGap} {UFWORD usWinAscent} {UFWORD usWinDescent} {uint32 ulCodePageRange1 (>= version 1) hex} {uint32 ulCodePageRange2 (>= version 1) hex} {FWORD sxHeight (>= version 2)} {FWORD sCapHeight (>= version 2)} {uint16 usDefaultChar (>= version 2) hex} {uint16 usBreakChar (>= version 2) hex} {uint16 usMaxContext (>= version 2)} {uint16 usLowerOpticalPointSize (>= version 5)} {uint16 usUpperOpticalPointSize (>= version 5)} #:tag "OS/2") (mkcmplx BaseGlyph {uint16 glyphID} {uint16 firstLayerIndex} {uint16 numLayers}) (mkcmplx Layer {uint16 glyphID} {uint16 paletteIndex}) (mkcmplx TableCOLR {uint16 version (== 0)} ; FIXME v1 has more stuff {uint16 numBaseGlyphRecords} {Offset32 baseGlyphRecordsOffset} {Offset32 layerRecordsOffset} {uint16 numLayerRecords} {BaseGlyph baseGlyphs [numBaseGlyphRecords] (at baseGlyphRecordsOffset)} {Layer layers [numLayerRecords] (at layerRecordsOffset)} #:tag "COLR") (mkcmplx ColorRecord {uint8 blue} {uint8 greed} {uint8 red} {uint8 alpha}) (mkcmplx TableCPAL {uint16 version (== 0)} ; FIXME v1 has more stuff {uint16 numPaletteEntries} {uint16 numPalettes} {uint16 numColorRecords} {Offset32 colorRecordsArrayOffset} {uint16 colorRecordIndices [numPalettes]} {ColorRecord colorRecords [numColorRecords] (at colorRecordsArrayOffset)} #:tag "CPAL") (mkcmplx TableRecord {Tag tableTag} {uint32 checksum unused hex} {Offset32 offset} {uint32 length} #:extra (list (cons 'field (list (~a "void *parsed;") (~a "void (*print)(Otfile *f, int indent, Otf *o, void *parsed);"))) (cons 'print (list (~a "if(v->print != nil && v->parsed != nil)") (~a " v->print(f, indent+indentΔ, o, v->parsed);"))))) (define (tagged-tables-fields tagged) (define (ptr c) (c-friendly-name (cmplx-tag c) #:downcase #t)) (define (case-statement c) (define tag (cmplx-tag c)) (define (ft t i) (~a "'" (string-ref t i) "'" (if (< i 3) (~a "<<" (* 8 (- 3 i))) ""))) (define case-tag (~a "(u32int)(" (string-join (map (λ (i) (ft tag i)) (range 4)) "|") ")")) (define after (cmplx-after c)) (define if-ready (string-join (map (λ (ac) (~a "v->" (ptr ac) " == nil")) after) " || ")) (list (~a "case " case-tag ":") (indent (if (empty? after) empty (list (~a "{") (~a " static int retried = 0;") (~a " if(" if-ready "){") (~a " if(retried){") (~a " werrstr(\"%s: deps missing\", \"" (cmplx-name c) "\");") (~a " goto err;") (~a " }") (~a " retried = 1;") (~a " retry++;") (~a " break;") (~a " }") (~a " if(retried)") (~a " retry--;") (~a "}")))) (~a " if(v->" (ptr c) " != nil)") ; don't reparse the same table (~a " break;") (~a " v->" (ptr c) " = calloc(1, sizeof(" (cmplx-name c) "));") (~a " if(read_" (cmplx-name c) "(o, v->" (ptr c) ") < 0){") (~a " free(v->" (ptr c) ");") (~a " v->" (ptr c) " = nil;") (~a " " (if (cmplx-optional c) "break;" "goto err;")) (~a " }") (~a " rec->parsed = v->" (ptr c) ";") (~a " rec->print = (void*)print_" (cmplx-name c) ";") (~a " break;"))) (list (cons 'field (map (λ (c) (~a (cmplx-name c) " *" (ptr c) ";")) tagged)) (cons 'read (list (~a "int retry = 0;") (~a "do{") (~a " for(int i = 0; i < v->numTables; i++){") (~a " TableRecord *rec = &v->tableRecords[i];") (~a " if(rec->length == 0)") ; skip all empty tables (~a " continue;") (~a " if(otfpushrange(o, rec->offset, rec->length) < 0)") (~a " goto err;") (~a " switch(rec->tableTag){") (indent (indent (map case-statement tagged))) (~a " default:") (~a " // FIXME fprint(2, \"no parser for \\\"%t\\\"\\n\", rec->tableTag);") (~a " break;") (~a " }") (~a " if(otfpoprange(o) < 0)") (~a " goto err;") (~a " }") (~a "}while(retry > 0);"))))) (mkcmplx TableDirectory {uint32 sfntVersion (== #x00010000 #x4f54544f) hex} {uint16 numTables} {uint16 searchRange} {uint16 entrySelector} {uint16 rangeShift} {TableRecord tableRecords [numTables]} #:extra (tagged-tables-fields tagged))