diff --git a/pitfall/fontkit/font.rkt b/pitfall/fontkit/font.rkt index 53a3b16e..802aaa88 100644 --- a/pitfall/fontkit/font.rkt +++ b/pitfall/fontkit/font.rkt @@ -35,9 +35,9 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (define table-decoder (hash-ref table-decoders table-tag (λ () (raise-argument-error '_decodeTable "decodable table" table-tag)))) (define offset (· (hash-ref (· directory tables) table-tag) offset)) - (define length (· (hash-ref (· directory tables) table-tag) length)) - (set-port-position! stream offset) - (send table-decoder decode (make-object RDecodeStream stream) this length)) + (define len (· (hash-ref (· directory tables) table-tag) length)) + (set-port-position! stream 0) + (send table-decoder decode (make-object RDecodeStream (peek-bytes len offset stream)) this length)) (define/public (_decodeDirectory) (set! directory (directory-decode stream (mhash '_startOffset 0))) diff --git a/pitfall/fontkit/loca.rkt b/pitfall/fontkit/loca.rkt index fb5c02c2..54651f2c 100644 --- a/pitfall/fontkit/loca.rkt +++ b/pitfall/fontkit/loca.rkt @@ -2,7 +2,9 @@ (require restructure) (provide (all-defined-out)) -(define short-style 0) +(define 16bit-style 0) +(define 32bit-style 1) +(define max-32-bit-value #xffff) #| approximates @@ -13,10 +15,24 @@ https://github.com/mbutterick/fontkit/blob/master/src/tables/loca.js (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) + (when (= 16bit-style (· res version)) + ;; in a 16bits-style loca table, actual 32bit 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)))))) + (hash-update! res 'offsets (λ (offsets) (map (curry * 2) offsets))))) + + (define/override (preEncode this-val stream) + ;; this = val to be encoded + (loca-preEncode this-val stream))) + +;; make "static method" +(define (loca-preEncode this-val . args) + ;; this = val to be encoded + (unless (hash-has-key? this-val 'version) + (hash-set! this-val 'version (if (> (last (· this-val offsets)) max-32-bit-value) + 32bit-style + 16bit-style)) + (when (= 16bit-style (· this-val version)) + (hash-update! this-val 'offsets (λ (offsets) (map (curryr / 2) offsets)))))) (define loca (make-object Rloca (λ (parent) (hash-ref (send parent _getTable 'head) 'indexToLocFormat)) diff --git a/pitfall/fontkit/subset.rkt b/pitfall/fontkit/subset.rkt index 0848f905..2df6b7cd 100644 --- a/pitfall/fontkit/subset.rkt +++ b/pitfall/fontkit/subset.rkt @@ -1,5 +1,5 @@ #lang fontkit/racket -(require "clone.rkt" "ttfglyphencoder.rkt") +(require "clone.rkt" "ttfglyphencoder.rkt" "loca.rkt") (provide Subset CFFSubset TTFSubset) #| @@ -70,20 +70,20 @@ https://github.com/mbutterick/fontkit/blob/master/src/subset/TTFSubset.js (send this _addGlyph gid)) (define maxp (cloneDeep (send (· this font) _getTable 'maxp))) - (hash-set! maxp 'numGlyphs (length (· this glyf))) ; todo + (hash-set! maxp 'numGlyphs (length (· this glyf))) - ;; todo - (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); + ;; populate the new loca table + (hash-update! (· this loca) 'offsets (λ (vals) (append vals (list (· this offset))))) + (loca-preEncode (· this loca)) - #;(define head (cloneDeep (send (· this font) _getTable 'head))) - ;; head.indexToLocFormat = this.loca.version; ; todo - - #;(define hhea (cloneDeep (send (· this font) _getTable 'hhea))) - ;; hhea.numberOfMetrics = this.hmtx.metrics.length; + (define head (cloneDeep (send (· this font) _getTable 'head))) + (hash-set! head 'indexToLocFormat (· this loca version)) + + (define hhea (cloneDeep (send (· this font) _getTable 'hhea))) + (hash-set! hhea 'numberOfMetrics (length (· this hmtx metrics))) + ;; todo: final encoding of directory, with all tables. + (unfinished) ) diff --git a/pitfall/restructure/array.rkt b/pitfall/restructure/array.rkt index 41595e1e..fd1117ec 100644 --- a/pitfall/restructure/array.rkt +++ b/pitfall/restructure/array.rkt @@ -10,10 +10,16 @@ https://github.com/mbutterick/restructure/blob/master/src/Array.coffee (define-subclass RStreamcoder (RArray type [length #f] [lengthType 'count]) (define/augment (decode stream [parent #f]) - (let ([length (if length - (resolveLength length stream parent) + (let ([length (cond + [length + (resolveLength length stream parent)] + [else + (define num (send stream length)) + (define denom (send type size)) + (unless (andmap (λ (x) (and x (number? x))) (list num denom)) + (raise-argument-error 'RArray:decode "valid length and size" (list num denom))) ;; implied length: length of stream divided by size of item - (report* (send stream length) (send type size) (floor (/ (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 83aff5ad..d50a3385 100644 --- a/pitfall/restructure/decodestream.rkt +++ b/pitfall/restructure/decodestream.rkt @@ -27,14 +27,13 @@ https://github.com/mbutterick/restructure/blob/master/src/DecodeStream.coffee (values (string->symbol (format "~a~a" key endian)) value)))) ;; basically just a wrapper for a Racket port -(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)])]) +;; but needs to start with a buffer so length can be found +(define-subclass object% (RDecodeStream [buffer #""]) + (field [_port (if (bytes? buffer) + (open-input-bytes buffer) + (raise-argument-error 'RDecodeStream "bytes" buffer))]) (getter-field [pos (port-position _port)]) - (getter-field [length (and (bytes? buffer-in) (bytes-length buffer-in))]) + (getter-field [length (bytes-length buffer)]) (define/public (read count) (read-bytes-exact count _port))) \ No newline at end of file diff --git a/pitfall/restructure/helper.rkt b/pitfall/restructure/helper.rkt index 99098b58..291e88e1 100644 --- a/pitfall/restructure/helper.rkt +++ b/pitfall/restructure/helper.rkt @@ -9,6 +9,8 @@ (abstract encode) (define/public (process . args) (void)) + (define/public (preEncode . args) + (void)) #;(abstract size))) diff --git a/pitfall/restructure/streamcoder.rkt b/pitfall/restructure/streamcoder.rkt index 8d0e8c3b..eab72303 100644 --- a/pitfall/restructure/streamcoder.rkt +++ b/pitfall/restructure/streamcoder.rkt @@ -8,7 +8,6 @@ (let loop ([x x]) (cond [(bytes? x) (loop (open-input-bytes x))] - [(input-port? x) (loop (make-object RDecodeStream x))] [(is-a? x RDecodeStream) (inner (void) decode x . args)] [else (raise-argument-error 'decode "item that can become RDecodeStream" x)]))) diff --git a/pitfall/restructure/struct.rkt b/pitfall/restructure/struct.rkt index 3db94a1e..6f96a5f8 100644 --- a/pitfall/restructure/struct.rkt +++ b/pitfall/restructure/struct.rkt @@ -13,7 +13,7 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee (for ([(k v) (in-dict assocs)]) (hash-set! fields k v)) - (define/public (make-key-index! [fields assocs]) + (define/public-final (make-key-index! [fields assocs]) (set! key-index (map car fields))) (make-key-index!) @@ -25,6 +25,7 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee res) (define/override (encode stream val [parent #f]) + (send this preEncode val stream) (for ([key (in-list key-index)]) (send (hash-ref fields key) encode stream (hash-ref val key)))) diff --git a/pitfall/restructure/versioned-struct.rkt b/pitfall/restructure/versioned-struct.rkt index 7c091ab0..6bd27d20 100644 --- a/pitfall/restructure/versioned-struct.rkt +++ b/pitfall/restructure/versioned-struct.rkt @@ -1,4 +1,4 @@ -#lang restructure/racket + #lang restructure/racket (require racket/dict "struct.rkt") (provide (all-defined-out)) @@ -8,11 +8,10 @@ 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] #:version [maybe-version #f]) (define res (send this _setup stream parent length)) (define version (cond - [maybe-version] + [maybe-version] ; for testing purposes: pass an explicit version [(procedure? type) (type parent)] [(is-a? type RBase) (send type decode stream)] [else (raise-argument-error 'decode "way of finding version" type)])) @@ -24,6 +23,4 @@ https://github.com/mbutterick/restructure/blob/master/src/VersionedStruct.coffee [else (send this _parseFields stream res fields) (send this process res stream) - res])) - - ) \ No newline at end of file + res]))) \ No newline at end of file