|
|
|
@ -18,13 +18,12 @@
|
|
|
|
|
(define-runtime-path default-font-face "default-fonts/default/SourceSerifPro-Regular.otf")
|
|
|
|
|
(define top-font-directory "fonts")
|
|
|
|
|
(define font-file-extensions '(#".otf" #".ttf" #".woff" #".woff2"))
|
|
|
|
|
(define default-font-family "text")
|
|
|
|
|
(define default-font-size 12)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (fonts-in-directory dir)
|
|
|
|
|
(for/list ([font-path (in-directory dir)]
|
|
|
|
|
#:when (member (path-get-extension font-path) font-file-extensions))
|
|
|
|
|
font-path))
|
|
|
|
|
font-path))
|
|
|
|
|
|
|
|
|
|
(define (setup-font-path-table [base-path (current-directory)])
|
|
|
|
|
;; create a table of font paths that we can use to resolve references to font names.
|
|
|
|
@ -46,36 +45,36 @@
|
|
|
|
|
#:when (directory-exists? font-family-subdir)
|
|
|
|
|
[fonts-in-this-directory (in-value (fonts-in-directory font-family-subdir))]
|
|
|
|
|
[font-path (in-list fonts-in-this-directory)])
|
|
|
|
|
(match-define (list font-path-string family-name)
|
|
|
|
|
(for/list ([x (list font-path font-family-subdir)])
|
|
|
|
|
(path->string (find-relative-path fonts-dir x))))
|
|
|
|
|
(define path-parts (for/list ([part (in-list (explode-path (string->path (string-downcase font-path-string))))])
|
|
|
|
|
(path->string part)))
|
|
|
|
|
(define key
|
|
|
|
|
(cons (string-downcase family-name)
|
|
|
|
|
(cond
|
|
|
|
|
;; special case: if there's only one style in the family directory,
|
|
|
|
|
;; treat it as the regular style, regardless of name
|
|
|
|
|
[(= (length fonts-in-this-directory) 1) 'r]
|
|
|
|
|
;; cases where fonts are in subdirectories named by style
|
|
|
|
|
;; infer style from subdir name
|
|
|
|
|
[(member "bold-italic" path-parts) 'bi]
|
|
|
|
|
[(member "bold" path-parts) 'b]
|
|
|
|
|
[(member "italic" path-parts) 'i]
|
|
|
|
|
[else
|
|
|
|
|
;; try to infer from filename alone
|
|
|
|
|
;; TODO: what happens when there is no regular style?
|
|
|
|
|
(define filename (string-downcase (last path-parts)))
|
|
|
|
|
(define filename-contains-bold? (string-contains? filename "bold"))
|
|
|
|
|
(define filename-contains-italic? (string-contains? filename "italic"))
|
|
|
|
|
(cond
|
|
|
|
|
[(and filename-contains-bold? filename-contains-italic?) 'bi]
|
|
|
|
|
[filename-contains-bold? 'b]
|
|
|
|
|
[filename-contains-italic? 'i]
|
|
|
|
|
[else 'r])])))
|
|
|
|
|
;; only set value if there's not one there already.
|
|
|
|
|
;; this means that we only use the first eligible font we find.
|
|
|
|
|
(hash-ref! font-paths key font-path))
|
|
|
|
|
(match-define (list font-path-string family-name)
|
|
|
|
|
(for/list ([x (list font-path font-family-subdir)])
|
|
|
|
|
(path->string (find-relative-path fonts-dir x))))
|
|
|
|
|
(define path-parts (for/list ([part (in-list (explode-path (string->path (string-downcase font-path-string))))])
|
|
|
|
|
(path->string part)))
|
|
|
|
|
(define key
|
|
|
|
|
(cons (string-downcase family-name)
|
|
|
|
|
(cond
|
|
|
|
|
;; special case: if there's only one style in the family directory,
|
|
|
|
|
;; treat it as the regular style, regardless of name
|
|
|
|
|
[(= (length fonts-in-this-directory) 1) 'r]
|
|
|
|
|
;; cases where fonts are in subdirectories named by style
|
|
|
|
|
;; infer style from subdir name
|
|
|
|
|
[(member "bold-italic" path-parts) 'bi]
|
|
|
|
|
[(member "bold" path-parts) 'b]
|
|
|
|
|
[(member "italic" path-parts) 'i]
|
|
|
|
|
[else
|
|
|
|
|
;; try to infer from filename alone
|
|
|
|
|
;; TODO: what happens when there is no regular style?
|
|
|
|
|
(define filename (string-downcase (last path-parts)))
|
|
|
|
|
(define filename-contains-bold? (string-contains? filename "bold"))
|
|
|
|
|
(define filename-contains-italic? (string-contains? filename "italic"))
|
|
|
|
|
(cond
|
|
|
|
|
[(and filename-contains-bold? filename-contains-italic?) 'bi]
|
|
|
|
|
[filename-contains-bold? 'b]
|
|
|
|
|
[filename-contains-italic? 'i]
|
|
|
|
|
[else 'r])])))
|
|
|
|
|
;; only set value if there's not one there already.
|
|
|
|
|
;; this means that we only use the first eligible font we find.
|
|
|
|
|
(hash-ref! font-paths key font-path))
|
|
|
|
|
font-paths)
|
|
|
|
|
|
|
|
|
|
(define (make-key font-family [bold #f] [italic #f])
|
|
|
|
@ -101,9 +100,9 @@
|
|
|
|
|
(display "(fontconfig lookup unimplemented)")
|
|
|
|
|
#;(for* ([bold (in-list (list #false #true))]
|
|
|
|
|
[italic (in-list (list #false #true))])
|
|
|
|
|
(hash-set! font-paths
|
|
|
|
|
(make-key font-family bold italic)
|
|
|
|
|
(family->path font-family #:bold bold #:italic italic))))
|
|
|
|
|
(hash-set! font-paths
|
|
|
|
|
(make-key font-family bold italic)
|
|
|
|
|
(family->path font-family #:bold bold #:italic italic))))
|
|
|
|
|
(cond
|
|
|
|
|
[(hash-ref font-paths (make-key font-family bold italic) #false)]
|
|
|
|
|
;; try regular style if style-specific key isn't there for b i or bi
|
|
|
|
@ -116,16 +115,16 @@
|
|
|
|
|
(member (path-get-extension (string->path x)) font-file-extensions)
|
|
|
|
|
#true))
|
|
|
|
|
|
|
|
|
|
(define (resolve-font-path font-paths val attrs)
|
|
|
|
|
(define (resolve-font-path font-paths attrs)
|
|
|
|
|
;; convert references to a font family and style to an font path on disk
|
|
|
|
|
;; we trust it exists because we used `setup-font-path-table` earlier,
|
|
|
|
|
;; but if not, fallback fonts will kick in, on the idea that a missing font shouldn't stop the show
|
|
|
|
|
(define this-font-family (hash-ref! attrs :font-family default-font-family))
|
|
|
|
|
(define this-font-family (hash-ref attrs :font-family (λ () (error 'need-default-font-family))))
|
|
|
|
|
(match (string-downcase this-font-family)
|
|
|
|
|
[(? font-path-string? ps) (path->complete-path ps)]
|
|
|
|
|
[_
|
|
|
|
|
(define this-bold (hash-ref! attrs :font-bold #false))
|
|
|
|
|
(define this-italic (hash-ref! attrs :font-italic #false))
|
|
|
|
|
(define this-bold (hash-ref attrs :font-bold (λ () (error 'need-default-font-bold))))
|
|
|
|
|
(define this-italic (hash-ref attrs :font-italic (λ () (error 'need-default-font-italic))))
|
|
|
|
|
(font-attrs->path font-paths this-font-family this-bold this-italic)]))
|
|
|
|
|
|
|
|
|
|
(define-pass (resolve-font-paths qs)
|
|
|
|
@ -137,7 +136,7 @@
|
|
|
|
|
(define font-paths (setup-font-path-table))
|
|
|
|
|
(do-attr-iteration qs
|
|
|
|
|
#:which-attr :font-family
|
|
|
|
|
#:attr-proc (λ (ak av attrs) (resolve-font-path font-paths av attrs))))
|
|
|
|
|
#:attr-proc (λ (_ __ attrs) (resolve-font-path font-paths attrs))))
|
|
|
|
|
|
|
|
|
|
(define (resolved-font-for-family val #:bold [bold #f] #:italic [italic #f])
|
|
|
|
|
(define qs (list (make-quad #:attrs (make-hasheq
|
|
|
|
@ -146,16 +145,6 @@
|
|
|
|
|
(cons :font-italic italic))))))
|
|
|
|
|
(last (explode-path (quad-ref (car (resolve-font-paths qs)) :font-family))))
|
|
|
|
|
|
|
|
|
|
(module+ test
|
|
|
|
|
(require rackunit)
|
|
|
|
|
(define-attr-list debug-attrs
|
|
|
|
|
[:font-family (attr-uncased-string-key 'font-family)])
|
|
|
|
|
(parameterize ([current-attrs debug-attrs])
|
|
|
|
|
(check-equal? (resolved-font-for-family "Heading") (string->path "fira-sans-light.otf"))
|
|
|
|
|
(check-equal? (resolved-font-for-family "CODE") (string->path "fira-mono.otf"))
|
|
|
|
|
(check-equal? (resolved-font-for-family "blockquote" #:bold #t) (string->path "fira-sans-bold.otf"))
|
|
|
|
|
(check-equal? (resolved-font-for-family "nonexistent-fam") (string->path "SourceSerifPro-Regular.otf"))))
|
|
|
|
|
|
|
|
|
|
(define (parse-em pstr)
|
|
|
|
|
(define em-suffix "em")
|
|
|
|
|
(and
|
|
|
|
@ -188,9 +177,17 @@
|
|
|
|
|
|
|
|
|
|
(define font-paths (setup-font-path-table))
|
|
|
|
|
(do-attr-iteration qs
|
|
|
|
|
#:attr-proc (λ (ak av attrs) (resolve-font-size-once attrs))))
|
|
|
|
|
|
|
|
|
|
#:attr-proc (λ (_ __ attrs) (resolve-font-size-once attrs))))
|
|
|
|
|
|
|
|
|
|
(module+ test
|
|
|
|
|
(require rackunit)
|
|
|
|
|
(define-attr-list debug-attrs
|
|
|
|
|
[:font-family (make-attr-uncased-string-key 'font-family)])
|
|
|
|
|
(parameterize ([current-attrs debug-attrs])
|
|
|
|
|
(check-equal? (resolved-font-for-family "Heading") (string->path "fira-sans-light.otf"))
|
|
|
|
|
(check-equal? (resolved-font-for-family "CODE") (string->path "fira-mono.otf"))
|
|
|
|
|
(check-equal? (resolved-font-for-family "blockquote" #:bold #t) (string->path "fira-sans-bold.otf"))
|
|
|
|
|
(check-equal? (resolved-font-for-family "nonexistent-fam") (string->path "SourceSerifPro-Regular.otf")))
|
|
|
|
|
|
|
|
|
|
(define qs (bootstrap-input (make-quad #:tag 'div #:attrs (make-hasheq (list (cons :font-size "100pt"))) #:elems (list (make-quad #:tag 'span #:attrs (make-hasheq (list (cons :font-size-previous "100pt") (cons :font-size "1.5em"))))))))
|
|
|
|
|
(resolve-font-sizes (parse-dimension-strings qs)))
|
|
|
|
|
#;(resolve-font-sizes (parse-dimension-strings qs)))
|
|
|
|
|