2017-08-25 0:01 GMT+02:00 Kieren MacMillan <[email protected]>:
> Hi Saul,
>
>> Personally, I think the behavior would be better if it aligned on the first 
>> dynamic to appear in the markup, rather than default to left.
>
> Perhaps better if this is a preference/parameter, with the default being 
> *left-aligned* not *dynamic-aligned*.
> (I would personally keep it left-aligned, and then use the edition-engraver 
> to tweak the position of the rare "outliers".)
>
>> With something like "poco f", it can be visually unclear where the f is 
>> supposed to begin — at the beginning of "poco" or at the "f"? That's a bit 
>> clearer of the dynamic itself is always the alignment point (though I prefer 
>> to always have the dynamic first for maximum clarity).
>
> Gould (pg. 107) addresses this. There are definitely more ambiguities and 
> potential problems with dynamic-aligning such texts than there are "safe 
> situations" (e.g., with preceding rests) — which is why, like you, I always 
> prefer to have the dynamic first (when possible).
>
> Cheers,
> Kieren.

Hi all,

the here so far proposed codes fail, if punctuation comes into the game.
\new Staff { c''\dynamic  "poco f, but p sub. ma non troppo" }

Thus I based my own code on the previous work of Valentin Villenave:
https://codereview.appspot.com/2220041/
https://codereview.appspot.com/20660044/

One problem for the event-function persists:
To get the first dynamic-word center-aligned under the NoteColumn you
need to do some calculations for tweaking X-offset or
self-alignment-X. (I choosed X-offset because the calculation is a
little easier ...)
Whatever you choose, a certain tweak is hardcoded now. And further
tweaking after applying the event-function will at first not work:
Having set a hardcoded tweak for X-offset makes it impossible to get a
tweak for self-alignment-X to work, neither would an additional
X-offset-tweak work. If I would have gone for self-alignment-X in the
event-function further tweaks of the same property would not work
either.

I think that's what David K explained here:
http://lists.gnu.org/archive/html/lilypond-user/2017-08/msg00194.html

Thus I coded a possibilty to lookup for an additional X-offset-tweak,
which will add it's value to the setting caused by the event-function.
Theoretically this could be done with self-alignment-X as well, but I
regarded the results from a users points of view too unpredictable.

Here's the code:


\version "2.19.64"

#(define (char-punctuation? ch)
  (char-set-contains? char-set:punctuation ch))

#(define char-set:dynamics
  (char-set #\f #\m #\p #\r #\s #\z))

#(define composite-chars
  (char-set-union char-set:dynamics char-set:punctuation))

#(define-markup-command (dynamic-text layout props str) (string?)
  "Takes a string, puts out a line-markup.
Parts of @var{strg} containing only characters used for dynamics are printed
using \\dynamic (punctuation-signs are disregarded.
Other parts are printed \\italic.

@lilypond[verbatim,quote]
\\markup {
  \\dynamic-text #\"poco f, but p sub. ma non troppo\"
}
@end lilypond
"
  (let* ((str-list (string-split str #\space))
         (text-markup
           (lambda (s) (make-normal-text-markup (make-italic-markup s)))))
    (interpret-markup layout props
      (make-line-markup
        ;; iterate over 'str-list'
        ;; - parts only containing dynamics/punctuation are splitted.
        ;;   dynamics are printed \dynamic, others \italic
        ;;   and finally \concat is applied
        ;; - others are printed \italic
        (map
          (lambda (word)
            (if (string-every composite-chars word)
                (let ((word-lst (string->list word)))
                  (make-concat-markup
                    (map
                      (lambda (ch)
                        (let ((print-ch (string ch)))
                          (if (char-punctuation? ch)
                              (text-markup print-ch)
                              (make-dynamic-markup print-ch))))
                      word-lst)))
                (text-markup word)))
          str-list)))))

dynamicH =
#(define-event-function (strg) (string?)
"Takes a string and puts out a (composed) dynamic script.
If the first word of the composed string is a dynamic sign, the ready dynamic-
script center-aligns this word at the parent-grob.
Further adapting the result with additional tweaks for X-offset are possible.
"
  (let* ((first-word (car (string-split strg #\space)))
         ;; don't take punctuation into account
         (trimmed-first-word (string-trim-both first-word char-set:punctuation))
         (offset
           (lambda (grob)
             (let* (;; get previous tweaks for X-offset and add their values
                    ;; they are added to the final result
                    (x-offset-tweaks
                      (filter
                        (lambda (tw)
                          (and (number? (cdr tw)) (eq? (car tw) 'X-offset)))
                        (ly:prob-property
                          (ly:grob-property grob 'cause)
                          'tweaks)))
                    (x-off (apply + (map cdr x-offset-tweaks))))
               ;; if 'first-word' is a dynamic, calculate it's x-extent and
               ;; return half of it's value
               ;; always take 'x-off' into account
               (if (string-every composite-chars first-word)
                   (let* ((layout (ly:grob-layout grob))
                          (props
                            (ly:grob-alist-chain grob
                              (ly:output-def-lookup
                                layout
                                'text-font-defaults)))
                          (first-word-stil
                            (interpret-markup layout props
                              (make-dynamic-text-markup trimmed-first-word)))
                          (first-word-stil-center
                            (interval-center
                              (ly:stencil-extent first-word-stil X))))
                     (+ x-off (- first-word-stil-center)))
                    ;; adding -1 is my choice
                    (+ x-off -1))))))

    #{
      -\tweak X-offset $offset
      #(make-dynamic-script (make-dynamic-text-markup strg))
    #}))

%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\new StaffGroup <<
  \new Staff { c''\dynamicH "fffff dramatically" }
  \new Staff { c''-\tweak X-offset -1 -\dynamicH "fffff dramatically" }
  \new Staff { c''-\tweak X-offset 1 -\dynamicH "fffff dramatically" }
  \new Staff { c''\dynamicH "fffff,,,,,,,,,, dramatically" }
  \new Staff { c''\dynamicH  "poco f, but p sub. ma non troppo" }
  \new Staff { c''\dynamicH "slightly more pp" }
>>


Though, because of the problems mentioned above I'm not sure whether
putting dynamic-script-creation _and_ settings for aligning it into
the same function.
The possibility to create dynamic-scripts on the fly and have them
aligned properly while having a nice user interface is nice, ofcourse,
but one needs to set more or less hardcoded defaults which then are
not changeable easily anymore, if at all.

HTH,
  Harm

_______________________________________________
lilypond-user mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to