From 4d6399fac5b47be9231e3be927c707810c83c778 Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Sun, 19 May 2019 10:36:01 -0700 Subject: [PATCH] add hfs-seconds type --- fontland/fontland/table/head.rkt | 108 +++++++++++++++++-------------- 1 file changed, 60 insertions(+), 48 deletions(-) diff --git a/fontland/fontland/table/head.rkt b/fontland/fontland/table/head.rkt index e63634d5..f41df717 100644 --- a/fontland/fontland/table/head.rkt +++ b/fontland/fontland/table/head.rkt @@ -1,5 +1,6 @@ -#lang racket/base -(require xenomorph) +#lang debug racket/base +(require xenomorph + racket/date) (provide head) #| @@ -7,53 +8,64 @@ approximates https://github.com/mbutterick/fontkit/blob/master/src/tables/head.js |# +; `name` table dates are seconds since 1/1/1904 (Mac file convention) +; whereas Racket / posix tracks since 1/1/1970 +; so we adjust with the difference in seconds +(define mac-to-posix-delta 2082844800) + +(define hfs-seconds (x:int #:size 8 + #:signed #f + #:endian 'be + #:post-decode (λ (int) (seconds->date (- int mac-to-posix-delta))) + #:pre-encode (λ (dt) (+ (date->seconds dt) mac-to-posix-delta)))) + (define head (x:struct - 'version int32be ;; 0x00010000 (version 1.0) - 'revision int32be ;; set by font manufacturer - 'checkSumAdjustment uint32be - 'magicNumber uint32be ;; set to 0x5F0F3CF5 - 'flags uint16be - 'unitsPerEm uint16be ;; range from 64 to 16384 - 'created (x:array #:type int32be #:length 2) - 'modified (x:array #:type int32be #:length 2) - 'xMin int16be ;; for all glyph bounding boxes - 'yMin int16be ;; for all glyph bounding boxes - 'xMax int16be ;; for all glyph bounding boxes - 'yMax int16be ;; for all glyph bounding boxes - 'macStyle (x:bitfield #:type uint16be - #:flags '(bold italic underline outline shadow condensed extended)) - 'lowestRecPPEM uint16be ;; smallest readable size in pixels - 'fontDirectionHint int16be - 'indexToLocFormat int16be ;; 0 for short offsets 1 for long - 'glyphDataFormat int16be ;; 0 for current format - )) + 'version int32be ;; 0x00010000 (version 1.0) + 'revision int32be ;; set by font manufacturer + 'checkSumAdjustment uint32be + 'magicNumber uint32be ;; set to 0x5F0F3CF5 + 'flags uint16be + 'unitsPerEm uint16be ;; range from 64 to 16384 + 'created hfs-seconds + 'modified hfs-seconds + 'xMin int16be ;; for all glyph bounding boxes + 'yMin int16be ;; for all glyph bounding boxes + 'xMax int16be ;; for all glyph bounding boxes + 'yMax int16be ;; for all glyph bounding boxes + 'macStyle (x:bitfield #:type uint16be + #:flags '(bold italic underline outline shadow condensed extended)) + 'lowestRecPPEM uint16be ;; smallest readable size in pixels + 'fontDirectionHint int16be + 'indexToLocFormat int16be ;; 0 for short offsets 1 for long + 'glyphDataFormat int16be ;; 0 for current format + )) (module+ test - (require rackunit "../helper.rkt" - racket/serialize) - (define ip (open-input-file charter-italic-path)) - (define dir (deserialize (read (open-input-file charter-italic-directory-path)))) - (define offset (hash-ref (hash-ref (hash-ref dir 'tables) 'head) 'offset)) - (define length (hash-ref (hash-ref (hash-ref dir 'tables) 'head) 'length)) - (check-equal? offset 236) - (check-equal? length 54) - (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") - (file-position ip 0) - (check-equal? (peek-bytes length offset ip) table-bytes) - (define table-data (decode head table-bytes)) - (check-equal? (hash-ref table-data 'unitsPerEm) 1000) - (check-equal? (hash-ref table-data 'yMin) -236) - (check-equal? (hash-ref table-data 'yMax) 980) - (check-equal? (hash-ref table-data 'xMax) 1174) - (check-equal? (hash-ref table-data 'xMin) -226) - (check-equal? (hash-ref table-data 'macStyle) (make-hash '((shadow . #f) - (extended . #f) - (condensed . #f) - (underline . #f) - (outline . #f) - (bold . #f) - (italic . #t)))) - (check-equal? (hash-ref table-data 'magicNumber) #x5F0F3CF5) - (check-equal? (hash-ref table-data 'indexToLocFormat) 0) ; used in loca table - (check-equal? (encode head table-data #f) table-bytes)) \ No newline at end of file + (require rackunit "../helper.rkt" + racket/serialize) + (define ip (open-input-file charter-italic-path)) + (define dir (deserialize (read (open-input-file charter-italic-directory-path)))) + (define offset (hash-ref (hash-ref (hash-ref dir 'tables) 'head) 'offset)) + (define length (hash-ref (hash-ref (hash-ref dir 'tables) 'head) 'length)) + (check-equal? offset 236) + (check-equal? length 54) + (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") + (file-position ip 0) + (check-equal? (peek-bytes length offset ip) table-bytes) + (define table-data (decode head table-bytes)) + (check-equal? (hash-ref table-data 'unitsPerEm) 1000) + (check-equal? (hash-ref table-data 'yMin) -236) + (check-equal? (hash-ref table-data 'yMax) 980) + (check-equal? (hash-ref table-data 'xMax) 1174) + (check-equal? (hash-ref table-data 'xMin) -226) + (check-equal? (hash-ref table-data 'macStyle) (make-hash '((shadow . #f) + (extended . #f) + (condensed . #f) + (underline . #f) + (outline . #f) + (bold . #f) + (italic . #t)))) + (check-equal? (hash-ref table-data 'magicNumber) #x5F0F3CF5) + (check-equal? (hash-ref table-data 'indexToLocFormat) 0) ; used in loca table + (check-equal? (encode head table-data #f) table-bytes)) \ No newline at end of file