lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Force text on line without using \textLengthOn


From: Urs Liska
Subject: Re: Force text on line without using \textLengthOn
Date: Fri, 26 Oct 2018 11:54:21 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1

Hi Harm,


Am 25.10.2018 um 23:38 schrieb Thomas Morley:
Hi Urs,

Am Do., 25. Okt. 2018 um 17:49 Uhr schrieb Urs Liska <address@hidden>:
...


> Hi Urs,

> from your description it sounds you need sort of a spanner with
> adjustable length.
> Attached some coding hacking TextSpanner.
> What do you think?


I didn't understand the code in detail, but am I right that

the code basically prints the texts as the start of a TextSpanner
Yes

\endTextSpanners parses a music expression and adds a \stopTextSpan 
automatically for any \startTextSpan
Not exactly, the first event with \startTextSpan is disregarded, all
other events with \startTextSpan get a \stopTextSpan added. The last
note/rest/skip/eventchord gets a \stopTextSpan as well.

OK. I don't really understand the handling of first and last events here, but I think I don't need this approach anyway.


\testII creates such a \startTextSpan to be processed by  \endTextSpanners
Yes

?

If so this means that all the music must be wrapped in an \endTextSpanners 
expression, isn't it?
Not exactly.
The proposed code/example does so, yes.
Though, \endTextSpanners is more for conveniance., you could drop
\endTextSpanners entirely and set \stopTextSpan manually.

I had a try that *seemed* to be successful, see below

If this is true then I would be quite a stretch to integrate this solution into 
my environment, because the input files are part of the edition in this case. 
They will be made available within a TEI file and therefore have to be 
extremely clean. So far there is exactly one \include and then either a single 
music expression (for a single-voice music example) or several music variables 
plus a custom \loadTemplate command that loads a file with a \score block to 
make use of the music variables.

For the first case (simple music expression) I can achieve the result by calling 
\endTextSpanners at the very end of the include file so the music expression will be 
used as the argument for the function. But for the other cases I'm not sure how I could 
arrange my files. In addition I only need this functionality in a subset of my >560 
files, but such a solution could probably not be optional in the way I'm doing it 
elsewhere in the project. (The main include file loads a <filename>-include.ily 
file if that is present on disk. Within that optional file I can place a layout block, 
edition-engraver mods and an arbitrary number of \loadTool commands. While this latter 
function probably isn't necessary for efficiency reasons (it would probably be easier to 
simply include all the available code for each compiled file), it is a nice way to 
document the specific needs of an example.)

Well, I'm not familiar with TEI, the edition-engraver, etc.
Sorry.

That's not necessary here. All I wanted to point out is that I need "clean" input files and a generic structure where I can't wrap the music variables in an arbitrary function call. The reference to the TEI is only that the primary input file's content will be included in the edition and should be stripped of any code that is only needed for rendering purposes. Eventually the project will be publicly available, and I'll probably write about it so it'll become clearer what this is about ...


I think I'll do some more experiments with the code itself before trying to 
integrate this.

Hm, as said I don't fully understand the code. But if I'm not mistaken 
\endTextSpanners works by first identifying a music expression that holds a 
\startTextSpan event and then adding a \stopTextSpan event to the note, rest or 
chord. Would it be possible to achieve the same thing directly from a 
music-function or event-function? Maybe if \testII wouldn't be an event 
function but a music-function taking the note/rest/chord as an argument, like

   \testII ##t "John Doe" c'

