From a028c6fd95da079ee05202ab8e304b2268fbb33a Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Wed, 21 Jun 2017 13:28:44 -0700 Subject: [PATCH] working on pointers --- pitfall/fontkit/GPOS-test.coffee | 222 +++++++++++++++++++++++++++++++ pitfall/fontkit/GPOS-test.rkt | 19 ++- pitfall/fontkit/GPOS.rkt | 11 +- pitfall/fontkit/font.rkt | 6 +- pitfall/fontkit/main.rkt | 3 +- pitfall/fontkit/opentype.rkt | 30 +++++ pitfall/fontkit/tables.rkt | 2 +- pitfall/restructure/array.rkt | 3 +- pitfall/restructure/main.rkt | 3 +- pitfall/restructure/pointer.rkt | 47 ++++--- 10 files changed, 318 insertions(+), 28 deletions(-) create mode 100644 pitfall/fontkit/GPOS-test.coffee diff --git a/pitfall/fontkit/GPOS-test.coffee b/pitfall/fontkit/GPOS-test.coffee new file mode 100644 index 00000000..28a5f91d --- /dev/null +++ b/pitfall/fontkit/GPOS-test.coffee @@ -0,0 +1,222 @@ +fontkit = require '../pdfkit/node_modules/fontkit' + +fira_path = "../pitfall/test/assets/fira.ttf" +f = fontkit.openSync(fira_path) +console.log(f.GPOS) + +### +{ version: 65536, + scriptList: + [ { tag: 'DFLT', script: [Object] }, + { tag: 'cyrl', script: [Object] }, + { tag: 'grek', script: [Object] }, + { tag: 'latn', script: [Object] } ], + featureList: + [ { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'cpsp', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'kern', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mark', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] }, + { tag: 'mkmk', feature: [Object] } ], + lookupList: + [ { lookupType: 1, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 1, + subTables: [ [Object] ], + markFilteringSet: 2 }, + { lookupType: 2, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 6, + subTables: [ [Object], [Object], [Object], [Object], [Object], [Object] ], + markFilteringSet: 2 }, + { lookupType: 2, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 7, + subTables: + [ [Object], + [Object], + [Object], + [Object], + [Object], + [Object], + [Object] ], + markFilteringSet: 2 }, + { lookupType: 2, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 6, + subTables: [ [Object], [Object], [Object], [Object], [Object], [Object] ], + markFilteringSet: 2 }, + { lookupType: 2, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 2, + subTables: [ [Object], [Object] ], + markFilteringSet: 4 }, + { lookupType: 4, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 1, + subTables: [ [Object] ], + markFilteringSet: 4 }, + { lookupType: 4, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 1, + subTables: [ [Object] ], + markFilteringSet: 4 }, + { lookupType: 4, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 1, + subTables: [ [Object] ], + markFilteringSet: 6 }, + { lookupType: 6, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 1, + subTables: [ [Object] ], + markFilteringSet: 6 }, + { lookupType: 6, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 1, + subTables: [ [Object] ], + markFilteringSet: 6 }, + { lookupType: 6, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 1, + subTables: [ [Object] ], + markFilteringSet: 6 }, + { lookupType: 6, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 1, + subTables: [ [Object] ], + markFilteringSet: 6 }, + { lookupType: 6, + flags: + { rightToLeft: false, + ignoreBaseGlyphs: false, + ignoreLigatures: false, + ignoreMarks: false, + useMarkFilteringSet: false, + markAttachmentType: false }, + subTableCount: 1, + subTables: [ [Object] ], + markFilteringSet: 1 } ] } +### \ No newline at end of file diff --git a/pitfall/fontkit/GPOS-test.rkt b/pitfall/fontkit/GPOS-test.rkt index a7ed5081..5dbff7a4 100644 --- a/pitfall/fontkit/GPOS-test.rkt +++ b/pitfall/fontkit/GPOS-test.rkt @@ -1,7 +1,22 @@ #lang fontkit/racket -(require "font.rkt" "directory.rkt" "gpos.rkt") +(require fontkit rackunit restructure) +(define fira-path "../pitfall/test/assets/fira.ttf") (define f (openSync fira-path)) (define ds (send f _getTableStream 'GPOS)) -(send GPOS decode ds) \ No newline at end of file +(file-position (· ds _port)) +(peek-bytes 4 0 (· ds _port)) ; version +(peek-bytes 2 4 (· ds _port)) ; scriptList pointer +(peek-bytes 2 10 (· ds _port)) ; number of Scriptrecords + +(send uint16be decode #"\0\n") + +(define h (send GPOS decode ds)) + + + +;(check-equal? (· h version) #x00010000) + +;h +;(check-equal? (length (· h scriptList)) 4) \ No newline at end of file diff --git a/pitfall/fontkit/GPOS.rkt b/pitfall/fontkit/GPOS.rkt index 5e24af49..f2bd152c 100644 --- a/pitfall/fontkit/GPOS.rkt +++ b/pitfall/fontkit/GPOS.rkt @@ -184,12 +184,15 @@ https://github.com/mbutterick/fontkit/blob/master/src/tables/GPOS.js ;; Fix circular reference ;; GPOSLookup.versions[9].extension.type = GPOSLookup; -(define gpos-common-dict (dictify 'scriptList uint16be ; pointer - 'featureList uint16be ; pointer - 'lookupList uint16be)) ; pointer +(define gpos-common-dict (dictify 'scriptList (+Pointer uint16be ScriptList) ; pointer + ;'featureList (+Pointer uint16be FeatureList) ; pointer + ;'lookupList (+Pointer uint16be (+LookupList GPOSLookup)) + )) ; pointer (define-subclass VersionedStruct (GPOS-VersionedStruct)) (define GPOS (+GPOS-VersionedStruct uint32be (dictify #x00010000 gpos-common-dict - #x00010001 (append gpos-common-dict (dictify 'featureVariations uint32be))))) ; pointer \ No newline at end of file + #x00010001 (append gpos-common-dict (dictify 'featureVariations uint32be))))) ; pointer + +(test-module) \ No newline at end of file diff --git a/pitfall/fontkit/font.rkt b/pitfall/fontkit/font.rkt index 8102c686..a2d04ee0 100644 --- a/pitfall/fontkit/font.rkt +++ b/pitfall/fontkit/font.rkt @@ -44,7 +44,11 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (define/public (_getTableStream tag) (define table (hash-ref (· this directory tables) tag)) - (and table (send stream pos (· table offset)) stream)) + (cond + [table + (send stream pos (· table offset)) + stream] + [else #f])) (define/public (_decodeTable table-tag) (define table-decoder (hash-ref table-codecs table-tag diff --git a/pitfall/fontkit/main.rkt b/pitfall/fontkit/main.rkt index f076aaaa..81aae8b7 100644 --- a/pitfall/fontkit/main.rkt +++ b/pitfall/fontkit/main.rkt @@ -3,4 +3,5 @@ (r+p "font.rkt" "glyph-position.rkt" "subset.rkt" - "bbox.rkt") \ No newline at end of file + "bbox.rkt" + "tables.rkt") \ No newline at end of file diff --git a/pitfall/fontkit/opentype.rkt b/pitfall/fontkit/opentype.rkt index aeaabe56..4d97a0f0 100644 --- a/pitfall/fontkit/opentype.rkt +++ b/pitfall/fontkit/opentype.rkt @@ -2,6 +2,36 @@ (require restructure) (provide (all-defined-out)) +;;######################## +;; Scripts and Languages # +;;######################## + +(define LangSysTable (+Struct + (dictify 'reserved uint16be + 'reqFeatureIndex uint16be + 'featureCount uint16be + 'featureIndexes (+Array uint16be 'featureCount)))) + +(define LangSysRecord (+Struct + (dictify 'tag (+String 4) + 'langSys (+Pointer uint16be LangSysTable (mhash 'type 'parent))))) + +(define Script (+Struct + (dictify 'defaultLangSys (+Pointer uint16be LangSysTable) + 'count uint16be + 'langSysRecords (+Array LangSysRecord 'count)))) + +(define-subclass Struct (ScriptRecord-Struct)) +(define ScriptRecord (+ScriptRecord-Struct + (dictify 'tag (+String 4) + 'script uint16be #;(+Pointer uint16be Script (mhash 'type 'parent))))) +(define-subclass Array (ScriptRecordArray) + (define/override (decode stream ctx) + (define val (super decode stream ctx)) + (report (· this _len)) + val)) +(define ScriptList (+ScriptRecordArray ScriptRecord uint16be)) + (define LookupRecord (+Struct (dictify 'sequenceIndex uint16be diff --git a/pitfall/fontkit/tables.rkt b/pitfall/fontkit/tables.rkt index 5a36cb1e..46cc4289 100644 --- a/pitfall/fontkit/tables.rkt +++ b/pitfall/fontkit/tables.rkt @@ -10,4 +10,4 @@ (test-module (require (submod TABLE-ID-STRING test) ...)) (define ID (make-hasheq (map cons (list 'TABLE-ID ...) (list TABLE-ID ...))))))) -(define-table-codecs table-codecs maxp hhea head loca prep fpgm hmtx cvt_ glyf OS/2 post) \ No newline at end of file +(define-table-codecs table-codecs maxp hhea head loca prep fpgm hmtx cvt_ glyf OS/2 post GPOS) \ No newline at end of file diff --git a/pitfall/restructure/array.rkt b/pitfall/restructure/array.rkt index 5c2a474c..20073dc9 100644 --- a/pitfall/restructure/array.rkt +++ b/pitfall/restructure/array.rkt @@ -8,6 +8,7 @@ https://github.com/mbutterick/restructure/blob/master/src/Array.coffee |# (define-subclass Streamcoder (Array type [_length #f] [lengthType 'count]) + (field [_len #f]) (define/augride (decode stream [parent #f]) (let ([len (cond @@ -19,7 +20,7 @@ https://github.com/mbutterick/restructure/blob/master/src/Array.coffee (unless (andmap (λ (x) (and x (number? x))) (list num denom)) (raise-argument-error 'Array:decode "valid length and size" (list num denom))) (floor (/ (send stream length) (send type size)))])]) - + (set! _len len) (caseq lengthType [(count) (for/list ([i (in-range len)]) (send type decode stream this))]))) diff --git a/pitfall/restructure/main.rkt b/pitfall/restructure/main.rkt index 6619c8c4..682daae9 100644 --- a/pitfall/restructure/main.rkt +++ b/pitfall/restructure/main.rkt @@ -7,4 +7,5 @@ "array.rkt" "bitfield.rkt" "stream.rkt" - "buffer.rkt") \ No newline at end of file + "buffer.rkt" + "pointer.rkt") \ No newline at end of file diff --git a/pitfall/restructure/pointer.rkt b/pitfall/restructure/pointer.rkt index 7462a742..ffcbb792 100644 --- a/pitfall/restructure/pointer.rkt +++ b/pitfall/restructure/pointer.rkt @@ -1,21 +1,34 @@ #lang restructure/racket +(provide (all-defined-out)) -(define pointer-ks (make-hash)) -(define results (make-hash)) +#| +approximates +https://github.com/mbutterick/restructure/blob/master/src/Pointer.coffee +|# -(define vals '(a b (h) d e f g h i j)) +(define-subclass RestructureBase (Pointer offsetType type [options (mhash)]) -(for ([(val i) (in-indexed vals)] - #:unless (hash-has-key? results val)) - (hash-set! results i (let/cc pointer-k - (cond - [(hash-ref pointer-ks val #f) => (λ (pk) - (hash-remove! pointer-ks val) - (pk (format "~a@~a" val i)))] - [(pair? val) (hash-set! pointer-ks (car val) pointer-k) 'tbd] - [else val])))) -(test-module - (check-equal? - (for/list ([i (in-range (length (hash-keys results)))]) - (hash-ref results i)) - '(a b "h@7" d e f g h i j))) \ No newline at end of file + (define/override (decode stream ctx) + (report (file-position (· stream _port))) + (define offset (send offsetType decode stream ctx)) + (define ptr offset) + (report* offset ptr) + (cond + [type (define orig-pos (send stream pos)) + (send stream pos ptr) + (define val (send type decode stream ctx)) + (send stream pos orig-pos) + (report* options) + val] + [else ptr])) + + + (define/override (encode stream val) + (error 'Pointer-encode-not-done)) + + (define/override (size val) + (error 'Pointer-size-not-done)) + + + + ) \ No newline at end of file