add information to wrap op

main
Matthew Butterick 6 years ago
parent b796fd2067
commit 1d4ae70355

@ -58,6 +58,9 @@
(define q:line (q #:size (pt +inf.0 line-height) (define q:line (q #:size (pt +inf.0 line-height)
#:out 'sw #:out 'sw
#:printable #true)) #:printable #true))
(define q:line-spacer (q #:size (pt +inf.0 (/ line-height 2))
#:out 'sw
#:printable #true))
(define softies (map string '(#\space #\- #\u00AD))) (define softies (map string '(#\space #\- #\u00AD)))
(define (soft-break-for-line? q) (define (soft-break-for-line? q)
@ -90,8 +93,11 @@
(break xs size (break xs size
#:hard-break-proc (λ (q) (equal? "" (car (quad-elems q)))) #:hard-break-proc (λ (q) (equal? "" (car (quad-elems q))))
#:soft-break-proc soft-break-for-line? #:soft-break-proc soft-break-for-line?
#:finish-wrap-proc (λ (pcs) (list (struct-copy quad q:line #:finish-wrap-proc (λ (pcs q idx)
[elems (consolidate-runs pcs)]))))) (append
(if (= idx 1) (list q:line-spacer) null)
(list (struct-copy quad q:line
[elems (consolidate-runs pcs)]))))))
(define q:page (q #:offset '(36 36) (define q:page (q #:offset '(36 36)
#:pre-draw (λ (q doc) (add-page doc)))) #:pre-draw (λ (q doc) (add-page doc))))
@ -101,14 +107,14 @@
(define (page-wrap xs vertical-height) (define (page-wrap xs vertical-height)
(break xs vertical-height #:finish-wrap-proc (λ (pcs) (list (struct-copy quad q:page [elems pcs]))))) (break xs vertical-height #:finish-wrap-proc (λ (pcs q idx) (list (struct-copy quad q:page [elems pcs])))))
(define (run xs path) (define (run xs path)
(define pdf (time-name make-pdf (make-pdf #:compress #t (define pdf (time-name make-pdf (make-pdf #:compress #t
#:auto-first-page #f #:auto-first-page #f
#:output-path path))) #:output-path path)))
(define line-width 200) (define line-width 200)
(define vertical-height 200) (define vertical-height 400)
(let* ([x (time-name runify (runify (qexpr->quad xs)))] (let* ([x (time-name runify (runify (qexpr->quad xs)))]
[x (time-name ->string-quad (map (λ (x) (->string-quad pdf x)) x))] [x (time-name ->string-quad (map (λ (x) (->string-quad pdf x)) x))]
[x (time-name line-wrap (line-wrap x line-width))] [x (time-name line-wrap (line-wrap x line-width))]

@ -105,7 +105,7 @@
(define (line-wrap xs size [debug #f]) (define (line-wrap xs size [debug #f])
(break xs size debug (break xs size debug
#:soft-break-proc soft-break? #:soft-break-proc soft-break?
#:finish-wrap-proc (λ (pcs) (list (struct-copy quad $line #:finish-wrap-proc (λ (pcs q idx) (list (struct-copy quad $line
[elems [elems
;; consolidate chars into a single run (naively) ;; consolidate chars into a single run (naively)
;; by taking attributes from first (including origin) ;; by taking attributes from first (including origin)
@ -117,7 +117,7 @@
(define (page-wrap xs size [debug #f]) (define (page-wrap xs size [debug #f])
(break xs size debug (break xs size debug
#:finish-wrap-proc (λ (pcs) (list (struct-copy quad $page #:finish-wrap-proc (λ (pcs q idx) (list (struct-copy quad $page
[elems pcs]))))) [elems pcs])))))
(define (typeset pdf qarg) (define (typeset pdf qarg)

@ -13,13 +13,13 @@
[debug #f] [debug #f]
#:hard-break-proc [hard-break? (λ (x) #f)] #:hard-break-proc [hard-break? (λ (x) #f)]
#:soft-break-proc [soft-break? (λ (x) #f)] #:soft-break-proc [soft-break? (λ (x) #f)]
#:finish-wrap-proc [finish-wrap-proc list]) #:finish-wrap-proc [finish-wrap-proc (λ (xs q idx) (list xs))])
#;((listof quad?) #;((listof quad?)
(real? (real?
any/c any/c
#:hard-break-proc (quad? . -> . any/c) #:hard-break-proc (quad? . -> . any/c)
#:soft-break-proc (quad? . -> . any/c) #:soft-break-proc (quad? . -> . any/c)
#:finish-wrap-proc ((listof any/c) . -> . (listof any/c))) . ->* . (listof any/c)) #:finish-wrap-proc ((listof any/c) quad? natural? . -> . (listof any/c))) . ->* . (listof any/c))
(break-hards xs target-size debug hard-break? soft-break? finish-wrap-proc)) (break-hards xs target-size debug hard-break? soft-break? finish-wrap-proc))
;; the hard breaks are used to divide the wrap territory into smaller chunks ;; the hard breaks are used to divide the wrap territory into smaller chunks
@ -50,19 +50,24 @@
target-size target-size
debug debug
soft-break? soft-break?
finish-wrap-proc) ; takes quads in wrap; returns list containing wrap (and maybe other things) finish-wrap-proc) ; takes quads in wrap, triggering quad, and wrap idx; returns list containing wrap (and maybe other things)
(define (finish-wrap qs wrap-idx [wrap-triggering-q (car qs)])
;; reverse because quads accumulated in reverse
;; wrap-triggering-q is ordinarily the last accumulated q
;; unless it's the last wrap, in which case it's #f
;; but we capture it separately because it's likely to get trimmed away by `nonprinting-at-end?`
(finish-wrap-proc (reverse (dropf qs nonprinting-at-end?)) wrap-triggering-q wrap-idx))
(let loop ([wraps null] ; list of (list of quads) (let loop ([wraps null] ; list of (list of quads)
[wrap-idx 1] ; wrap count
[next-wrap-head null] ; list of quads ending in previous `soft-break?` [next-wrap-head null] ; list of quads ending in previous `soft-break?`
[next-wrap-tail null] ; list of unbreakable quads [next-wrap-tail null] ; list of unbreakable quads
[current-dist #false] ; #false (to indicate start) or integer [current-dist #false] ; #false (to indicate start) or integer
[qs qs]) ; list of quads [qs qs]) ; list of quads
(match qs (match qs
[(== empty) (define last-wrap (wrap-append next-wrap-tail next-wrap-head)) [(== empty) (define last-wrap (finish-wrap (wrap-append next-wrap-tail next-wrap-head) wrap-idx #f))
(append* ; because `finish-wrap-proc` returns a spliceable list ; append* because `finish-wrap-proc` returns a spliceable list
(reverse ; because wraps accumulated in reverse ; reverse because wraps accumulated in reverse
(for/list ([wrap-qs (in-list (cons last-wrap wraps))]) (append* (reverse (cons last-wrap wraps)))]
;; reverse because quads accumulated in reverse
(finish-wrap-proc (reverse (dropf wrap-qs nonprinting-at-end?))))))]
[(cons q other-qs) [(cons q other-qs)
(debug-report q 'next-q) (debug-report q 'next-q)
(debug-report (quad-elems q) 'next-q-elems) (debug-report (quad-elems q) 'next-q-elems)
@ -73,12 +78,14 @@
[(and (? soft-break?) (? nonprinting-at-start?)) [(and (? soft-break?) (? nonprinting-at-start?))
(debug-report q 'skipping-soft-break-at-beginning) (debug-report q 'skipping-soft-break-at-beginning)
(loop wraps (loop wraps
wrap-idx
next-wrap-head next-wrap-head
next-wrap-tail next-wrap-tail
current-dist current-dist
other-qs)] other-qs)]
[_ (debug-report 'hard-quad-at-start) [_ (debug-report 'hard-quad-at-start)
(loop wraps (loop wraps
wrap-idx
next-wrap-head next-wrap-head
(list q) (list q)
(distance q) (distance q)
@ -94,19 +101,22 @@
;; a break is inevitable but we want to wait to finish the wrap until we see a hard quad ;; a break is inevitable but we want to wait to finish the wrap until we see a hard quad
;; but we can move the current-partial into the current-wrap ;; but we can move the current-partial into the current-wrap
(loop wraps (loop wraps
wrap-idx
(wrap-append (cons q next-wrap-tail) next-wrap-head) (wrap-append (cons q next-wrap-tail) next-wrap-head)
null null
(+ dist current-dist) (+ dist current-dist)
other-qs)] other-qs)]
[_ #:when (empty? next-wrap-head) [_ #:when (empty? next-wrap-head)
(debug-report 'would-overflow-hard-without-captured-break) (debug-report 'would-overflow-hard-without-captured-break)
(loop (cons next-wrap-tail wraps) (loop (cons (finish-wrap next-wrap-tail wrap-idx) wraps)
(add1 wrap-idx)
null null
null null
#false #false
qs)] qs)]
[_ ; finish the wrap & reset the line without consuming a quad [_ ; finish the wrap & reset the line without consuming a quad
(loop (cons next-wrap-head wraps) (loop (cons (finish-wrap next-wrap-head wrap-idx) wraps)
(add1 wrap-idx)
null null
next-wrap-tail next-wrap-tail
(apply + (map distance next-wrap-tail)) (apply + (map distance next-wrap-tail))
@ -115,6 +125,7 @@
(debug-report 'would-not-overflow-soft) (debug-report 'would-not-overflow-soft)
;; a soft break that fits, so move it on top of the next-wrap-head with the next-wrap-tail ;; a soft break that fits, so move it on top of the next-wrap-head with the next-wrap-tail
(loop wraps (loop wraps
wrap-idx
(wrap-append (cons q next-wrap-tail) next-wrap-head) (wrap-append (cons q next-wrap-tail) next-wrap-head)
null null
(+ dist current-dist) (+ dist current-dist)
@ -123,6 +134,7 @@
(debug-report 'would-not-overflow) (debug-report 'would-not-overflow)
;; add to partial ;; add to partial
(loop wraps (loop wraps
wrap-idx
next-wrap-head next-wrap-head
(cons q next-wrap-tail) (cons q next-wrap-tail)
(+ dist current-dist) (+ dist current-dist)
@ -167,7 +179,7 @@
(define (linewrap xs size [debug #f]) (define (linewrap xs size [debug #f])
(add-between (break xs size debug (add-between (break xs size debug
#:finish-wrap-proc list #:finish-wrap-proc (λ (xs . _) (list xs))
#:hard-break-proc (λ (q) (char=? (car (quad-elems q)) #\newline)) #:hard-break-proc (λ (q) (char=? (car (quad-elems q)) #\newline))
#:soft-break-proc soft-break?) lbr)) #:soft-break-proc soft-break?) lbr))
@ -344,7 +356,7 @@
(break xs size debug (break xs size debug
#:hard-break-proc (λ (q) (memv (car (quad-elems q)) '(#\newline))) #:hard-break-proc (λ (q) (memv (car (quad-elems q)) '(#\newline)))
#:soft-break-proc soft-break? #:soft-break-proc soft-break?
#:finish-wrap-proc (λ (pcs) (list (apply q pcs)))) #:finish-wrap-proc (λ (pcs . _) (list (apply q pcs))))
lbr)) lbr))
(module+ test (module+ test

Loading…
Cancel
Save