where the TextSpanner is added to the c' ?
Well, you can't start _and_ end a TextSpanner on the same event. See
the warning for { c'1\startTextSpan\stopTextSpan }.
Thus the sophisticated endTextSpanner. Ofcourse endTextSpanner can't
end a textSpanner which is started at the last note of a file as well.

It's thinkable to create a music-functions taking a musical argument
and doing something like
{ \myFunction c'1 }
-> { c'1\startTextSpan <>\stopTextSpan }
This will return a warning if at happens at the end of a file, though.

I copied all relevant code to a different structure, and while it compiles and produces the spanners as desired there are still problems.

%%%
\version "2.19.82"

#(define (minimum-length-from-stencil process-string?)
   ;; Set the minimum-length of a grob, which is supposed to be a TextSpanner,
   ;; to the length of the stencil of bound-details.left.text plus 0.1
   (lambda (grob)
     (let* ((bound-details (ly:grob-property grob 'bound-details))
            (lft (assoc-get 'left bound-details))
            (txt (assoc-get 'text lft))
            (txt-stil
             (if (markup? txt)
                 (grob-interpret-markup
                  grob
                  (if process-string?
                      (markup->string txt)
                      txt))
                 #f))
            (txt-x-ext (if txt-stil (ly:stencil-extent txt-stil X) #f))
            (txt-x-length
             (if (and txt-x-ext (interval-sane? txt-x-ext))
                 (- (cdr txt-x-ext) (car txt-x-ext))
                 0)))
       (+ txt-x-length 0.1))))


startSingleTextSpan =
#(define-event-function (text-length-on txt)((boolean? #f) markup?)
   #{
     -\tweak style #'none
     -\tweak staff-padding 3
     -\tweak springs-and-rods #ly:spanner::set-spacing-rods
     -\tweak minimum-length  #(minimum-length-from-stencil #f)
     -\tweak minimum-length-after-break 0
     -\tweak font-shape #'upright
     -\tweak bound-details.left.text
     #(if text-length-on
          txt
          (make-with-dimensions-markup empty-interval empty-interval txt))
     -\tweak bound-details.left-broken.text ##f
     \startTextSpan
   #})

spanner =
#(define-music-function (text-length-on text music)((boolean?) markup? 
ly:music?)
   (let*
    ((is-single-music #t))
    (define (append-script-at! prop)
      (set! (ly:music-property music prop)
            (append (ly:music-property music prop)
              (list (startSingleTextSpan text-length-on text)))))

    (case (ly:music-property music 'name)
      ((EventChord)
       (append-script-at! 'elements))
      ((NoteEvent RestEvent SkipEvent)
       (append-script-at! 'articulations))
      (else (set! is-single-music #f)))
(if is-single-music
        #{
          #music
          <>\stopTextSpan
        #}
        music)))

my-upbow =
#(define-music-function (text-length-on music)((boolean?) ly:music?)
   (spanner text-length-on "hin." music))

my-downbow =
#(define-music-function (text-length-on music)((boolean?) ly:music?)
   (spanner text-length-on "her." music))

\relative {
  \my-upbow #f
  c'16 ( d e f )
  \my-downbow #f g (
  \my-upbow #f a g a )
  \my-upbow #f \time 2/4
}
%%%

I've reversed the logic of zero-dimensions? to a text-length-on argument (#t meaning: do use the space). This doesn't affect the outcome, and the wrong behaviour was the same before I changed this.

The problem is that with this text-length-on being true the spanner pushes the next *note*, even if that doesn't have any spanner attached (first attached image) while with it being false the spanners will collide (second attachment). Additionally (but this is already present in your code) when using make-with-dimensions-markup (where is this defined? I don't find this with git grep???) the spanner will have no vertical extent as well, which can cause it to be cut off from the page (or collide with the previous system).

I don't see why the horizontal behaviour is any different in my version, and I can only speculate that it *does* have something to do with the way \endTextSpanners handles the events.

Any ideas?

PS:
I assume it is *not* possible to write a function that can be written as post-event that will add the \startTextSpan event to the current note *and* adds the <>\stopTextSpan as the next note? I'm asking because I would actually like to have this function as a drop-in replacement for \upbow and \downbow.


Cheers,
   Harm

Attachment: document.png
Description: PNG image

Attachment: document.png
Description: PNG image


reply via email to

[Prev in Thread] Current Thread [Next in Thread]