lilypond-devel
[Top][All Lists]
Advanced

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

[PATCH] ledger lines


From: Juergen Reuter
Subject: [PATCH] ledger lines
Date: Mon, 25 Mar 2002 23:23:11 +0100 (CET)

Hi!

Attached is a revision of the patch that I sent on last December 31st,
regarding ledger lines.  It was rejected due to blotdiameter problems.
I tried to solve them as far as possible, revealing some oddities that
are still in lily.  Hence, I hope this patch satisfies your quality
constraints, even if it still contains some issues, which, however,
reflect more general issues of lily that I can not fix in a single
patch -- this patch is already quite big as for a few relatively
simple goals!

The simple goals of this patch are:

* Junk multiple implementations of ledger line creation in note_head,
  custos, and porrectus.  This is important since there soon will be
  some more applications of ledger lines to come (e.g. ambitus
  engraver).

* Make thickness of ledgerlines adjustable.  This is essential for
  mensural notation.

* Fix some bugs in the current ledger_line implementation, most
  notably that of the horizontal extent of ledger lines which equals
  at least the extent of the metafont ledger_line character, and which
  grows(!) if the desired extent shrinks below this limit.


When I sent the first revision of this patch, it was rejected since
the resulting ledger lines had sharp edges, although the draw_box
routine in music-drawing-routines.ps seemed to regard blotdiameter.
In the meantime, draw_box seems to consider blotdiameter (at least
with the environment of my machine).  Though a faced a couple of new
problems that I would like to discuss.

First of all, I think the current model of blotdiameter may lead to
weird effects, not to say that it is mathmatically seen ambigous.  Let
me explain this on the example of draw_box.  draw_box draws a box with
round edges as follows:

  __________________________  ______
 /     \  ^           /     \      ^
|         |blot              |     |
|       | |dia       |       |     |
|         |meter             |     |
|\ _ _ /  v           \ _ _ /|     |
|                            |     |
|                            |     | Box
|                    <------>|     | extent
|                      blot  |     | (Y_AXIS)
|                    diameter|     |
|                            |     |
|  _ _                  _ _  |     |
|/     \              /     \|     |
|                            |     |
|       |            |       |     |
|(0,0)                       |     v
x\_____/______________\_____/ ______
|                            |
|                            |
|                            |
|<-------------------------->|
      Box extent(X_AXIS)

This works well, as long as the extent (either X_AXIS or Y_AXIS) is
greater than or equal to blotdiameter.  However, if below
blotdiameter, you get, in the best case weird effects, or in the worst
case, ambigous behaviour.  In my opinion, if below blotdiameter,
draw_box should create a blot, i.e. a dot of size blotdiameter.  To
implement this correctly, draw_box probably should bound the extent
via doing something like x_extent:=max(blotdiameter,x_extent), and the
same for y extent; otherwise you may internally end up operating with
negative values for width or height.

To circumvent this situation, I would like to suggest a different
model for "blotting" an existing shape: given an arbitrary shape, just
move a pencircle of size blotdiameter around the outline of this shape
to create a blotted shape.  In the case of draw_box, this leads to the
following model:

  __________________________
 /     \  ^           /     \
|         |blot              |
|   +   | |dia       |   +---|------
|         |meter             |     ^
|\ _ _ /  v           \ _ _ /|     |
|                            |     |
|                            |     | Box
|                    <------>|     | extent
|                      blot  |     | (Y_AXIS)
|                    diameter|     |
|                            |     |
|  _ _                  _ _  |     |
|/     \              /     \|     |
| (0,0)                      |     v
|   x   |            |   +---|------
|   |                    |   |
 \__|__/______________\__|__/
    |                    |
    |                    |
    |                    |
    |<------------------>|
      Box extent(X_AXIS)

Note, that "blotting" slightly increases the dimensions of an existing
shape by half the diameter of the blot.  However, you solve the above
problems of an extent smaller than blotdiameter in a natural way.  If
the extent is set to 0, with this model, you really get a single blot
(i.e. a circle with diameter blotdiameter) as result.

In my attached patch, I have included an implementation for the above
box model (at least for ps; I could not find out how to easily draw a
circle in pdf; any volunteers appreciated!); see
Lookup::roundfilledbox ().

This model is general enough to apply to any shape with a steady
outline and has some more advantageous properties regarding backwards
compatibility to work done earlier in lilypond.  As you correctly
presumed, the porrectus shape is broken due to the recently introduced
blotting on beams and bezier curves.  For example, have a look at
composing complex shapes from beams.

a) Shape composed from beams without blotting:

       |\
       | \
       |  \
       |   \
       |    \
       |     \
        \     \
         \    |
         |\   |
         | \  |
         |  \ |
         |   \|
         |    \
          \   |
           \  |
            \ |
             \|

b) The same shape composed from beams with blotting similar to current
draw_box implementation:

         _
        / \
       |   \
       |    \
       |     \
        \     \
         \    |
          \   |
           \  |
          / \_/
         |   \
         |    \
          \   |
           \  |
            \_/


b) Once again the same shape composed from beams with blotting as
above suggested:

       _
      / \
      |  \
      |   \
      |    \
      |     \
      |      \
      |       \
       \       \
        |      |
        |      |
        |      |
        |      |
         \     |
          \    |
           \   |
            \  |
             \_/

In c), the two shapes overlap by an amount such that inner edges as in
b) do not arise.

Actually, from having a look at mensural porrectus in ancient-font.ly,
the current implementation of beam seems to be a mixture of b) and c),
which is even worse...

By the way, I think, blotdiameter should be passed as parameter to
general-purpose functions like filledbox, since different notation
styles may prefer different values for blotdiameter.  The fact that in
the metafont code, pencircles of different sizes are used, stresses
this need.  With the current implementation, setting blotdiameter in
the paper block has no effect on Lookup::filledbox; my implementation
of Lookup::roundfilledbox however considers blotdiameter; and this
effect can also be seen on ledger_lines if Lookup::roundfilledbox is
used in Note-head::brew_ledger_lines.

By another way, do I really need a Grob *me, to do a thing like
me->paper_l ()->get_var ("...")?  I think, these variables are global,
and hence there should be a possibilty of accessing them without
having a Grob at hand (I really do not like to pass a Grob into a
function of class Lookup).  Or am I missing here something?

Ah, and yes, it seems the blotdiameter on bezier curves and filledbox
(when called by roundfilledbox on the ps level in ps.scm) is too big
by an estimated factor of 2.  Maybe radius and diameter have been
confused somewhere?  For compensation of this error, the call to
Lookup::roundfilledbox in Note-head::brew_ledger_lines currently uses
a blotdiameter multiplied by a factor of 2.0.  This constant should be
removed as soon as this error is fixed.

To switch between filledbox and roundfilledbox when creating ledger
lines, just comment in/out the proper call in
Note-head::brew_ledger_lines.

porrectus.cc:
>  /*
>
>  TODO:
>
>  ugr. why not  called direction?
>
>   */
>  SCM stem_direction_scm = me->get_grob_property ("direction");

Because it's really only the direction of the stem (or rather
"cauda"), not the direction of the whole grob.  But this code will
have to be revised in a few weeks, anyway.

Greetings,
Juergen

Attachment: patch_1.5.47_jr1.diff
Description: Text document


reply via email to

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