From fe237130812485c610d00e33750abf2c70a465bd Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Fri, 9 Jun 2017 16:25:40 -0700 Subject: [PATCH] resume in head table: bitfield --- pitfall/fontkit/bbox.rkt | 2 +- pitfall/fontkit/clone.rkt | 2 +- pitfall/fontkit/cmap-processor.rkt | 2 +- pitfall/fontkit/directory.rkt | 73 ++++++++++--------- pitfall/fontkit/font.rkt | 105 ++++++++++++++------------- pitfall/fontkit/glyph-position.rkt | 2 +- pitfall/fontkit/glyph.rkt | 2 +- pitfall/fontkit/glyphrun.rkt | 2 +- pitfall/fontkit/head.rkt | 52 +++++++++++++ pitfall/fontkit/helper.rkt | 12 +++ pitfall/fontkit/hhea.rkt | 39 ++++++++++ pitfall/fontkit/layout-engine.rkt | 2 +- pitfall/fontkit/main.rkt | 2 +- pitfall/fontkit/maxp.rkt | 39 ++++++++++ pitfall/fontkit/racket.rkt | 30 ++++++++ pitfall/fontkit/script.rkt | 2 +- pitfall/fontkit/subset.rkt | 22 +++++- pitfall/fontkit/tables.rkt | 11 +++ pitfall/fontkit/ttfglyphencoder.rkt | 2 +- pitfall/pitfall/helper.rkt | 2 +- pitfall/restructure/decodestream.rkt | 10 +-- pitfall/sugar/port.rkt | 21 +++++- 22 files changed, 325 insertions(+), 111 deletions(-) create mode 100644 pitfall/fontkit/head.rkt create mode 100644 pitfall/fontkit/helper.rkt create mode 100644 pitfall/fontkit/hhea.rkt create mode 100644 pitfall/fontkit/maxp.rkt create mode 100644 pitfall/fontkit/racket.rkt create mode 100644 pitfall/fontkit/tables.rkt diff --git a/pitfall/fontkit/bbox.rkt b/pitfall/fontkit/bbox.rkt index 2f040183..8ebde8a5 100644 --- a/pitfall/fontkit/bbox.rkt +++ b/pitfall/fontkit/bbox.rkt @@ -1,4 +1,4 @@ -#lang pitfall/racket +#lang fontkit/racket (provide BBox bbox->list) (define-subclass object% (BBox diff --git a/pitfall/fontkit/clone.rkt b/pitfall/fontkit/clone.rkt index 86152e6b..5a1fc990 100644 --- a/pitfall/fontkit/clone.rkt +++ b/pitfall/fontkit/clone.rkt @@ -1,4 +1,4 @@ -#lang racket +#lang fontkit/racket (provide cloneDeep) (define (cloneDeep val) diff --git a/pitfall/fontkit/cmap-processor.rkt b/pitfall/fontkit/cmap-processor.rkt index 49b99ba1..d56bbba6 100644 --- a/pitfall/fontkit/cmap-processor.rkt +++ b/pitfall/fontkit/cmap-processor.rkt @@ -1,4 +1,4 @@ -#lang pitfall/racket +#lang fontkit/racket (provide CmapProcessor) (define-subclass object% (CmapProcessor cmapTable) diff --git a/pitfall/fontkit/directory.rkt b/pitfall/fontkit/directory.rkt index dbf96d42..19b7e1c0 100644 --- a/pitfall/fontkit/directory.rkt +++ b/pitfall/fontkit/directory.rkt @@ -1,4 +1,4 @@ -#lang pitfall/racket +#lang fontkit/racket (require restructure) (provide (all-defined-out)) @@ -32,40 +32,41 @@ https://github.com/mbutterick/fontkit/blob/master/src/tables/directory.js (define is (make-object RDecodeStream ip)) (send Directory decode is)) -(module+ test - (require rackunit racket/serialize) - (define ip (open-input-file "test/assets/Charter.ttf")) - (check-equal? - (directory-decode ip) - (deserialize '((3) - 0 - () - 0 - () + +(test-module + (require racket/serialize) + (define ip (open-input-file charter-path)) + (check-equal? + (directory-decode ip) + (deserialize '((3) + 0 + () + 0 + () + () + (h + ! () - (h + (tag u . "\u0000\u0001\u0000\u0000") + (rangeShift . 96) + (searchRange . 128) + (numTables . 14) + (entrySelector . 3) + (tables + h ! - () - (tag u . "\u0000\u0001\u0000\u0000") - (rangeShift . 96) - (searchRange . 128) - (numTables . 14) - (entrySelector . 3) - (tables - h - ! - (equal) - (loca h ! () (tag u . "loca") (offset . 38692) (checkSum . 2795817194) (length . 460)) - (glyf h ! () (tag u . "glyf") (offset . 4620) (checkSum . 1143629849) (length . 34072)) - (OS/2 h ! () (tag u . "OS/2") (offset . 360) (checkSum . 2351070438) (length . 96)) - (hhea h ! () (tag u . "hhea") (offset . 292) (checkSum . 132056097) (length . 36)) - (post h ! () (tag u . "post") (offset . 41520) (checkSum . 1670855689) (length . 514)) - (|cvt | h ! () (tag u . "cvt ") (offset . 4592) (checkSum . 10290865) (length . 26)) - (VDMX h ! () (tag u . "VDMX") (offset . 1372) (checkSum . 1887795202) (length . 1504)) - (prep h ! () (tag u . "prep") (offset . 4512) (checkSum . 490862356) (length . 78)) - (maxp h ! () (tag u . "maxp") (offset . 328) (checkSum . 50135594) (length . 32)) - (hmtx h ! () (tag u . "hmtx") (offset . 456) (checkSum . 3982043058) (length . 916)) - (cmap h ! () (tag u . "cmap") (offset . 2876) (checkSum . 1723761408) (length . 1262)) - (name h ! () (tag u . "name") (offset . 39152) (checkSum . 2629707307) (length . 2367)) - (head h ! () (tag u . "head") (offset . 236) (checkSum . 4281190895) (length . 54)) - (fpgm h ! () (tag u . "fpgm") (offset . 4140) (checkSum . 106535991) (length . 371)))))))) \ No newline at end of file + (equal) + (loca h ! () (tag u . "loca") (offset . 38692) (checkSum . 2795817194) (length . 460)) + (glyf h ! () (tag u . "glyf") (offset . 4620) (checkSum . 1143629849) (length . 34072)) + (OS/2 h ! () (tag u . "OS/2") (offset . 360) (checkSum . 2351070438) (length . 96)) + (hhea h ! () (tag u . "hhea") (offset . 292) (checkSum . 132056097) (length . 36)) + (post h ! () (tag u . "post") (offset . 41520) (checkSum . 1670855689) (length . 514)) + (|cvt | h ! () (tag u . "cvt ") (offset . 4592) (checkSum . 10290865) (length . 26)) + (VDMX h ! () (tag u . "VDMX") (offset . 1372) (checkSum . 1887795202) (length . 1504)) + (prep h ! () (tag u . "prep") (offset . 4512) (checkSum . 490862356) (length . 78)) + (maxp h ! () (tag u . "maxp") (offset . 328) (checkSum . 50135594) (length . 32)) + (hmtx h ! () (tag u . "hmtx") (offset . 456) (checkSum . 3982043058) (length . 916)) + (cmap h ! () (tag u . "cmap") (offset . 2876) (checkSum . 1723761408) (length . 1262)) + (name h ! () (tag u . "name") (offset . 39152) (checkSum . 2629707307) (length . 2367)) + (head h ! () (tag u . "head") (offset . 236) (checkSum . 4281190895) (length . 54)) + (fpgm h ! () (tag u . "fpgm") (offset . 4140) (checkSum . 106535991) (length . 371)))))))) \ No newline at end of file diff --git a/pitfall/fontkit/font.rkt b/pitfall/fontkit/font.rkt index 5ca0b4eb..da1c91b7 100644 --- a/pitfall/fontkit/font.rkt +++ b/pitfall/fontkit/font.rkt @@ -1,5 +1,5 @@ -#lang pitfall/racket -(require "freetype-ffi.rkt" ffi/unsafe racket/runtime-path "subset.rkt" "glyph.rkt" "layout-engine.rkt" "bbox.rkt" "glyphrun.rkt" "cmap-processor.rkt" "directory.rkt") +#lang fontkit/racket +(require "freetype-ffi.rkt" ffi/unsafe racket/runtime-path "subset.rkt" "glyph.rkt" "layout-engine.rkt" "bbox.rkt" "glyphrun.rkt" "cmap-processor.rkt" "directory.rkt" restructure/decodestream "tables.rkt") (provide (all-defined-out)) (define-runtime-path charter-path "../pitfall/test/assets/charter.ttf") @@ -14,13 +14,12 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (define-subclass object% (TTFFont stream) (when stream (unless (input-port? stream) (raise-argument-error 'TTFFont "input port" stream))) - (unless (member (bytes->string/latin-1 (peek-bytes 4 0 stream)) - (list "true" "OTTO" "\u0\u1\u0\u0")) + (unless (member (peek-bytes 4 0 stream) (list #"true" #"OTTO" (bytes 0 1 0 0))) (raise 'probe-fail)) - (port-count-lines! stream) + ;; skip variationCoords (field [_directoryPos (port-position stream)] - [_tables (mhash)] + [_tables (mhash)] ; holds decoded tables (loaded lazily) [_glyphs (mhash)] [_layoutEngine #f]) @@ -28,14 +27,17 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (send this _decodeDirectory) (define/public (_getTable table-tag) - (unless (hash-has-key? (hash-ref directory 'tables) table-tag) - (raise-argument-error '_getTable "table that exists" table-tag)) - (hash-ref! _tables table-tag (_decodeTable table-tag))) ; load table from cache, decode if necessary - - (define/public (_decodeTable table) - (report table '_decodeTable:starting) - (define-values (l c p) (port-next-location stream)) - (set-port-next-location! stream l c p)) + (unless (has-table? this table-tag) + (raise-argument-error '_getTable "table that exists in font" table-tag)) + (hash-ref! _tables table-tag (_decodeTable table-tag))) ; get table from cache, load if not there + + (define/public (_decodeTable table-tag) + (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/public (_decodeDirectory) (set! directory (directory-decode stream (mhash '_startOffset 0))) @@ -84,20 +86,19 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js ;; The font’s [ascender](https://en.wikipedia.org/wiki/Ascender_(typography)) (define/contract (ascent this) (->m number?) - (FT_FaceRec-ascender (· this ft-face))) + (hash-ref (send this _getTable 'hhea) 'ascent)) ;; The font’s [descender](https://en.wikipedia.org/wiki/Descender) (define/contract (descent this) (->m number?) - (FT_FaceRec-descender (· this ft-face))) + (hash-ref (send this _getTable 'hhea) 'descent)) ;; The amount of space that should be included between lines (define/contract (lineGap this) (->m number?) - (define hhea-table (cast (FT_Get_Sfnt_Table (· this ft-face) 'ft_sfnt_hhea) _pointer _FT_HoriHeader-pointer)) - (FT_HoriHeader-lineGap hhea-table)) + (hash-ref (send this _getTable 'hhea) 'lineGap)) (define/contract (underlinePosition this) @@ -143,11 +144,11 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js ;; The font’s bounding box, i.e. the box that encloses all glyphs in the font. (define/contract (bbox this) (->m (is-a?/c BBox)) - (let ([bbox (FT_FaceRec-bbox (· this ft-face))]) - (make-object BBox (FT_BBox-xMin bbox) - (FT_BBox-yMin bbox) - (FT_BBox-xMax bbox) - (FT_BBox-yMax bbox)))) + (define head-table (send this _getTable 'head)) + (make-object BBox (· head-table xMin) + (· head-table yMin) + (· head-table xMax) + (· head-table yMax))) (define/contract (_cmapProcessor this) @@ -164,16 +165,16 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js -(define (has-table? this tag) - (FT_Load_Sfnt_Table (· this ft-face) (tag->int tag) 0 0 0)) +(define/contract (has-table? this tag) + ((or/c bytes? symbol?) . ->m . boolean?) + (hash-has-key? (· this directory tables) (if (bytes? tag) + (string->symbol (bytes->string/latin-1 tag)) + tag))) -(define (has-cff-table? this) (has-table? this #"CFF ")) - -(define (has-morx-table? this) (has-table? this #"morx")) - -(define (has-gpos-table? this) (has-table? this #"GPOS")) - -(define (has-gsub-table? this) (has-table? this #"GSUB")) +(define has-cff-table? (curryr has-table? '|CFF |)) +(define has-morx-table? (curryr has-table? 'morx)) +(define has-gpos-table? (curryr has-table? 'GPOS)) +(define has-gsub-table? (curryr has-table? 'GSUB)) ;; Returns a glyph object for the given glyph id. @@ -262,23 +263,23 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (error 'fontkit:create "unknown font format"))) -(module+ test - (require rackunit) - (define f (openSync (path->string charter-path))) - (check-equal? (postscriptName f) "Charter") - (check-equal? (· f unitsPerEm) 1000) - (check-equal? (· f ascent) 980) - (check-equal? (· f descent) -238) - (check-equal? (measure-string f "f" (· f unitsPerEm)) 321.0) - (check-false (· f has-cff-table?)) - (check-false (· f has-morx-table?)) - (check-false (· f has-gsub-table?)) - (check-false (· f has-gpos-table?)) - (check-true (send f has-table? #"cmap")) - (check-equal? (· f lineGap) 0) - (check-exn exn:fail:contract? (λ () (send f _getTable 'nonexistent-table-tag))) - (send f _getTable 'maxp) - #;(· f createSubset) - - - ) \ No newline at end of file +(test-module + (define f (openSync (path->string charter-path))) + (check-equal? (postscriptName f) "Charter") + (check-equal? (· f unitsPerEm) 1000) + (check-equal? (· f ascent) 980) + (check-equal? (· f descent) -238) + (check-equal? (bbox->list (· f bbox)) '(-161 -236 1193 963)) + (check-equal? (measure-string f "f" (· f unitsPerEm)) 321.0) + (check-false (· f has-cff-table?)) + (check-false (· f has-morx-table?)) + (check-false (· f has-gsub-table?)) + (check-false (· f has-gpos-table?)) + (check-true (send f has-table? #"cmap")) + (check-equal? (· f lineGap) 0) + (check-exn exn:fail:contract? (λ () (send f _getTable 'nonexistent-table-tag))) + #;(send f _getTable 'maxp) + (define subset (make-object TTFSubset f)) + (send subset encode) + + ) \ No newline at end of file diff --git a/pitfall/fontkit/glyph-position.rkt b/pitfall/fontkit/glyph-position.rkt index 2d40fe57..34b149ff 100644 --- a/pitfall/fontkit/glyph-position.rkt +++ b/pitfall/fontkit/glyph-position.rkt @@ -1,4 +1,4 @@ -#lang pitfall/racket +#lang fontkit/racket (provide GlyphPosition) ;; Represents positioning information for a glyph in a GlyphRun. diff --git a/pitfall/fontkit/glyph.rkt b/pitfall/fontkit/glyph.rkt index 659bf331..5ec34582 100644 --- a/pitfall/fontkit/glyph.rkt +++ b/pitfall/fontkit/glyph.rkt @@ -1,4 +1,4 @@ -#lang pitfall/racket +#lang fontkit/racket (require "freetype-ffi.rkt") (provide Glyph CFFGlyph TTFGlyph) (module+ test (require rackunit)) diff --git a/pitfall/fontkit/glyphrun.rkt b/pitfall/fontkit/glyphrun.rkt index 050adfbc..07c7f520 100644 --- a/pitfall/fontkit/glyphrun.rkt +++ b/pitfall/fontkit/glyphrun.rkt @@ -1,4 +1,4 @@ -#lang pitfall/racket +#lang fontkit/racket (require "bbox.rkt" "script.rkt") (provide GlyphRun) diff --git a/pitfall/fontkit/head.rkt b/pitfall/fontkit/head.rkt new file mode 100644 index 00000000..3be8ecf7 --- /dev/null +++ b/pitfall/fontkit/head.rkt @@ -0,0 +1,52 @@ +#lang fontkit/racket +(require restructure) +(provide (all-defined-out)) + +(define-subclass RStruct (Rhead)) + +(define head (make-object Rhead + (dictify + '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 (make-object RArray int32be 2) + 'modified (make-object RArray int32be 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 uint16be + #| +new Bitfield(uint16be [ + ' '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 + ))) + +(test-module + (require "directory.rkt") + (define ip (open-input-file charter-path)) + (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") + (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 magicNumber) #x5F0F3CF5)) + diff --git a/pitfall/fontkit/helper.rkt b/pitfall/fontkit/helper.rkt new file mode 100644 index 00000000..176f6716 --- /dev/null +++ b/pitfall/fontkit/helper.rkt @@ -0,0 +1,12 @@ +#lang racket/base +(require (for-syntax racket/base) racket/runtime-path br/define) +(provide (all-defined-out)) + +(define index? (λ (x) (and (number? x) (integer? x) (not (negative? x))))) + +(define-runtime-path charter-path "../pitfall/test/assets/Charter.ttf") + +(define-macro (test-module . EXPRS) + #`(module+ test + (require #,(datum->syntax caller-stx 'rackunit)) + . EXPRS)) \ No newline at end of file diff --git a/pitfall/fontkit/hhea.rkt b/pitfall/fontkit/hhea.rkt new file mode 100644 index 00000000..dc4e4983 --- /dev/null +++ b/pitfall/fontkit/hhea.rkt @@ -0,0 +1,39 @@ +#lang fontkit/racket +(require restructure) +(provide (all-defined-out)) + +(define-subclass RStruct (Rhhea)) + +(define hhea (make-object Rhhea + (dictify + 'version int32be + 'ascent int16be ;; Distance from baseline of highest ascender + 'descent int16be ;; Distance from baseline of lowest descender + 'lineGap int16be ;; Typographic line gap + 'advanceWidthMax uint16be ;; Maximum advance width value in 'hmtx' table + 'minLeftSideBearing int16be ;; Maximum advance width value in 'hmtx' table + 'minRightSideBearing int16be ;; Minimum right sidebearing value + 'xMaxExtent int16be + 'caretSlopeRise int16be ;; Used to calculate the slope of the cursor (rise/run); 1 for vertical + 'caretSlopeRun int16be ;; 0 for vertical + 'caretOffset int16be ;; Set to 0 for non-slanted fonts + 'reserved (make-object RArray int16be 4) + 'metricDataFormat int16be ;; 0 for current format + 'numberOfMetrics uint16be ;; Number of advance widths in 'hmtx' table + ))) + +(test-module + (require "directory.rkt") + (define ip (open-input-file charter-path)) + (define dir (directory-decode ip)) + (define offset (· dir tables hhea offset)) + (define length (· dir tables hhea length)) + (check-equal? offset 292) + (check-equal? length 36) + (define table-bytes #"\0\1\0\0\3\324\377\22\0\0\4\311\377_\377`\4\251\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\345") + (set-port-position! ip 0) + (check-equal? (peek-bytes length offset ip) table-bytes) + (define table-data (send hhea decode (make-object RDecodeStream table-bytes))) + (check-equal? (· table-data ascent) 980) + (check-equal? (· table-data descent) -238)) + diff --git a/pitfall/fontkit/layout-engine.rkt b/pitfall/fontkit/layout-engine.rkt index bd4540cb..08615d91 100644 --- a/pitfall/fontkit/layout-engine.rkt +++ b/pitfall/fontkit/layout-engine.rkt @@ -1,4 +1,4 @@ -#lang pitfall/racket +#lang fontkit/racket (require "script.rkt" "glyph.rkt" "glyphrun.rkt" "glyph-position.rkt") (provide LayoutEngine) diff --git a/pitfall/fontkit/main.rkt b/pitfall/fontkit/main.rkt index 4a9db4b0..f076aaaa 100644 --- a/pitfall/fontkit/main.rkt +++ b/pitfall/fontkit/main.rkt @@ -1,4 +1,4 @@ -#lang restructure/racket +#lang fontkit/racket (r+p "font.rkt" "glyph-position.rkt" diff --git a/pitfall/fontkit/maxp.rkt b/pitfall/fontkit/maxp.rkt new file mode 100644 index 00000000..630310da --- /dev/null +++ b/pitfall/fontkit/maxp.rkt @@ -0,0 +1,39 @@ +#lang fontkit/racket +(require restructure) +(provide (all-defined-out)) + +(define-subclass RStruct (Rmaxp)) + +(define maxp (make-object Rmaxp + (dictify 'version int32be + 'numGlyphs uint16be ;; The number of glyphs in the font + 'maxPoints uint16be ;; Maximum points in a non-composite glyph + 'maxContours uint16be ;; Maximum contours in a non-composite glyph + 'maxComponentPoints uint16be ;; Maximum points in a composite glyph + 'maxComponentContours uint16be ;; Maximum contours in a composite glyph + 'maxZones uint16be ;; 1 if instructions do not use the twilight zone, 2 otherwise + 'maxTwilightPoints uint16be ;; Maximum points used in Z0 + 'maxStorage uint16be ;; Number of Storage Area locations + 'maxFunctionDefs uint16be ;; Number of FDEFs + 'maxInstructionDefs uint16be ;; Number of IDEFs + 'maxStackElements uint16be ;; Maximum stack depth + 'maxSizeOfInstructions uint16be ;; Maximum byte count for glyph instructions + 'maxComponentElements uint16be ;; Maximum number of components referenced at “top level” for any composite glyph + 'maxComponentDepth uint16be ;; Maximum levels of recursion; 1 for simple components + ))) + +(test-module + (require "directory.rkt") + (define ip (open-input-file charter-path)) + (define dir (directory-decode ip)) + (define maxp-offset (· dir tables maxp offset)) + (define maxp-length (· dir tables maxp length)) + (check-equal? maxp-offset 328) + (check-equal? maxp-length 32) + (define maxp-bytes #"\0\1\0\0\0\345\0f\0\a\0O\0\4\0\1\0\0\0\0\0\n\0\0\2\0\1s\0\2\0\1") + (set-port-position! ip 0) + (check-equal? (peek-bytes maxp-length maxp-offset ip) maxp-bytes) + (define maxp-data (send maxp decode (make-object RDecodeStream maxp-bytes))) + (check-equal? (· maxp-data numGlyphs) 229) + (check-equal? (· maxp-data version) 65536)) + diff --git a/pitfall/fontkit/racket.rkt b/pitfall/fontkit/racket.rkt new file mode 100644 index 00000000..5bb02fe4 --- /dev/null +++ b/pitfall/fontkit/racket.rkt @@ -0,0 +1,30 @@ +#lang racket/base +(require (for-syntax racket/base br/syntax)) +(provide (for-syntax (all-from-out racket/base br/syntax))) +(provide (all-from-out racket/base) r+p) + +(define-syntax-rule (r+p id ...) (begin (require id ...) (provide (all-from-out id ...)))) + +(r+p "helper.rkt" + sugar/debug + racket/class + racket/file + racket/match + racket/string + racket/format + racket/contract + racket/list + racket/port + racket/function + br/define + sugar/class + sugar/js + sugar/dict + sugar/stub + sugar/port) + +(module reader syntax/module-reader + #:language 'fontkit/racket + #:read @-read + #:read-syntax @-read-syntax + (require (prefix-in @- scribble/reader))) \ No newline at end of file diff --git a/pitfall/fontkit/script.rkt b/pitfall/fontkit/script.rkt index d404a0be..dfdecfc8 100644 --- a/pitfall/fontkit/script.rkt +++ b/pitfall/fontkit/script.rkt @@ -1,4 +1,4 @@ -#lang pitfall/racket +#lang fontkit/racket (provide (all-defined-out)) ;; approximates diff --git a/pitfall/fontkit/subset.rkt b/pitfall/fontkit/subset.rkt index 91e234c6..6a9095ef 100644 --- a/pitfall/fontkit/subset.rkt +++ b/pitfall/fontkit/subset.rkt @@ -1,9 +1,11 @@ -#lang pitfall/racket +#lang fontkit/racket (require "clone.rkt" "ttfglyphencoder.rkt") (provide Subset CFFSubset TTFSubset) -;; approximates -;; https://github.com/devongovett/fontkit/blob/master/src/subset/Subset.js +#| +approximates +https://github.com/devongovett/fontkit/blob/master/src/subset/Subset.js +|# (define-subclass object% (Subset font) (field [glyphs empty] ; list of glyph ids in the subset @@ -67,8 +69,20 @@ https://github.com/mbutterick/fontkit/blob/master/src/subset/TTFSubset.js (for ([gid (in-list (· this glyphs))]) (send this _addGlyph gid)) - (define maxp (cloneDeep (send (· this font) _getTable maxp))) + (define maxp (cloneDeep (send (· this font) _getTable 'maxp))) + ;; (hash-set! maxp 'numGlyphs (length (· this glyf))) ; todo + + ;; todo + ;; this.loca.offsets.push(this.offset); + ;; Tables.loca.preEncode.call(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; (unfinished) ) + diff --git a/pitfall/fontkit/tables.rkt b/pitfall/fontkit/tables.rkt new file mode 100644 index 00000000..c6a1a3d3 --- /dev/null +++ b/pitfall/fontkit/tables.rkt @@ -0,0 +1,11 @@ +#lang fontkit/racket +(provide (all-defined-out)) + +(define-macro (define-table-decoders ID TABLE-ID ...) + (with-pattern ([TABLE-ID-STRINGS (pattern-case-filter #'(TABLE-ID ...) + [STX (datum->syntax caller-stx (format "~a.rkt" (syntax->datum #'STX)))])]) + #'(begin + (r+p . TABLE-ID-STRINGS) + (define ID (make-hasheq (map cons (list 'TABLE-ID ...) (list TABLE-ID ...))))))) + +(define-table-decoders table-decoders maxp hhea head) \ No newline at end of file diff --git a/pitfall/fontkit/ttfglyphencoder.rkt b/pitfall/fontkit/ttfglyphencoder.rkt index 284da511..e34ed100 100644 --- a/pitfall/fontkit/ttfglyphencoder.rkt +++ b/pitfall/fontkit/ttfglyphencoder.rkt @@ -1,4 +1,4 @@ -#lang pitfall/racket +#lang fontkit/racket (provide TTFGlyphEncoder) (define-subclass object% (TTFGlyphEncoder) diff --git a/pitfall/pitfall/helper.rkt b/pitfall/pitfall/helper.rkt index b5866f30..3068a231 100644 --- a/pitfall/pitfall/helper.rkt +++ b/pitfall/pitfall/helper.rkt @@ -25,7 +25,7 @@ (define (layout? x) (and (hash? x) (hash-has-key? x 'glyphs) (hash-has-key? x 'positions))) -(define index? (and/c (not/c negative?) integer?)) +(define index? (and/c number? integer? (not/c negative?))) \ No newline at end of file diff --git a/pitfall/restructure/decodestream.rkt b/pitfall/restructure/decodestream.rkt index da307dc4..401e9a36 100644 --- a/pitfall/restructure/decodestream.rkt +++ b/pitfall/restructure/decodestream.rkt @@ -24,14 +24,12 @@ [endian '("" BE LE)]) (values (string->symbol (format "~a~a" key endian)) value)))) -(require racket/port) ;; basically just a wrapper for a Racket port (define-subclass object% (RDecodeStream [buffer-in #""]) - (field [buffer (if (input-port? buffer-in) - (port->bytes buffer-in) - buffer-in)] - [length (bytes-length buffer)] - [_port (open-input-bytes buffer)]) + (field [_port (cond + [(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)]) (define/public (read count) diff --git a/pitfall/sugar/port.rkt b/pitfall/sugar/port.rkt index fe4cf839..70f9528b 100644 --- a/pitfall/sugar/port.rkt +++ b/pitfall/sugar/port.rkt @@ -3,5 +3,22 @@ (provide (all-defined-out) (all-from-out racket/port)) (define (port-position ip) - (define-values (line col pos) (port-next-location ip)) - pos) \ No newline at end of file + (file-position ip)) + +(define (set-port-position! ip where) + (file-position ip where)) + +(module+ test + (require rackunit) + (define ip (open-input-bytes (bytes 1 2 3 4))) + (port-count-lines! ip) + (check-equal? (port-position ip) 0) + (check-equal? (read-byte ip) 1) + (check-equal? (port-position ip) 1) + (check-equal? (read-byte ip) 2) + (set-port-position! ip 4) + (check-equal? (port-position ip) 4) + (check-equal? (read-byte ip) eof) + (set-port-position! ip 0) + (check-equal? (port-position ip) 0) + (check-equal? (read-byte ip) 1)) \ No newline at end of file