On Fri, Jun 3, 2016 at 8:44 AM, David Nalesnik wrote:
> Hi,
>
> On Fri, Jun 3, 2016 at 2:48 AM, Simon Albrecht wrote:
>> On 03.06.2016 03:25, tisimst wrote:
>>>
>>> There has been some EXCELLENT work to make this (more) automated
>>
>>
>> Done by David Nalesnik (and Paul Morris). Try searching the -user archive
>> for ‘text-spanner-inner-text’. At least that’s the filename I have here.
>>
>
> See http://www.mail-archive.com/lilypond-user%40gnu.org/msg105069.html
> for code to include and a number of usage examples.
>
Cleaner version attached.
DN
P.S. Lots and lots of code -- to keep clutter down, you will probably
want to put it in a file to be included.
\version "2.19.27"
FUNCTIONS TO INCLUDE
%% CUSTOM GROB PROPERTIES
% Taken from http://www.mail-archive.com/lilypond-user%40gnu.org/msg97663.html
% (Paul Morris)
% function from "scm/define-grob-properties.scm" (modified)
#(define (cn-define-grob-property symbol type?)
(set-object-property! symbol 'backend-type? type?)
(set-object-property! symbol 'backend-doc "custom grob property")
symbol)
% For internal use.
#(cn-define-grob-property 'text-spanner-stencils list?)
% user interface
#(cn-define-grob-property 'text-spanner-line-count number-list?)
% How much space between line and object to left and right?
% Default is '(0.0 . 0.0).
#(cn-define-grob-property 'line-X-offset number-pair?)
% Vertical shift of connector line, independenf of texts.
#(cn-define-grob-property 'line-Y-offset number?)
#(define (get-text-distribution text-list line-extents)
;; Given a list of texts and a list of line extents, attempt to
;; find a decent line distribution. The goal is to put more texts
;; on longer lines, while ensuring that first and last lines are texted.
;; TODO: ideally, we should consider extents of text, rather than
;; simply their number.
(let* ((line-count (length line-extents))
(text-count (length text-list))
(line-lengths
(map (lambda (line) (interval-length line))
line-extents))
(total-line-len (apply + line-lengths))
(exact-per-line
(map (lambda (line-len)
(* text-count (/ line-len total-line-len)))
line-lengths))
;; First and last lines can't be untexted.
(adjusted
(let loop ((epl exact-per-line) (idx 0) (result '()))
(if (null? epl)
(reverse! result)
(if (and (or (= idx 0)
(= idx (1- line-count)))
(< (car epl) 1.0))
(loop (cdr epl) (1+ idx)
(cons 1.0 result))
(loop (cdr epl) (1+ idx)
(cons (car epl) result)))
;; The idea is to raise the "most roundable" line's count, then the
;; "next most roundable," and so forth, until we account for all texts.
;; Everything else is rounded down (except those lines which need to be
;; bumped up to get the minimum of one text), so we shouldn't exceed our
;; total number of texts.
;; TODO: Need a promote-demote-until-flush to be safe, unless this is
;; mathematically sound!
(define (promote-until-flush result)
(let* ((floored (map floor result))
(total (apply + floored)))
(if (>= total text-count)
(begin
;(format #t "guess: ~a~%~%~%" result)
floored)
(let* ((decimal-amount
(map (lambda (x) (- x (floor x))) result))
(maximum (apply max decimal-amount))
(max-location
(list-index
(lambda (x) (= x maximum))
decimal-amount))
(item-to-bump (list-ref result max-location)))
;(format #t "guess: ~a~%" result)
(list-set! result max-location (ceiling item-to-bump))
(promote-until-flush result)
(let ((result (map inexact->exact
(promote-until-flush adjusted
(if (not (= (apply + result) text-count))
;; If this doesn't work, discard, triggering crude
;; distribution elsewhere.
'()
result
#(define (get-broken-connectors grob text-distribution connectors)
"Modify @var{connectors} to reflect line breaks. Return a list
of lists of booleans representing whether to draw a connecting line
between successive texts."
;; The variable 'connectors' holds a list of booleans representing whether
;; a line will be drawn between two successive texts. This function
;; transforms the list of booleans into a list of lists of booleans
;; which reflects line breaks and the additional lines which must be drawn.
;;
;; Given an input of '(#t #t #f)
;;
;;