Hello Werner,

> Should we change this to a public function?
> 
> 
>     Werner

I think this might prove very useful. Essentially if we define

%%%
#(define-markup-list-command (space-lines layout props mlist) (markup-list?)
   #:properties ((baseline-skip 4.5))
   (space-lines baseline-skip (interpret-markup-list layout props mlist)))
%%%

we can then also get the behaviour of `\wordwrap-lines` for `\wordwrap-string` 
as

\markuplist \space-lines \wordwrap-string-internal ##f "Lorem ipsum [...]"

which has the advantage that long texts can have page breaks, and we can reflow 
this into say columns as in the attached mockup.

It would be nice to do this breakable though. Maybe here it might make sense 
to generalize the pure-unpure concept, e.g. having a breakable stencil which 
returns a height estimate. Page breaking splits this into a set of blocks and 
calls a hook with the height of the blocks, which would flow the content into 
the blocks, or something.

Cheers,
Tina
#(define-markup-list-command (space-lines layout props mlist) (markup-list?)
   #:properties ((baseline-skip 4.5))
   (space-lines baseline-skip (interpret-markup-list layout props mlist)))

#(define-markup-command (columnify layout props ncols mlist) (integer? markup-list?)
   #:properties ((line-width)
                 (col-sep 4.5))
   (define (find-col-break ncols heights extensive)
     (if (<= ncols 1)
         (list
          (cons 'buckets (list (length heights)))
          (cons 'heights (list (apply + heights)))
          (cons 'avg-height (apply + heights))
          (cons 'avg-h2 (expt (apply + heights) 2)))
         (let ((current-opt 0)
               (current-opt-val +inf.0)
               (current-opt-ret 0)
               (current-bucket 0)
               (current-height 0)
               (current-rest heights)
               (heuristic (/ (apply + heights) ncols)))
           (for-each
            (lambda (height)
              (set! current-bucket (1+ current-bucket))
              (set! current-height (+ current-height height))
              (set! current-rest (cdr current-rest))
              (if (or extensive
                      (and (>= current-height (* heuristic 0.7))
                           (<= current-height (* heuristic 1.3))))
                  (let* ((rest-opt (find-col-break (1- ncols) current-rest #f))
                         (avg (assoc-get 'avg-height rest-opt))
                         (avg-h2 (assoc-get 'avg-h2 rest-opt))
                         (buckets (assoc-get 'buckets rest-opt))
                         (new-avg (/ (+ current-height (* (1- ncols) avg)) ncols))
                         (new-avg-h2 (/ (+ (expt current-height 2) (* (1- ncols) avg-h2)) ncols))
                         (score (- new-avg-h2 (expt new-avg 2))))
                    (if (<= score current-opt-val)
                        (begin
                         (set! current-opt current-bucket)
                         (set! current-opt-val score)
                         (set! current-opt-ret
                               (list
                                (cons 'buckets (cons current-bucket buckets))
                                (cons 'heights (cons current-height (assoc-get 'heights rest-opt)))
                                (cons 'avg-height new-avg)
                                (cons 'avg-h2 new-avg-h2))))))))
            heights)
           (if (and (= current-opt 0) (not extensive)) ; No solution within 30% of average height was found
               (find-col-break ncols heights #t)
               current-opt-ret))))

   (define (split-list lst l1 . rest)
     (if (null? rest)
         (list lst)
         (cons
          (list-head lst l1)
          (apply split-list (list-tail lst l1) rest))))


   (let* ((col-width (/ (- line-width (* (1- ncols) col-sep)) ncols))
          (lines (interpret-markup-list layout (cons (list (cons 'line-width col-width)) props) mlist))
          (heights (map (lambda (x) (interval-length (ly:stencil-extent x Y))) lines))
          (col-break (find-col-break ncols heights #f))
          (buckets (assoc-get 'buckets col-break))
          (b-heights (assoc-get 'heights col-break))
          (max-height (apply max b-heights))
          (b-lines (apply split-list lines buckets))
          (s-lines
           (map
            (lambda (lines height n-lines n-col)
              (let ((pad (if (> n-lines 1) (/ (- max-height height) (1- n-lines)) 0)))
                (ly:stencil-translate-axis
                 (ly:stencil-aligned-to (stack-stencils Y DOWN pad lines) X LEFT)
                 (* n-col (+ col-width col-sep)) X)))
            b-lines b-heights buckets (iota ncols))))
     (apply ly:stencil-add s-lines)))

\markup \column {
  \fill-line { \null \fontsize #6 PREFACE \null }
  \vspace #1
  \columnify #3 \space-lines \wordwrap-string-internal ##t "
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
"
  \vspace #2
}

\markup \column {
  \fill-line { \null \fontsize #6 "CRITICAL REMARKS" \null }
  \vspace #1
  \columnify #3 \space-lines \wordwrap-string-internal ##t "
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
"
}

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to