ref: b53bbd5a75d2682dc6606269714bec8f8d9d9796
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)))
(define ufmt (if (plan9?) "%ud" "%u"))
(mktype String 8 char "%s")
(mktype String-UTF16 8 char "%s")
(mktype uint8 8 u8int ufmt)
(mktype int8 8 s8int "%d")
(mktype uint16 16 u16int ufmt)
(mktype int16 16 s16int "%d")
(mktype uint24 24 u32int ufmt)
(mktype uint32 32 u32int ufmt)
(mktype int32 32 s32int "%d")
(mktype FWORD 16 s16int "%d")
(mktype UFWORD 16 u16int ufmt)
(mktype LONGDATETIME
64
s64int
(cons (if (plan9?) "%τ" "%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 ufmt)
(mktype Offset24 24 u32int ufmt)
(mktype Offset32 32 u32int ufmt)
(mktype Version16Dot16 32 u32int (cons "%d.%d" (λ (v) (~a v ">>16, " v "&0xffff"))))
(mktype Fixed
32
float
"%g"
(λ (b index [offset #f]) (~a "(" ((type-parse int32) b index offset) ")/65536.0f")))
(mktype F2DOT14
16
float
"%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 [?]})
; FIXME
(mkcmplx SubtableCmap4
{uint16 length}
{uint16 language}
{uint16 segCountX2}
{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 [?]})
(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]})
; FIXME
(mkcmplx SubtableCmap10
{uint16 reserved}
{uint32 length}
{uint32 language}
{uint32 startCharCode}
{uint32 numChars}
#;{uint16 glyphIdArray [?]})
(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")
(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
Glyf
{int16 numberOfContours ->o}
{int16 xMin}
{int16 yMin}
{int16 xMax}
{int16 yMax}
#:extra
(list (cons 'field (list (~a "ComponentGlyph *component;") (~a "SimpleGlyph *simple;")))
(cons 'read
(list (~a "if(v->numberOfContours < 0 && read_ComponentGlyph(o, &v->component, 0) < 0)")
(~a " goto err;")
(~a "if(v->numberOfContours > 0 && read_SimpleGlyph(o, &v->simple) < 0)")
(~a " goto err;")))
(cons 'print
(list (~a "if(v->component != nil){")
(~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"component\");")
(~a " print_ComponentGlyph(f, indent+indentΔ, o, v->component);")
(~a "}else if(v->simple != nil){")
(~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}
{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 Lookup
{uint16 lookupType}
{uint16 lookupFlag}
{uint16 subTableCount}
{Offset16 subtableOffsets [subTableCount]}
{uint16 markFilteringSet})
(mkcmplx LookupList {uint16 lookupCount} {Offset16 lookupOffsets [lookupCount]})
(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 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)})
(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 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 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]})
(mkcmplx KernSubtable
{uint16 version (== 0) unused}
{uint16 length (>= 6)} ; including this header
{uint16 coverage hex}) ; FIXME the rest depends on the coverage bits (8-15 = 0 or 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))
(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)}) ; FIXME offsets array
(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 DesignAxes
{AxisRecord designAxes [o->designAxisCount]}
{Offset16 axisValueOffsets [o->axisValueCount]}) ; FIXME array of offsets
(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}
{uint16 elidedFallbackNameID (> minorVersion 0)}
{DesignAxes designAxes (at designAxesOffset)}
#:tag "STAT")
(mkcmplx GaspRange {uint16 rangeMaxPPEM} {uint16 rangeGaspBehavior hex})
(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}
{Tuple intermediateStartTuple}
{Tuple intermediateEndTuple})
(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->axisCount)} ; FIXME
{uint16 sharedTupleCount}
{Offset32 sharedTuplesOffset}
{uint16 glyphCount #;(== o->glyphCount)} ; FIXME
{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)}
{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 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 " 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))