lilypond-user
[Top][All Lists]
Advanced

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

Re: how offsets and alignment works: an explanation


From: Trevor Daniels
Subject: Re: how offsets and alignment works: an explanation
Date: Sat, 23 Mar 2013 16:56:37 -0000

Hi Janek

This is explained very concisely and without examples in the NR, see
http://www.lilypond.org/doc/v2.17/Documentation/notation/aligning-objects

For a reference manual I think is is adequate, especially given the length 
of the NR already.

So the best place for this is probably the CG, as Phil suggests, with links
into it from the NR.

Trevor
 
----- Original Message ----- 
From: "Janek Warchoł" <address@hidden>
To: "LilyPond Users" <address@hidden>
Sent: Saturday, March 23, 2013 2:05 PM
Subject: how offsets and alignment works: an explanation


> Hi,
> 
> here's an explanation of what's happening when we're using XY-offset,
> self-alignment etc.  I hope that it'll help users get a better
> understanding of LilyPond internals; i also think it would be a good
> material for documentation, but i'm not sure where should it be placed
> - it seems to fit both in Learning as well as Extending, and maybe
> even CG...
> 
> Let's start at the very beginning:
> LilyPond needs to know where each and every grob should be placed.
> This placement information is stored using relative coordinates:
> position of a grob is defined relative to the position of its parent
> (if we had used absolute coordinates - e.g. distances from the edges
> of the page - it would be hard to maintain spatial relationships
> between grobs).
> 
> Every grob knows which grob is its parent in respective axis.  For
> example, a Flag knows that its X-parent is a particular Stem.
> 
> Relative coordinates that describe grob's placement are stored in grob
> properties called X-offset and Y-offset.  They are measured in
> staffspaces.  X-offset is the horizontal displacement between grob's
> reference point and the reference point of grob's X-parent (similarly
> with Y-offset).
> 
> What is a reference point?  It's a special point that defines the
> grob's position.  Think about geometry: if you have to define where a
> figure is placed on a plane, you'll usually say something like "the
> lower left corner of this square has coordinates (0, 2)" "or "the
> center of this circle is at (-1, 3)". "Lower left corner" and "center"
> would be the reference points for square and circle.
> 
> This illustration shows where refpoints of particular grobs are located:
> 
> {
>  \override NoteHead #'style = #'altdefault
>  g'2-> c''\fermata | as'1^"Yogi" |
>  b'\breve _"Larry" | \mark "Twinkle" e''8 s4.
> }
> -> see attached "refpoint examples.png"
> 
> By overriding X-offset value, we can move grobs relative to their parents:
> 
> {
>  \override NoteHead #'style = #'altdefault
>  \override Script #'X-offset = #2
>  \override TextScript #'X-offset = #1.5
>  \override Stem #'X-offset = #2
>  \override Score.RehearsalMark #'X-offset = #-2
>  g'2-> c''\fermata | as'1^"Yogi" |
>  b'\breve _"Larry" | \mark "Twinkle" e''8 s4.
> }
> -> see attached "offsets.png"
> 
> (notice that the Flag moved together with its Stem)
> 
> Now, let's explain another pair of properties: X-extent and Y-extent.
> Each of them is a pair of numbers (an Interval), and they store grob's
> dimensions relative to its reference point.  For example X-extent
> equal to (-1 . 4) means that the left edge of the grob is 1 staffspace
> to the left of its reference point, and right edge is 4 staffspace to
> the right from reference point, for a total width of 4 - (-1) = 4 + 1
> = 5 staffspaces.
> Both numbers in an extent may be positive, for example (2 . 3) is a
> valid extent: it means that the whole grob is on the right of its
> refpoint, and the width of the grob is 3 - 2 = 1 staffspace.
> Similarly, both numbers can be negative; these situations are quite
> unusual but won't give LilyPond headaches.
> The most common situation (at least for X-extent) is that the first
> number is 0, which means that the reference point is on the left edge
> of the grob.
> 
> Now, suppose that we want to position a RehearsalMark so that its
> right edge is aligned with a Barline.  With X-offset = 0 (i.e. its
> reference point aligned on parent, which is equal to Barline in this
> situation) RehearsalMark would be placed like this:
> 
> {
>  \override Score.RehearsalMark #'X-offset = #0
>  b4 b b b \mark "Twinkle" b b b b
> }
> -> see image (1) in attached "images.png"
> 
> So, we need to shift it.  Remember what the second number in X-extent
> means?  It's the position of grob's right edge relative to its
> refpoint.  If we subtract this value from 0, we'll get the X-offset we
> want:
> 
> {
>  \override Score.RehearsalMark #'X-offset = #-10.4
>  b4 b b b \mark "Twinkle" b b b b
> }
> (2)
> 
> What if we wanted to center some grob on the refpoint on its parent?
> That's simple: calculate the displacement between grob's refpoint and
> /center/ of it's extent.  Some examples:
> 1) X-extent = (-2 . 2) -> X-offset = 0 - 0 = 0
> 2) X-extent = (0 . 4) -> X-offset = 0 - (0 + 0.5 * 4) = -2
> 3) X-extent = (-2 . 4) -> X-offset = 0 - ((0.5 * -2) + (0.5 * 4)) = 0
> - (-1 + 2) = -1
> 
> There is a special C++ procedure x_aligned_on_self that can do these
> calculations for us; it's defined in Self_alignment_interface class.
> To use it, we say:
> 
> \override GrobName #'X-offset = 
> #ly:self-alignment-interface::x-aligned-on-self
> 
> And it means "when you need to know a GrobName's X-offset, run
> x_aligned_on_self procedure form Self_alignment_interface C++ class on
> this RehearsalMark and take the value that the procedure returned".
> 
> Then we need to specify what alignment we want:
> 
> \override GrobName #'self-alignment-X = #RIGHT
> 
> will tell the procedure to find the displacement between grob's
> refpoint and its right edge, and use it as X-offset, which will result
> in grob being right-aligned.
> 
> So, if you change a grob's extent, you will affect how it will be
> aligned (because LilyPond will think that grob's dimensions are
> different):
> 
> {
>  \override Score.RehearsalMark #'X-extent = #'(0 . 8)
>  \override Score.RehearsalMark #'self-alignment-X = #RIGHT
>  b4 b b b \mark "Twinkle" b b b b
> }
> (3)
> 
> Also, if a grob's extent is empty (i.e. it's not an Interval),
> procedures like x_aligned_on_self won't have any information about
> grob's dimensions, so they won't be able to calculate an offset
> (they'll just return 0).  In other words, a grob with an empty extent
> can only be "aligned" on its refpoint, because there's no other
> information that can be used for alignment:
> 
> {
>  \override Score.RehearsalMark #'X-extent = ##f
>  b4 b b b \mark "Twinkle" b b b b
> }
> (4)
> 
> Notice that empty extent and zero extent result in the same positioning:
> 
> {
>  \override Score.RehearsalMark #'X-extent = #'(0 . 0)
>  b4 b b b \mark "Twinkle" b b b b
> }
> (5)
> 
> However, empty extent (or zero extent, or any other extent) doesn't
> prevent us from placing the grob at any location we want - we just
> can't use alignment procedures for that.  We can still specify any
> offset we want, and it will work as usual:
> 
> {
>  \override Score.RehearsalMark #'X-extent = ##f
>  \override Score.RehearsalMark #'X-offset = #-10.4
>  b4 b b b \mark "Twinkle" b b b b
> }
> (6)
> 
> Now, there is one more thing to keep in mind: grob's parent has its
> own dimensions, too, and we need to take them into account.  For
> example, if we write
> 
> { a'1 }
> \addlyrics {
>  \override LyricText #'X-offset =
> #ly:self-alignment-interface::x-aligned-on-self
>  \override LyricText #'self-alignment-X = #CENTER
>  nn
> }
> (7)
> 
> the LyricText will be centered, but *on the refpoint of its parent*
> (i.e. the center of the syllable will be aligned to the refpoint of
> the notehead).  If we want the center of the LyricText to be aligned
> with the center of its parent NoteHead, we have to use a different
> procedure: aligned_on_x_parent.  It works very similarly to
> x_aligned_on_self, but in addition to calculating offset based on
> grob's own extent, it also uses grob's parent extent:
> 
> { a'1 }
> \addlyrics {
>  \override LyricText #'X-offset =
> #ly:self-alignment-interface::aligned-on-x-parent
>  \override LyricText #'self-alignment-X = #CENTER
>  nn
> }
> (8)
> 
> I hope that this helps anyone, and that i got everything right.
> 
> cheers,
> Janek
>


--------------------------------------------------------------------------------


> _______________________________________________
> lilypond-user mailing list
> address@hidden
> https://lists.gnu.org/mailman/listinfo/lilypond-user
>

reply via email to

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