|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
#lang typed/racket/base
|
|
|
|
|
(require (for-syntax typed/racket/base ))
|
|
|
|
|
(require (for-syntax typed/racket/base))
|
|
|
|
|
(require typed/racket/class math/flonum racket/list racket/file)
|
|
|
|
|
(require/typed racket/draw
|
|
|
|
|
[record-dc% (Class (init-field)
|
|
|
|
@ -13,8 +13,10 @@
|
|
|
|
|
(define precision 4.0)
|
|
|
|
|
(define base (flexpt 10.0 precision))
|
|
|
|
|
|
|
|
|
|
(define-syntax-rule (round-float x)
|
|
|
|
|
(fl/ (flround (fl* base (fl x))) base))
|
|
|
|
|
(: round-float (Float . -> . Float))
|
|
|
|
|
(define (round-float x)
|
|
|
|
|
(/ (round (* base x)) base))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-syntax (values->list stx)
|
|
|
|
|
(syntax-case stx ()
|
|
|
|
@ -36,9 +38,9 @@
|
|
|
|
|
(build-path "font.cache"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define current-text-cache (make-parameter (make-hash '())))
|
|
|
|
|
(define current-text-cache-changed? (make-parameter #f))
|
|
|
|
|
(define current-font-cache (make-parameter (make-hash '())))
|
|
|
|
|
(define current-text-cache (make-parameter ((inst make-hash (List String String Symbol Symbol) Measurement-Result-Type) '())))
|
|
|
|
|
(define current-text-cache-changed? : (Parameterof Boolean) (make-parameter #f))
|
|
|
|
|
(define current-font-cache (make-parameter ((inst make-hash (List String Symbol Symbol) (Instance (Class (init-field)))) '())))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (update-text-cache-file)
|
|
|
|
@ -49,20 +51,21 @@
|
|
|
|
|
(define (load-text-cache-file)
|
|
|
|
|
(define cache-file-path (get-cache-file-path))
|
|
|
|
|
(current-text-cache (if (file-exists? cache-file-path)
|
|
|
|
|
(deserialize (file->value cache-file-path))
|
|
|
|
|
(make-hash '()))))
|
|
|
|
|
(cast (deserialize (file->value cache-file-path)) (HashTable (List String String Symbol Symbol) Measurement-Result-Type))
|
|
|
|
|
((inst make-hash (List String String Symbol Symbol) Measurement-Result-Type) '()))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-type Measurement-Result-Type (List Nonnegative-Real Nonnegative-Real Nonnegative-Real Nonnegative-Real))
|
|
|
|
|
(define-type Measurement-Result-Type (List Float Float Float Float))
|
|
|
|
|
(define mrt? (make-predicate Measurement-Result-Type))
|
|
|
|
|
(define-type MMS-Type ((String String) (Symbol Symbol) . ->* . Measurement-Result-Type))
|
|
|
|
|
|
|
|
|
|
(: measure-max-size-base MMS-Type)
|
|
|
|
|
(define (measure-max-size-base text font [weight 'normal] [style 'normal])
|
|
|
|
|
(define font-instance (cast (hash-ref! (current-font-cache) (list font weight style) (λ() (make-font #:size max-size #:style style #:weight weight #:face font))) (Instance (Class (init-field)))))
|
|
|
|
|
;; 'combine' boolean only makes a difference for two or more chars
|
|
|
|
|
(send dc get-text-extent text font-instance (>= (string-length text) 1))
|
|
|
|
|
(cast (hash-ref! (current-text-cache) (list text font weight style) (λ() #;(current-text-cache-changed? #t)
|
|
|
|
|
(values->list (send dc get-text-extent text font-instance (>= (string-length text) 1))))) Measurement-Result-Type))
|
|
|
|
|
(define font-instance (hash-ref! (current-font-cache) (list font weight style) (λ() (make-font #:size max-size #:style style #:weight weight #:face font))))
|
|
|
|
|
;; 'combine' boolean only makes a difference for two or more chars, so use (>= (string-length text) 1) for speed
|
|
|
|
|
((inst hash-ref! (List String String Symbol Symbol) Measurement-Result-Type) (current-text-cache) (list text font weight style) (λ() (current-text-cache-changed? #t)
|
|
|
|
|
(define-values (width height descent extra) (send dc get-text-extent text font-instance (>= (string-length text) 1)))
|
|
|
|
|
(list (fl width) (fl height) (fl descent) (fl extra)))))
|
|
|
|
|
|
|
|
|
|
(define measure-cache ((inst make-hash (List String String Symbol Symbol) Measurement-Result-Type)))
|
|
|
|
|
|
|
|
|
@ -70,32 +73,20 @@
|
|
|
|
|
(define (measure-max-size text font [weight 'normal] [style 'normal])
|
|
|
|
|
(hash-ref! measure-cache (list text font weight style) (λ () (measure-max-size-base text font weight style))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-syntax-rule (width x) (first x))
|
|
|
|
|
(define-syntax-rule (height x) (second x))
|
|
|
|
|
(define-syntax-rule (descent x) (third x))
|
|
|
|
|
(define-syntax-rule (extra x) (fourth x))
|
|
|
|
|
#;(define-syntax-rule (extra x) (fourth x))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-syntax-rule (measure-text-max-size text font weight style)
|
|
|
|
|
(width (measure-max-size text font weight style)))
|
|
|
|
|
|
|
|
|
|
(: measure-text ((String Nonnegative-Float String) (Symbol Symbol) . ->* . Nonnegative-Float))
|
|
|
|
|
;; works by taking max size and scaling it down. Allows caching of results.
|
|
|
|
|
(: measure-text ((String Positive-Float String) (Symbol Symbol) . ->* . Float))
|
|
|
|
|
(define (measure-text text size font [weight 'normal] [style 'normal])
|
|
|
|
|
;; Native function only accepts integers, so get max-size and scale down to size needed.
|
|
|
|
|
(define raw-measure (measure-text-max-size text font weight style))
|
|
|
|
|
(cast (round-float (/ (* (exact->inexact raw-measure) (exact->inexact size)) max-size)) Nonnegative-Float))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-syntax-rule (measure-ascent-max-size text font weight style)
|
|
|
|
|
(let ([result-list (measure-max-size text font weight style)])
|
|
|
|
|
(- (height result-list) (descent result-list))))
|
|
|
|
|
(define raw-width (width (measure-max-size text font weight style)))
|
|
|
|
|
(round-float (/ (* raw-width size) max-size)))
|
|
|
|
|
|
|
|
|
|
(: measure-ascent ((String Nonnegative-Float String) (Symbol Symbol) . ->* . Nonnegative-Float))
|
|
|
|
|
;; works by taking max size and scaling it down. Allows caching of results.
|
|
|
|
|
(: measure-ascent ((String Positive-Float String) (Symbol Symbol) . ->* . Float))
|
|
|
|
|
(define (measure-ascent text size font [weight 'normal] [style 'normal])
|
|
|
|
|
; ((string? flonum? string?) (symbol? symbol?) . ->* . flonum?)
|
|
|
|
|
;; Native function only accepts integers, so get max-size and scale down to size needed.
|
|
|
|
|
(define raw-baseline-distance (measure-ascent-max-size text font weight style))
|
|
|
|
|
(cast (round-float (/ (* (exact->inexact raw-baseline-distance) (exact->inexact size)) max-size)) Nonnegative-Float))
|
|
|
|
|
(define result-list : Measurement-Result-Type (measure-max-size text font weight style))
|
|
|
|
|
(define raw-baseline-distance (- (height result-list) (descent result-list)))
|
|
|
|
|
(round-float (/ (* raw-baseline-distance size) max-size)))
|