On 2020-01-16 4:01 pm, Paolo Prete wrote:
This gives a clearer overview, thanks, but I would not use it, even if
it
produces the wanted result.
Sorry if I implied otherwise, but I thought I was clear that this code
was not intended for practical use. This is only test code to
demonstrate the underlying mechanisms are actually working properly. I
wanted to address what I consider a flawed premise that things are
broken. Rather, what should be clear is that things are complicated.
And I am uncomfortable with so casually equating the two.
I did not omit them, given that I did not want to reset any property,
as I
explained in other posts. In practice, you are only making reset of all
the
properties that add more space between the grob and the reference
point. At
the end, considering that you have to add a .46 value, you get even a
worse
procedure than \override Y-offset, while using the same logic (which
is:
distance from a reference point, and not *offset the result*). So: I
think
it's better to use a ruler from the middle of the staff.
No other way, if you want to preserve the avoid-collision algo.
There is no "offset the result" apart from extra-offset. There are many
ways to *influence* the positioning of a grob, but only extra-offset
operates on the final computed position. Everything else works within
the magic that is LilyPond's layout logic, which seems to be designed
around keeping as much in relative terms as opposed to absolute terms.
With that in mind, say you want to move an object upward on the page.
That is fine, but it is an absolute adjustment. To convert it to a
relative one, you must answer why you need to move the object. Is it
because it is too close to something? Is it because it does not line up
nicely with something else? Is it because the decomposing remains of a
donut you forgot about have become sentient and are whispering dark
thoughts?
Once you have clarified why something needs to move, then you can best
determine which tool is the right one for the job. The goal is to move
the object once, and not have to revisit it after other things change.
Encoding the logic behind why something needs to move lets LilyPond do
it for you. Padding can help with adjusting how near or far objects are
from one another, but sometimes alignment suffers. Alignment of grobs
requires working from a common reference point, and one will need to
consider what constructs exist within LilyPond that can help with this.
The Dynamics context, for instance, does not have to be used only for
dynamics. Of course, sometimes relative adjustments are just not
suitable and you may end up needing to use the absolute extra-offset.
As for the donut, that is beyond my pay grade, and I wish you only the
best of luck.
(Future headline: Krispy Kreme responsible for zombie outbreak with
Halloween-inspired glazed, "raised-from-the-dead" donuts.)
Of course, the tools and constructs available in LilyPond are certainly
not exhaustive. Given the discussion, it seems we could benefit greatly
with the introduction of a so-called "outside-staff-offset" which moves
grobs away from the staff by an absolute amount--think extra padding but
only on the side nearest the staff.
If that sounds interesting, know that you can approximate it with a
combination of outside-staff-padding and extra-offset to achieve
outside-staff-offset. It just takes a little grade-school math:
%%%%
\version "2.19.83"
notes = \fixed c''' { \mark "mark" \ottava 1 f8( 8) 4 \ottava 0 f,2 }
{
\omit Staff.Clef \omit Staff.TimeSignature
\override Score.RehearsalMark.self-alignment-X = #LEFT
% Default behavior.
\notes
% Try moving the bracket up by two staff spaces.
\override Staff.OttavaBracket.outside-staff-padding = 2.46
\notes
% Oops, the mark moved too far.
% Split the difference between padding and offset.
\override Staff.OttavaBracket.outside-staff-padding = 1.46
\override Staff.OttavaBracket.extra-offset = #'(0 . 1)
\notes
}
%%%%
But what happens when outside-staff-padding is *not* the defining
property controlling the vertical position? Consider a bracket whose
effective Y-offset is large enough that it is positioned too far away
from other outside-staff grobs.
This could be handled as followed:
%%%%
\version "2.19.83"
#(define (addRuler color left right)
(grob-transformer 'stencil (lambda (grob orig)
(ly:stencil-add
(grob-interpret-markup grob #{
\markup \with-dimensions-from \null
\with-color #color \path #0.1 #`(
(moveto ,left 0) (lineto ,right 0)
(moveto ,left 1) (lineto ,right 1)
(moveto ,left 2) (lineto ,right 2)
) #})
orig))))
notesI = \fixed c''' { \mark "mark" \ottava 1 d8 8 4 \ottava 0 d,2 }
notesII = \fixed c''' { \mark "mark" \ottava 1 a8( 8) 4 \ottava 0 a,2 }
shiftOttavaBracket = #(define-music-function (amount) (number?)
(let ((half (/ amount 2)))
#{
\offset Y-offset #half Staff.OttavaBracket
\override Staff.OttavaBracket.outside-staff-padding = #(+ 0.46
half)
\override Staff.OttavaBracket.extra-offset = #`(0 . ,half)
#}))
unshiftOttavaBracket = {
\revert Staff.OttavaBracket.Y-offset
\revert Staff.OttavaBracket.outside-staff-padding
\revert Staff.OttavaBracket.extra-offset
}
{
\omit Staff.Clef \omit Staff.TimeSignature
\override Score.RehearsalMark.self-alignment-X = #LEFT
% Test with bracket that is positioned by Y-offset.
\override Staff.OttavaBracket.stencil = #(addRuler red -5 10)
\notesI
\shiftOttavaBracket 1
\notesI
\shiftOttavaBracket 2
\notesI
\unshiftOttavaBracket
% Test with bracket that is positioned by outside-staff.
\override Staff.OttavaBracket.stencil = #(addRuler blue -5 10)
\notesII
\shiftOttavaBracket 1
\notesII
\shiftOttavaBracket 2
\notesII
}
%%%%
And lo and behold: \offset Y-offset is not setting the world ablaze. (:
To be clear, again, this code is nothing more than a proof of concept.
It would need to be adapted for practical use; but I truly hope folks
can see that the tools for positioning really are there. They just
might not be as specialized as we would like. I would still vote for a
*real* outside-staff-offset, as the semantics are more obvious than
trying to use a combination of other properties.
Whew, that was a lot of work for one email. I could go for a donut.
-- Aaron Hill