diff --git a/fontland/fontland/font.rkt b/fontland/fontland/font.rkt index ee3212cd..d67d8505 100644 --- a/fontland/fontland/font.rkt +++ b/fontland/fontland/font.rkt @@ -5,7 +5,6 @@ "bbox.rkt" "glyphrun.rkt" "directory.rkt" - "db.rkt" "struct.rkt" "table-stream.rkt" xenomorph @@ -68,82 +67,31 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (+bbox (hash-ref head-table 'xMin) (hash-ref head-table 'yMin) (hash-ref head-table 'xMax) (hash-ref head-table 'yMax))) -(define current-layout-caching (make-parameter #false)) - -(struct hb-gid (val) #:transparent) -(struct hb-cluster (chars) #:transparent) -(struct hb-position (xad yad xoff yoff etc) #:transparent) -(struct hb-layout (hb-gids hb-clusters hb-positions) #:transparent) - -(define hb-output (x:struct 'hb-gids (x:array #:type uint16 #:length uint16) - 'hb-clusters (x:array #:type (x:array #:type uint16 #:length uint16) #:length uint16) - 'hb-positions (x:array #:type (x:array #:type uint16 #:length 5) #:length uint16))) - -(define (hb-layout->glyphrun font hbr) - (match hbr - [(hash-table ('hb-gids gids) - ('hb-clusters clusters) - ('hb-positions posns)) - (define glyphs (for/list ([gidx (in-list gids)] - [cluster (in-list clusters)]) - (get-glyph font gidx cluster))) - (define positions (for/list ([posn (in-list posns)]) - (apply +glyph-position posn))) - (glyphrun glyphs positions)])) - -(define (harfbuzz-layout font codepoints features script language) + +;; 181228: disk-based caching (either with sqlite or `with-cache`) is a loser +;; reads & writes aren't worth it vs. recomputing +;; (though this is good news, as it avoids massive disk caches hanging around) +;; ram cache in pitfall suffices + +;; todo: preserve semantics of user-features argument from pitfall, which is +;; #f = no features, null = default features, list = explicit features +(define (layout font str [features #f] [script #f] [language #f]) (define buf (hb-buf font)) (hb_buffer_reset buf) + (define codepoints (for/list ([c (in-string str)]) (char->integer c))) (hb_buffer_add_codepoints buf codepoints) (define chars (map hb_glyph_info_t-codepoint (hb_buffer_get_glyph_infos buf))) (hb_shape (hb-font font) buf (map tag->hb-feature (or features null))) (define gis (hb_buffer_get_glyph_infos buf)) - (dictify 'hb-gids (map hb_glyph_info_t-codepoint gis) - 'hb-clusters (break-at chars (map hb_glyph_info_t-cluster gis)) - 'hb-positions (map hb_glyph_position_t->list (hb_buffer_get_glyph_positions buf)))) - -(define layout-cache (make-hasheqv)) - -(define hb-input (x:struct 'font-crc uint32 - 'codepoints (x:array #:type uint16) - 'userFeatures (x:array #:type (x:string #:length uint8)))) - -(define (layout-cache-key font-crc codepoints user-features . _) - (crc32c-bytes (encode hb-input (dictify - 'font-crc font-crc - 'codepoints codepoints - 'userFeatures user-features) #f))) - - -;; Returns a GlyphRun object, which includes an array of Glyphs and GlyphPositions for the given string. -(init-db) ; make sure db is ready for queries -(define (layout font string [user-features #f] [script #f] [language #f] #:test [test #f]) - #;((string?) ((option/c (listof symbol?)) (option/c symbol?) (option/c symbol?)) . ->*m . GlyphRun?) - (define (get-layout string) - (define codepoints (map char->integer (string->list string))) - (define args (list codepoints (if user-features (sort user-features symbolglyphrun font layout)) (map get-layout substrs)))] - [else (if test - (get-layout string) - (hb-layout->glyphrun font (get-layout string)))])) + (define hb-gids (map hb_glyph_info_t-codepoint gis)) + (define hb-clusters (break-at chars (map hb_glyph_info_t-cluster gis))) + (define hb-positions (map hb_glyph_position_t->list (hb_buffer_get_glyph_positions buf))) + (define glyphs (for/vector ([gidx (in-list hb-gids)] + [cluster (in-list hb-clusters)]) + (get-glyph font gidx cluster))) + (define positions (for/vector ([posn (in-list hb-positions)]) + (apply +glyph-position posn))) + (glyphrun glyphs positions)) #| @@ -182,7 +130,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/base.js (error 'create-font "unknown font format"))) (module+ test - (require rackunit) + (require rackunit racket/struct) (define charter (open-font charter-path)) (define fira (open-font (path->string fira-path))) (define otf (open-font (path->string fira-otf-path))) @@ -197,11 +145,10 @@ https://github.com/mbutterick/fontkit/blob/master/src/base.js (check-equal? (font-cap-height charter) 671) (check-equal? (font-x-height charter) 481) (check-equal? (bbox->list (font-bbox charter)) '(-161 -236 1193 963)) - (check-equal? (caar (hash-ref (layout charter "f" #:test #t) 'hb-positions)) 321) + (check-equal? (glyph-position-x-advance (car (glyphrun-positions (layout charter "f")))) 321) (check-true (has-table? charter #"cmap")) (check-exn exn:fail:contract? (λ () (get-table charter 'nonexistent-table-tag))) (check-true - (let ([h (layout fira "Rifle" #:test #t)]) - (and (equal? (hash-ref h 'hb-gids) '(227 480 732 412)) - (equal? (hash-ref h 'hb-clusters) '((82) (105) (102 108) (101))) - (equal? (hash-ref h 'hb-positions) '((601 0 0 0 0) (279 0 0 0 0) (580 0 0 0 0) (547 0 0 0 0))))))) + (let ([gr (layout fira "Rifle")]) + (and (equal? (map glyph-id (glyphrun-glyphs gr)) '(227 480 732 412)) + (equal? (map struct->list (glyphrun-positions gr)) '((601 0 0 0 0) (279 0 0 0 0) (580 0 0 0 0) (547 0 0 0 0)))))))