diff --git a/quad/core-types.rkt b/quad/core-types.rkt index 248cf8dd..d3fc345d 100644 --- a/quad/core-types.rkt +++ b/quad/core-types.rkt @@ -49,4 +49,4 @@ (define-predicate Index? Index) -(define-type+predicate Breakpoint Nonnegative-Integer) +(define-type+predicate Breakpoint Index) diff --git a/quad/wrap-typed.rkt b/quad/wrap-typed.rkt index acfd64b7..d6ef9743 100644 --- a/quad/wrap-typed.rkt +++ b/quad/wrap-typed.rkt @@ -206,7 +206,7 @@ (cond [(not (empty? exploded-line-quads)) ;; after exploding, each quad will have a string with one character. - (define shifted-lists (shift exploded-line-quads '(1 -1))) + (define shifted-lists (shifts exploded-line-quads '(1 -1))) (define lefts (first shifted-lists)) (define rights (second shifted-lists)) (for/list : (Listof Quad) ([q-left (in-list lefts)][q (in-list exploded-line-quads)][q-right (in-list rights)]) @@ -415,26 +415,29 @@ ;; first-fit and best-fit are variants. (define-type Find-Breakpoints-Type ((Vectorof PieceQuad) Float -> (Listof Breakpoint))) (define/typed (adaptive-fit-proc pieces measure [use-first? #t] [use-best? #t]) - (((Vectorof PieceQuad) Float) (Boolean Boolean) . ->* . (Listof Nonnegative-Integer)) + (((Vectorof PieceQuad) Float) (Boolean Boolean) . ->* . (Listof Breakpoint)) ;; this is the winning performance strategy: extract the numbers first, then just wrap on those. ;; todo: how to avoid re-measuring pieces later? ;; todo: how to retain information about words per line and hyphen at end? (define-values (pieces-rendered-widths pieces-rendered-before-break-widths) (make-piece-vectors pieces)) - (define pieces-with-word-space (vector-map (λ([piece : PieceQuad]) (and (quad-has-attr? piece world:word-break-key) (equal? (quad-attr-ref (assert (quad-attr-ref piece world:word-break-key) quad?) 'nb) " "))) pieces)) + (define pieces-with-word-space (vector-map (λ([piece : PieceQuad]) (and (quad-has-attr? piece world:word-break-key) (equal? (quad-attr-ref (assert (quad-attr-ref piece world:word-break-key) quad?) world:no-break-key) " "))) pieces)) (define (make-first-fit-bps-and-widths) (define-values (reversed-bps reversed-widths) ;; breakpoints get stacked onto bps, so (car bps) is always the next starting point ;; thus use '(0) as a starting value to indicate that the first line starts at bp 0 ;; bps will end up with at least two values (if all pieces fit on first line, bps = 0 and last bp) - (for/fold ([bps : (Pairof Breakpoint (Listof Breakpoint)) '(0) ][line-widths : (Listof Float) empty]) - ([j-1 : Breakpoint (in-range (vector-length pieces))]) + (for/fold ([bps : (Pairof Breakpoint (Listof Breakpoint)) '(0) ] + [line-widths : (Listof Value-Type) empty]) + ;; (in-range (vector-length pieces)) won't work here because it doesn't preserve Index type + ([j-1 : Breakpoint (in-list (range (vector-length pieces)))]) (define line-starting-bp (car bps)) (define line-width (get-line-width (make-trial-line pieces-rendered-widths pieces-rendered-before-break-widths - line-starting-bp (add1 j-1)))) + ;; add1 does not preserve Index type, so assert + line-starting-bp (assert (add1 j-1) index?)))) (if (fl> line-width (fl* world:allowed-overfull-ratio measure)) (values (cons j-1 bps) (cons line-width line-widths)) (values bps line-widths)))) @@ -497,7 +500,7 @@ 0.0) (fl world:new-line-penalty) ($penalty->value penalty-up-to-i) - (let ([line-width (get-line-width (make-trial-line pieces-rendered-widths pieces-rendered-before-break-widths i j))]) + (let ([line-width (get-line-width (make-trial-line pieces-rendered-widths pieces-rendered-before-break-widths (assert i index?) (assert j index?)))]) (cond ;; overfull line: huge penalty prevents break; multiplier is essential for monotonicity. ;; multiply by -1 because line-width is longer than measure, thus diff is negative