diff --git a/pitfall/fontkit/directory.rkt b/pitfall/fontkit/directory.rkt index 19b7e1c0..cc85b418 100644 --- a/pitfall/fontkit/directory.rkt +++ b/pitfall/fontkit/directory.rkt @@ -15,6 +15,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/tables/directory.js (define-subclass RStruct (RDirectory) (define/override (process res stream) + ;; in `restructure` `process` method, `res` is aliased as `this` (define new-tables-val (mhash)) (for ([table (in-list (· res tables))]) (hash-set! new-tables-val (string->symbol (· table tag)) table)) @@ -29,7 +30,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/tables/directory.js 'tables (make-object RArray TableEntry 'numTables)))) (define (directory-decode ip [options (mhash)]) - (define is (make-object RDecodeStream ip)) + (define is (make-object RDecodeStream (port->bytes ip))) (send Directory decode is)) diff --git a/pitfall/fontkit/head.rkt b/pitfall/fontkit/head.rkt index 9af73b5d..8e46e09c 100644 --- a/pitfall/fontkit/head.rkt +++ b/pitfall/fontkit/head.rkt @@ -32,27 +32,29 @@ https://github.com/mbutterick/fontkit/blob/master/src/tables/head.js (test-module (require "directory.rkt") - (define ip (open-input-file charter-path)) + (define ip (open-input-file charter-italic-path)) ; use italic to make sure style flags are set correctly (define dir (directory-decode ip)) (define offset (· dir tables head offset)) (define length (· dir tables head length)) (check-equal? offset 236) (check-equal? length 54) - (define table-bytes #"\0\1\0\0\0\2\0\0@\247\22 _\17<\365\0\t\3\350\0\0\0\0\316\3\301?\0\0\0\0\316\3\304\363\377_\377\24\4\251\3\303\0\0\0\t\0\2\0\0\0\0") + (define table-bytes #"\0\1\0\0\0\2\0\0.\252t<_\17<\365\0\t\3\350\0\0\0\0\316\3\301\261\0\0\0\0\316\3\304\364\377\36\377\24\4\226\3\324\0\2\0\t\0\2\0\0\0\0") (set-port-position! ip 0) (check-equal? (peek-bytes length offset ip) table-bytes) (define table-data (send head decode (make-object RDecodeStream table-bytes))) (check-equal? (· table-data unitsPerEm) 1000) (check-equal? (· table-data yMin) -236) - (check-equal? (· table-data yMax) 963) - (check-equal? (· table-data xMax) 1193) - (check-equal? (· table-data xMin) -161) + (check-equal? (· table-data yMax) 980) + (check-equal? (· table-data xMax) 1174) + (check-equal? (· table-data xMin) -226) (check-equal? (· table-data macStyle) (make-hash '((shadow . #f) (extended . #f) (condensed . #f) (underline . #f) (outline . #f) (bold . #f) - (italic . #f)))) - (check-equal? (· table-data magicNumber) #x5F0F3CF5)) + (italic . #t)))) + (check-equal? (· table-data magicNumber) #x5F0F3CF5) + (check-equal? (· table-data indexToLocFormat) 0) ; used in loca table + ) diff --git a/pitfall/fontkit/helper.rkt b/pitfall/fontkit/helper.rkt index 176f6716..a20f7701 100644 --- a/pitfall/fontkit/helper.rkt +++ b/pitfall/fontkit/helper.rkt @@ -4,7 +4,8 @@ (define index? (λ (x) (and (number? x) (integer? x) (not (negative? x))))) -(define-runtime-path charter-path "../pitfall/test/assets/Charter.ttf") +(define-runtime-path charter-path "../pitfall/test/assets/charter.ttf") +(define-runtime-path charter-italic-path "../pitfall/test/assets/charter-italic.ttf") (define-macro (test-module . EXPRS) #`(module+ test diff --git a/pitfall/fontkit/loca.rkt b/pitfall/fontkit/loca.rkt index 9894b70d..fb5c02c2 100644 --- a/pitfall/fontkit/loca.rkt +++ b/pitfall/fontkit/loca.rkt @@ -2,20 +2,269 @@ (require restructure) (provide (all-defined-out)) +(define short-style 0) + #| approximates https://github.com/mbutterick/fontkit/blob/master/src/tables/loca.js |# -(define-subclass RVersionedStruct (Rloca)) +(define-subclass RVersionedStruct (Rloca) + (define/override (process res stream) + ;; in `restructure` `process` method, `res` is aliased as `this` + ;; + (when (= short-style (· res version)) + ;; in a short-style loca table, actual offset values are divided by 2 (to fit into 16 bits) + ;; so we re-inflate them. + (hash-update! res 'offsets (λ (offsets) (map (curry * 2) offsets)))))) (define loca (make-object Rloca - (λ (this) (hash-ref (send this _getTable 'head) 'indexToLocFormat)) + (λ (parent) (hash-ref (send parent _getTable 'head) 'indexToLocFormat)) (dictify - - + 0 (dictify 'offsets (make-object RArray uint16be)) + 1 (dictify 'offsets (make-object RArray uint32be)) ))) (test-module - ) + (require "directory.rkt") + (define ip (open-input-file charter-path)) + (define dir (directory-decode ip)) + (define offset (· dir tables loca offset)) + (define len (· dir tables loca length)) + (check-equal? offset 38692) + (check-equal? len 460) + (set-port-position! ip 0) + (define ds (make-object RDecodeStream (peek-bytes len offset ip))) + (define table-data (send loca decode ds #:version 0)) + (check-equal? (length (· table-data offsets)) 230) + (check-equal? (· table-data offsets) '(0 + 0 + 0 + 136 + 296 + 500 + 864 + 1168 + 1548 + 1628 + 1716 + 1804 + 1944 + 2048 + 2128 + 2176 + 2256 + 2312 + 2500 + 2596 + 2788 + 3052 + 3168 + 3396 + 3624 + 3732 + 4056 + 4268 + 4424 + 4564 + 4640 + 4728 + 4804 + 5012 + 5384 + 5532 + 5808 + 6012 + 6212 + 6456 + 6672 + 6916 + 7204 + 7336 + 7496 + 7740 + 7892 + 8180 + 8432 + 8648 + 8892 + 9160 + 9496 + 9764 + 9936 + 10160 + 10312 + 10536 + 10780 + 10992 + 11148 + 11216 + 11272 + 11340 + 11404 + 11444 + 11524 + 11820 + 12044 + 12216 + 12488 + 12728 + 12932 + 13324 + 13584 + 13748 + 13924 + 14128 + 14232 + 14592 + 14852 + 15044 + 15336 + 15588 + 15776 + 16020 + 16164 + 16368 + 16520 + 16744 + 16984 + 17164 + 17320 + 17532 + 17576 + 17788 + 17896 + 18036 + 18284 + 18552 + 18616 + 18988 + 19228 + 19512 + 19712 + 19796 + 19976 + 20096 + 20160 + 20224 + 20536 + 20836 + 20876 + 21000 + 21200 + 21268 + 21368 + 21452 + 21532 + 21720 + 21908 + 22036 + 22244 + 22664 + 22872 + 22932 + 22992 + 23088 + 23220 + 23268 + 23372 + 23440 + 23600 + 23752 + 23868 + 23988 + 24084 + 24184 + 24224 + 24548 + 24788 + 25012 + 25292 + 25716 + 25884 + 26292 + 26396 + 26540 + 26796 + 27172 + 27488 + 27512 + 27536 + 27560 + 27584 + 27912 + 27936 + 27960 + 27984 + 28008 + 28032 + 28056 + 28080 + 28104 + 28128 + 28152 + 28176 + 28200 + 28224 + 28248 + 28272 + 28296 + 28320 + 28344 + 28368 + 28392 + 28416 + 28440 + 28464 + 28488 + 28512 + 28536 + 28560 + 28968 + 28992 + 29016 + 29040 + 29064 + 29088 + 29112 + 29136 + 29160 + 29184 + 29208 + 29232 + 29256 + 29280 + 29304 + 29328 + 29352 + 29376 + 29400 + 29424 + 29448 + 29472 + 29496 + 29520 + 29824 + 30164 + 30220 + 30652 + 30700 + 30956 + 31224 + 31248 + 31332 + 31488 + 31636 + 31916 + 32104 + 32176 + 32484 + 32744 + 32832 + 32956 + 33248 + 33664 + 33884 + 34048 + 34072))) diff --git a/pitfall/fontkit/subset.rkt b/pitfall/fontkit/subset.rkt index f809e145..0848f905 100644 --- a/pitfall/fontkit/subset.rkt +++ b/pitfall/fontkit/subset.rkt @@ -73,13 +73,15 @@ https://github.com/mbutterick/fontkit/blob/master/src/subset/TTFSubset.js (hash-set! maxp 'numGlyphs (length (· this glyf))) ; todo ;; todo - (hash-update! (send (· this font) _getTable 'loca) 'offsets (λ (val) (push-end! val (· this offset)))) + (report 'boing) + (report (send (· this font) _getTable 'loca) 'offsets) + #;(hash-update! (report (send (· this font) _getTable 'loca)) 'offsets (λ (val) (push-end! val (· this offset)))) ;; Tables.loca.preEncode.call(this.loca); - (define head (cloneDeep (send (· this font) _getTable 'head))) + #;(define head (cloneDeep (send (· this font) _getTable 'head))) ;; head.indexToLocFormat = this.loca.version; ; todo - (define hhea (cloneDeep (send (· this font) _getTable 'hhea))) + #;(define hhea (cloneDeep (send (· this font) _getTable 'hhea))) ;; hhea.numberOfMetrics = this.hmtx.metrics.length; (unfinished) diff --git a/pitfall/pitfall/test/assets/charter-italic.ttf b/pitfall/pitfall/test/assets/charter-italic.ttf new file mode 100644 index 00000000..a6501214 Binary files /dev/null and b/pitfall/pitfall/test/assets/charter-italic.ttf differ diff --git a/pitfall/restructure/array.rkt b/pitfall/restructure/array.rkt index 72e6ffcb..41595e1e 100644 --- a/pitfall/restructure/array.rkt +++ b/pitfall/restructure/array.rkt @@ -12,7 +12,8 @@ https://github.com/mbutterick/restructure/blob/master/src/Array.coffee (define/augment (decode stream [parent #f]) (let ([length (if length (resolveLength length stream parent) - (send stream length))]) + ;; implied length: length of stream divided by size of item + (report* (send stream length) (send type size) (floor (/ (send stream length) (send type size)))))]) (caseq lengthType [(count) (for/list ([i (in-range length)]) diff --git a/pitfall/restructure/decodestream.rkt b/pitfall/restructure/decodestream.rkt index 401e9a36..83aff5ad 100644 --- a/pitfall/restructure/decodestream.rkt +++ b/pitfall/restructure/decodestream.rkt @@ -1,7 +1,9 @@ #lang restructure/racket (provide (all-defined-out)) -;; approximates https://github.com/mbutterick/restructure/blob/master/src/DecodeStream.coffee +#| approximates +https://github.com/mbutterick/restructure/blob/master/src/DecodeStream.coffee +|# (define (read-bytes-exact count p) (define bs (read-bytes count p)) @@ -25,12 +27,14 @@ (values (string->symbol (format "~a~a" key endian)) value)))) ;; basically just a wrapper for a Racket port -(define-subclass object% (RDecodeStream [buffer-in #""]) +(define-subclass object% (RDecodeStream [buffer-in #f]) (field [_port (cond + [(not buffer-in) (open-input-bytes (bytes))] [(bytes? buffer-in) (open-input-bytes buffer-in)] [(input-port? buffer-in) buffer-in] [else (raise-argument-error 'RDecodeStream "bytes or input port" buffer-in)])]) (getter-field [pos (port-position _port)]) + (getter-field [length (and (bytes? buffer-in) (bytes-length buffer-in))]) (define/public (read count) (read-bytes-exact count _port))) \ No newline at end of file diff --git a/pitfall/restructure/struct.rkt b/pitfall/restructure/struct.rkt index e433dbe4..3db94a1e 100644 --- a/pitfall/restructure/struct.rkt +++ b/pitfall/restructure/struct.rkt @@ -7,12 +7,16 @@ approximates https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee |# -(define-subclass RBase (RStruct assocs) - (field [key-index (map car assocs)] +(define-subclass RBase (RStruct [assocs (dictify)]) + (field [key-index #f] [fields (mhash)]) (for ([(k v) (in-dict assocs)]) (hash-set! fields k v)) + (define/public (make-key-index! [fields assocs]) + (set! key-index (map car fields))) + (make-key-index!) + (define/override (decode stream [parent #f] [length 0]) (define res (_setup stream parent length)) (_parseFields stream res fields) @@ -24,7 +28,7 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee (for ([key (in-list key-index)]) (send (hash-ref fields key) encode stream (hash-ref val key)))) - (define/private (_setup stream parent length) + (define/public-final (_setup stream parent length) (define res (mhasheq)) ;; define hidden properties @@ -35,13 +39,13 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee '_length (mhasheq 'value length))) res) - (define/private (_parseFields stream res field) + (define/public-final (_parseFields stream res fields) (for ([key (in-list key-index)]) - (define hashvalue (hash-ref fields key)) + (define dictvalue (dict-ref fields key)) (define val - (if (procedure? hashvalue) - (hashvalue res) - (send hashvalue decode stream res))) + (if (procedure? dictvalue) + (dictvalue res) + (send dictvalue decode stream res))) (hash-set! res key val))) ) diff --git a/pitfall/restructure/versioned-struct.rkt b/pitfall/restructure/versioned-struct.rkt index c46e0cc7..7c091ab0 100644 --- a/pitfall/restructure/versioned-struct.rkt +++ b/pitfall/restructure/versioned-struct.rkt @@ -8,14 +8,22 @@ https://github.com/mbutterick/restructure/blob/master/src/VersionedStruct.coffee |# (define-subclass RStruct (RVersionedStruct type [versions (dictify)]) - - (define/override (decode stream [parent #f] [length 0]) + + (define/override (decode stream [parent #f] [length 0] #:version [maybe-version #f]) (define res (send this _setup stream parent length)) (define version (cond + [maybe-version] [(procedure? type) (type parent)] [(is-a? type RBase) (send type decode stream)] [else (raise-argument-error 'decode "way of finding version" type)])) - (report version 'yay) - #;(_parseFields stream res fields) - #;(send this process res stream) - res)) \ No newline at end of file + (hash-set! res 'version version) + (define fields (dict-ref versions version (λ () (raise-argument-error 'RVersionedStruct:decode "valid version key" version)))) + (send this make-key-index! fields) + (cond + [(is-a? fields RVersionedStruct) (send fields decode stream parent)] + [else + (send this _parseFields stream res fields) + (send this process res stream) + res])) + + ) \ No newline at end of file