]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge branch 'master' of git://git.sv.gnu.org/lilypond
authorGraham Percival <graham@percival-music.ca>
Fri, 2 May 2008 23:51:30 +0000 (16:51 -0700)
committerGraham Percival <graham@percival-music.ca>
Fri, 2 May 2008 23:51:30 +0000 (16:51 -0700)
48 files changed:
Documentation/topdocs/NEWS.tely
Documentation/user/fundamental.itely
Documentation/user/lilypond-book.itely
VERSION
flower/include/drul-array.hh
input/regression/arpeggio-parenthesis.ly [new file with mode: 0644]
input/regression/completion-heads-lyrics.ly [new file with mode: 0644]
input/regression/tie-direction-broken.ly [new file with mode: 0644]
lily/align-interface.cc
lily/arpeggio.cc
lily/axis-group-interface.cc
lily/completion-note-heads-engraver.cc
lily/dynamic-align-engraver.cc [new file with mode: 0644]
lily/dynamic-engraver.cc
lily/engraver.cc
lily/figured-bass-engraver.cc
lily/global-context-scheme.cc
lily/grob.cc
lily/hairpin.cc
lily/include/arpeggio.hh
lily/include/lily-proto.hh
lily/include/prob.hh
lily/include/skyline-pair.hh [new file with mode: 0644]
lily/include/skyline.hh
lily/include/spanner.hh
lily/include/tie-details.hh
lily/lyric-combine-music-iterator.cc
lily/new-dynamic-engraver.cc [new file with mode: 0644]
lily/paper-column.cc
lily/paper-system-scheme.cc [new file with mode: 0644]
lily/prob-scheme.cc
lily/separation-item.cc
lily/skyline-pair.cc [new file with mode: 0644]
lily/skyline.cc
lily/spacing-interface.cc
lily/spacing-spanner.cc
lily/system.cc
lily/tie-details.cc
lily/tie-formatting-problem.cc
lily/tie.cc
ly/engraver-init.ly
ly/spanners-init.ly
scm/define-context-properties.scm
scm/define-grobs.scm
scm/define-markup-commands.scm
scm/document-markup.scm
scm/music-functions.scm
scripts/lilypond-book.py

index c03e68de01e5716f705f7a7a9426d5e64a6fc8c5..1d04699985e3522917ae646150f1378854e911f3 100644 (file)
@@ -65,6 +65,17 @@ which scares away people.
 
 @end ignore
 
+@item
+Arpeggios may now use ``parenthesis'' style brackets:
+
+@lilypond[relative,ragged-right]
+  \override Arpeggio #'stencil = #ly:arpeggio::brew-chord-slur
+
+  % Note: does not work for cross staff arpeggios.
+  \override Arpeggio #'X-extent = #ly:grob::stencil-width
+  <c g' c>2\arpeggio ~ c
+@end lilypond
+
 @item
 Enclosing text within boxes with rounded corners is now possible,
 using the @code{rounded-box} command.
index 51ab75c3fa5e8a33763506e3e3670f03c228965a..77b4d49346306a5e63ab3fa2524ca52b9dd506b8 100644 (file)
@@ -18,10 +18,10 @@ concepts and techniques required to produce equally beautiful
 but more complex scores.
 
 @menu
-* How LilyPond input files work::     
-* Voices contain music::        
-* Contexts and engravers::      
-* Extending the templates::     
+* How LilyPond input files work::
+* Voices contain music::
+* Contexts and engravers::
+* Extending the templates::
 @end menu
 
 
@@ -45,6 +45,9 @@ description of the input format, see @ruser{File structure}.
 @node Introduction to the LilyPond file structure
 @subsection Introduction to the LilyPond file structure
 
+@cindex input format
+@cindex file structure
+
 A basic example of a LilyPond input file is
 
 @example
@@ -61,6 +64,11 @@ A basic example of a LilyPond input file is
 There are many variations of this basic pattern, but this
 example serves as a useful starting place.
 
+@funindex \book
+@funindex \score
+@cindex book
+@cindex score
+
 Up to this point none of the examples you have seen has used a
 @code{\score@{@}} command.  This is because LilyPond automatically
 adds the extra commands which are needed when you give it simple
@@ -94,6 +102,8 @@ In other words, if the input contains a single music expression,
 LilyPond will interpret the file as though the music expression
 was wrapped up inside the commands shown above.
 
+@cindex implicit contexts
+
 @strong{A word of warning!}  Many of the examples in the LilyPond
 documentation will omit the @code{\new Staff} and @code{\new Voice}
 commands, leaving them to be created implicitly.  For simple
@@ -136,6 +146,13 @@ things, such as
 @}
 @end example
 
+@funindex \header
+@funindex \layout
+@funindex \midi
+@cindex header
+@cindex layout
+@cindex midi
+
 @noindent
 Note that these three commands -- @code{\header}, @code{\layout}
 and @code{\midi} -- are special: unlike all other commands which
@@ -155,6 +172,8 @@ MIDI output respectively.  They are described fully in the
 Notation Reference -- @ruser{Score layout} and
 @ruser{Creating MIDI files}.
 
+@cindex scores, multiple
+
 You may code multiple @code{\score} blocks.  Each will be
 treated as a separate score, but they will be all combined into
 a single output file.  A @code{\book} command is not necessary
@@ -204,14 +223,14 @@ melody = \relative c' @{
 When LilyPond looks at this file, it takes the value of
 @code{melody} (everything after the equals sign) and inserts it
 whenever it sees @code{\melody}.  There's nothing special about
-the names -- it could be @code{melody}, @code{global}, 
+the names -- it could be @code{melody}, @code{global},
 @code{TimeKey},
 @code{pianorighthand}, or @code{foofoobarbaz}.  For more details,
 see @ref{Saving typing with variables and functions}.
 Remember that you can use almost any name you like as long
 as it contains just alphabetic characters and is distinct from
 LilyPond command names.  The exact
-limitations on variable names are detailed in 
+limitations on variable names are detailed in
 @ruser{File structure}.
 
 
@@ -224,6 +243,8 @@ For a complete definition of the input format, see
 @node Score is a (single) compound musical expression
 @subsection Score is a (single) compound musical expression
 
+@funindex \score
+@cindex score
 @cindex Compound music expression
 @cindex Music expression, compound
 
@@ -260,7 +281,7 @@ music expression and work our way down.
 A whole Wagner opera would easily double the length of this
 manual, so let's just add a singer and piano.  We don't need a
 @code{GrandStaff} for this ensemble, which simply groups a number
-of staves together with a brace at the left, so we shall remove 
+of staves together with a brace at the left, so we shall remove
 it.  We @emph{do} need a singer and a piano, though.
 
 @example
@@ -281,7 +302,7 @@ music.  And we definitely want to show the vocal part and piano
 part at the same time, not one after the other!  However, the
 @code{<< ... >>} construct is not really necessary for the Singer
 staff, as it contains only one music expression, but Staves often
-do require simultaneous Voices within them, so using 
+do require simultaneous Voices within them, so using
 @code{<< ... >>}
 rather than braces is a good habit to adopt. We'll add some real
 music later; for now let's just put in some dummy notes and lyrics.
@@ -321,7 +342,7 @@ braces next to @code{\new Voice = vocal}, we could start writing
 But if we did that, the @code{\score} section would get pretty
 long, and it would be harder to understand what was happening.  So
 let's use variables instead.  These were introduced at the end
-of the previous section, remember?  So, adding a few notes, we 
+of the previous section, remember?  So, adding a few notes, we
 now have a piece of real music:
 
 @lilypond[verbatim,quote,ragged-right]
@@ -365,9 +386,12 @@ on the same horizontal position in your text editor.
 @node Nesting music expressions
 @subsection Nesting music expressions
 
-It is not essential to declare all staves at the beginning; 
+@cindex staves, temporary
+@cindex ossias
+
+It is not essential to declare all staves at the beginning;
 they may be introduced temporarily at any point.  This is
-particularly useful for creating ossia sections 
+particularly useful for creating ossia sections
 (see @rglos{ossia}).  Here is a simple example showing how
 to introduce a new staff temporarily for the duration of
 three notes:
@@ -376,7 +400,7 @@ three notes:
 \new Staff {
   \relative g' {
     r4 g8 g c4 c8 d |
-    e4 r8 
+    e4 r8
     <<
       { f c c }
       \new Staff {
@@ -394,6 +418,8 @@ following a clef change -- slightly smaller than the clef
 at the beginning of the line.  This is usual for clefs printed
 in the middle of a line.
 
+@cindex staff, positioning
+
 The ossia section may be placed above the staff
 as follows:
 
@@ -413,10 +439,10 @@ as follows:
 }
 @end lilypond
 
-This example uses @code{\with}, which will be explained more 
+This example uses @code{\with}, which will be explained more
 fully later.  It is a means of modifying the default behavior
-of a single Staff.  Here it says that the new staff should be 
-placed above the staff called @qq{main} instead of the default 
+of a single Staff.  Here it says that the new staff should be
+placed above the staff called @qq{main} instead of the default
 position which is below.
 
 Ossia are often written without clef and without
@@ -427,9 +453,11 @@ have not yet been introduced.  See @ref{Size of objects}
 @node On the un-nestedness of brackets and ties
 @subsection On the un-nestedness of brackets and ties
 
+@cindex brackets, nesting
+
 You have already met a number of different types of bracket in
 writing the input file to LilyPond.  These obey different rules
-which can be confusing at first.  Before we explain the rules 
+which can be confusing at first.  Before we explain the rules
 let's first review the different types of bracket.
 
 @c attempt to force this onto a new page
@@ -501,14 +529,14 @@ two tuplets, and a phrasing slur extending out of a tuplet
 @section Voices contain music
 
 Singers need voices to sing, and so does LilyPond.
-The actual music for all instruments in a score 
-is contained in Voices -- the most fundamental 
+The actual music for all instruments in a score
+is contained in Voices -- the most fundamental
 of all LilyPond's concepts.
 
 @menu
-* I'm hearing Voices::          
-* Explicitly instantiating voices::  
-* Voices and vocals::           
+* I'm hearing Voices::
+* Explicitly instantiating voices::
+* Voices and vocals::
 @end menu
 
 @node I'm hearing Voices
@@ -516,23 +544,27 @@ of all LilyPond's concepts.
 
 @cindex polyphony
 @cindex layers
+@cindex multiple voices
 @cindex Voice context
+@cindex context, Voice
+@cindex simultaneous music
+@cindex concurrent music
 
-The lowest, most fundamental or innermost layers in a LilyPond 
+The lowest, most fundamental or innermost layers in a LilyPond
 score are called @q{Voice contexts} or just @q{Voices} for short.
-Voices are sometimes called @q{layers} in other notation 
+Voices are sometimes called @q{layers} in other notation
 packages.
 
 In fact, a Voice layer or context is the only one which can
 contain music.  If a Voice context is not explicitly declared
 one is created automatically, as we saw at the beginning of
-this chapter.  Some instruments such as an 
+this chapter.  Some instruments such as an
 Oboe can play only one note at a time.  Music written for
 such instruments is monophonic and requires just a single
 voice.  Instruments which can play more than one note at a
 time like the piano will often require multiple voices to
 encode the different concurrent notes and rhythms they are
-capable of playing.  
+capable of playing.
 
 A single voice can contain many notes in a chord, of course,
 so when exactly are multiple voices needed?  Look first at
@@ -543,8 +575,8 @@ this example of four chords:
 <d g>4 <d fis> <d a'> <d g>
 @end lilypond
 
-This can be expressed using just the single angle bracket chord 
-symbols, @code{< ... >}, and for this just a single voice is 
+This can be expressed using just the single angle bracket chord
+symbols, @code{< ... >}, and for this just a single voice is
 needed.  But suppose the F-sharp were actually an eighth-note
 followed by an eighth-note G, a passing note on the way to the A?
 Now we have two notes which start at the same time but have
@@ -568,7 +600,7 @@ The fragments must also be separated with double backward slashes,
 notes would be entered into a single voice, which would usually
 cause errors.  This technique is particularly suited to pieces of
 music which are largely monophonic with occasional short sections
-of polyphony.  
+of polyphony.
 
 Here's how we split the chords above into two voices and add both
 the passing note and a slur:
@@ -675,6 +707,8 @@ blue triangle voice.
 }
 @end lilypond
 
+@funindex \voiceXXXStyle
+
 The commands @code{\voiceXXXStyle} are mainly intended for use in
 educational documents such as this one.  They modify the color
 of the note head, the stem and the beams, and the style of the
@@ -683,8 +717,8 @@ Voice one is set to red diamonds, voice two to blue triangles,
 voice three to green crossed circles, and voice four (not used
 here) to magenta crosses.  We shall see later how commands like
 these may be created by the user.
-See @ref{Visibility and color of objects}
-TODO Add link to using variables for tweaks
+See @ref{Visibility and color of objects} and
+@ref{Using variables for tweaks}.
 
 Polyphony does not change the relationship of notes within a
 @code{\relative @{ @}} block.  Each note is still calculated
@@ -716,7 +750,7 @@ command at the start of each voice:
 \relative c' @{ noteE ... @}
 @end example
 
-Let us finally analyze the voices in a more complex piece of 
+Let us finally analyze the voices in a more complex piece of
 music.  Here are
 the notes from the first two bars of the second of Chopin's
 Deux Nocturnes, Op 32.  This example will be used at later
@@ -778,11 +812,11 @@ not understand.
   <<
     { % Voice one
       \voiceOneStyle
-      c2 aes4. bes8 
+      c2 aes4. bes8
     }
   \\  % Voice two
     { \voiceTwoStyle
-      aes2 f4 fes 
+      aes2 f4 fes
     }
   \\  % No Voice three (we want stems down)
   \\  % Voice four
@@ -791,7 +825,7 @@ not understand.
       \once \override NoteColumn #'force-hshift = #0
       <ees c>2
       \once \override NoteColumn #'force-hshift = #0.5
-      des2 
+      des2
     }
   >> |
   <c ees aes c>1 |
@@ -840,8 +874,8 @@ and placing the music in voice four:
 @end lilypond
 
 @noindent
-We see that this fixes the stem direction, but exposes a 
-problem sometimes encountered with multiple voices -- the 
+We see that this fixes the stem direction, but exposes a
+problem sometimes encountered with multiple voices -- the
 stems of the notes in one voice can collide with the note heads
 in other voices.  In laying out the notes, LilyPond allows the
 notes or chords from two voices to occupy the same vertical
@@ -853,7 +887,7 @@ notes of the lowest voice are clearly not well placed by default.
 LilyPond provides several ways to adjust the horizontal placing
 of notes.  We are not quite ready yet to see how to correct this,
 so we shall leave this problem until a later section
-(see the force-hshift property in @ref{Fixing overlapping 
+(see the force-hshift property in @ref{Fixing overlapping
 notation} )
 
 @node Explicitly instantiating voices
@@ -863,6 +897,8 @@ notation} )
 @funindex \voiceTwo
 @funindex \voiceThree
 @funindex \voiceFour
+@funindex \new Voice
+@cindex Voice contexts, creating
 
 Voice contexts can also be created manually
 inside a @code{<< >>} block to create polyphonic music, using
@@ -883,7 +919,7 @@ the previous section:
 @end example
 
 @noindent
-is equivalent to 
+is equivalent to
 
 @example
 \new Staff <<
@@ -907,11 +943,11 @@ ties, articulations, text annotations, augmentation dots of dotted
 notes, and fingerings.  @code{\voiceOne} and @code{\voiceThree}
 make these objects point upwards, while @code{\voiceTwo} and
 @code{\voiceFour} make them point downwards.  These commands also
-generate a horizontal shift for each voice when this is required 
-to avoid clashes of note heads.  The command @code{\oneVoice} 
+generate a horizontal shift for each voice when this is required
+to avoid clashes of note heads.  The command @code{\oneVoice}
 reverts the settings back to the normal values for a single voice.
 
-Let us see in some simple examples exactly what effect 
+Let us see in some simple examples exactly what effect
 @code{\oneVoice}, @code{\voiceOne} and @code{voiceTwo} have on
 markup, ties, slurs, and dynamics:
 
@@ -976,6 +1012,9 @@ permitting a phrasing slur to be drawn over them.
 @cindex nesting music expressions
 @cindex nesting simultaneous constructs
 
+@cindex voices, temporary
+@cindex voices, nesting
+
 More deeply nested polyphony constructs are possible, and if a
 voice appears only briefly this might be a more natural way to
 typeset the music.
@@ -1000,6 +1039,7 @@ typeset the music.
 }
 @end lilypond
 
+@cindex spacing notes
 
 This method of nesting new voices briefly is useful
 when only small sections of the music
@@ -1074,6 +1114,11 @@ have no shift or the same shift specified, the error message
 Vocal music presents a special difficulty: we need to combine two
 expressions -- notes and lyrics.
 
+@funindex \new Lyrics
+@funindex \lyricsto
+@cindex Lyrics context, creating
+@cindex lyrics, linking to voice
+
 You have already seen the @code{\addlyrics@{@}} command, which
 handles simple scores well.  However, this technique is
 quite limited.  For more complex music, you must introduce the
@@ -1095,17 +1140,25 @@ name assigned to the Voice.
 >>
 @end lilypond
 
-Note that the lyrics must be linked to a @code{Voice} context, 
-@emph{not} a @code{Staff} context.  This is a case where it is 
+Note that the lyrics must be linked to a @code{Voice} context,
+@emph{not} a @code{Staff} context.  This is a case where it is
 necessary to create @code{Staff} and @code{Voice} contexts
 explicitly.
 
+@cindex lyrics and beaming
+@cindex beaming and lyrics
+@funindex \autoBeamOff
+
 The automatic beaming which LilyPond uses by default works well
 for instrumental music, but not so well for music with lyrics,
 where beaming is either not required at all or is used to indicate
 melismata in the lyrics.  In the example above we use the command
 @code{\autoBeamOff} to turn off the automatic beaming.
 
+@funindex \new ChoirStaff
+@funindex \lyricmode
+@cindex vocal score structure
+
 Let us reuse the earlier example from Judas Maccabæus to
 illustrate this more flexible technique.  We first recast
 it to use variables so the music and lyrics can be separated
@@ -1155,6 +1208,8 @@ more verses may be added to the lyrics,
 and the variables containing the music can easily be placed
 in separate files should they become too long.
 
+@cindex hymn structure
+
 Here is a example of the first line of a hymn with four
 verses, set for SATB.  In this case the words for all four
 parts are the same.
@@ -1194,6 +1249,8 @@ VerseFour  = \lyricmode {
 }
 @end lilypond
 
+@cindex verse and refrain
+
 We end with an example to show how we might code a solo verse which
 continues into a two-part refrain in two staves.  The
 positioning of the sequential and simultaneous sections to achieve
@@ -1401,6 +1458,8 @@ in the fine-tuning of LilyPond output.
 @node Contexts explained
 @subsection Contexts explained
 
+@cindex contexts explained
+
 When music is printed, many notational elements which do not
 appear explicitly in the input file must be added to the
 output.  For example, compare the input and output of the
@@ -1471,6 +1530,11 @@ preceding word with no hyphen or underscore, e.g.,
 @node Creating contexts
 @subsection Creating contexts
 
+@funindex \new
+@cindex new contexts
+@cindex creating contexts
+@cindex contexts, creating
+
 There can be only one top level context: the
 @code{Score}
 context.  This is created with the @code{\score} command,
@@ -1483,10 +1547,6 @@ necessary to create them by hand.
 The simplest command that does this is @code{\new}.
 It is prepended to a music expression, for example
 
-@funindex \new
-@cindex new contexts
-@cindex Context, creating
-
 @example
 \new @var{type} @var{music-expression}
 @end example
@@ -1500,6 +1560,9 @@ Note that there is no @code{\new Score} command;
 the single top-level @code{Score} context is introduced
 with @code{\score}.
 
+@cindex contexts, naming
+@cindex naming contexts
+
 The @code{\new} command may also give a identifying name to the
 context to distinguish it from other contexts of the same type,
 
@@ -1556,8 +1619,8 @@ lines of the staff, the @code{Clef_engraver} determines and sets
 the pitch reference point on the staff by drawing a clef symbol.
 
 Here are some of the most common engravers together with their
-function.  You will see it is easy to guess the function from
-the name, or vice versa.
+function.  You will see it is usually easy to guess the function
+from the name, or vice versa.
 
 @multitable @columnfractions .3 .7
 @headitem Engraver
@@ -1594,12 +1657,14 @@ the name, or vice versa.
 
 We shall see later how the output of LilyPond can be changed
 by modifying the action of Engravers.
-  
+
 
 @node Modifying context properties
 @subsection Modifying context properties
 
 @cindex context properties
+@cindex context properties, modifying
+@cindex modifying context properties
 @funindex \set
 @funindex \unset
 
@@ -1778,7 +1843,7 @@ a b
 @end lilypond
 
 We have now seen how to set the values of several different
-types of property.  Note that integers and numbers are alway
+types of property.  Note that integers and numbers are always
 preceded by a hash sign, @code{#}, while a true or false value
 is specified by ##t and ##f, with two hash signs.  A text
 property should be enclosed in double quotation signs, as above,
@@ -1788,6 +1853,7 @@ in a much more general way by using the very powerful
 
 
 @funindex \with
+@cindex context properties, setting with \with
 
 Context properties may also be set at the time the context is
 created.  Sometimes this is a clearer way of specifying a
@@ -1830,8 +1896,8 @@ this new default value may be restored with the
 @node Adding and removing engravers
 @subsection Adding and removing engravers
 
-@cindex Engravers, adding
-@cindex Engravers, removing
+@cindex engravers, adding
+@cindex engravers, removing
 
 @funindex \consists
 @funindex \remove
@@ -1912,9 +1978,9 @@ the notes in all the voices on that staff:
   }
   <<
   \new Voice
-  \relative c'' { 
+  \relative c'' {
     \voiceOne
-    c a b g 
+    c a b g
   }
   \new Voice
   \relative c' {
@@ -1926,8 +1992,10 @@ the notes in all the voices on that staff:
 
 @subsubheading Changing all contexts of the same type
 
+@funindex \layout
+
 The examples above show how to remove or add engravers to
-individual contexts.  It is also possible to remove or add 
+individual contexts.  It is also possible to remove or add
 engravers to every context of a specific type by placing the
 commands in the appropriate context in a @code{\layout}
 block.  For example, if we wanted to show an ambitus for every
@@ -1961,7 +2029,7 @@ staff in a four-staff score we could write
 @end lilypond
 
 @noindent
-The default values of context properties may also be set
+The values of context properties may also be set
 for all contexts of a particular type by including the
 @code{\set} command in a @code{\context} block in the
 same way.
@@ -1969,24 +2037,26 @@ same way.
 @node Extending the templates
 @section Extending the templates
 
-You've read the tutorial, you know how to write music, you 
+You've read the tutorial, you know how to write music, you
 understand the fundamental concepts.  But how can you
-get the staves that you want?  Well, you can find lots of 
-templates (see @ref{Templates}) which may give you a start.  
+get the staves that you want?  Well, you can find lots of
+templates (see @ref{Templates}) which may give you a start.
 But what
 if you want something that isn't covered there?  Read on.
 
 TODO Add links to templates after they have been moved to LSR
 
 @menu
-* Soprano and cello::           
-* Four-part SATB vocal score::  
-* Building a score from scratch::  
+* Soprano and cello::
+* Four-part SATB vocal score::
+* Building a score from scratch::
 @end menu
 
 @node Soprano and cello
 @subsection Soprano and cello
 
+@cindex template, modifying
+
 Start off with the template that seems closest to what you want to end
 up with.  Let's say that you want to write something for soprano and
 cello.  In this case, we would start with @q{Notes and lyrics} (for the
@@ -2036,16 +2106,16 @@ melody = \relative c' @{
 @}
 @end example
 
-We don't need two @code{\version} commands.  We'll need the 
+We don't need two @code{\version} commands.  We'll need the
 @code{melody} section.  We don't want two @code{\score} sections
 -- if we had two @code{\score}s, we'd get the two parts separately.
-We want them together, as a duet.  Within the @code{\score} 
+We want them together, as a duet.  Within the @code{\score}
 section, we don't need two @code{\layout} or @code{\midi}.
 
-If we simply cut and paste the @code{melody} section, we would 
+If we simply cut and paste the @code{melody} section, we would
 end up with two @code{melody} definitions.  This would not generate
 an error, but the second one would be used for both melodies.
-So let's rename them to make them distinct.  We'll call the 
+So let's rename them to make them distinct.  We'll call the
 section for the soprano @code{sopranoMusic} and the section for
 the cello @code{celloMusic}.  While we're doing this, let's rename
 @code{text} to be @code{sopranoLyrics}.  Remember to rename both
@@ -2053,8 +2123,8 @@ instances of all these names -- both the initial definition (the
 @code{melody = \relative c' @{ } part) and the name's use (in the
 @code{\score} section).
 
-While we're doing this, let's change the cello part's staff -- 
-celli normally use bass clef.  We'll also give the cello some 
+While we're doing this, let's change the cello part's staff --
+celli normally use bass clef.  We'll also give the cello some
 different notes.
 
 @example
@@ -2101,7 +2171,7 @@ want the cello part to appear under the soprano part, we need to add
 @noindent
 underneath the soprano stuff.  We also need to add @code{<<} and
 @code{>>} around the music -- that tells LilyPond that there's
-more than one thing (in this case, two @code{Staves}) happening 
+more than one thing (in this case, two @code{Staves}) happening
 at once.  The @code{\score} looks like this now
 
 @c Indentation in this example is deliberately poor
@@ -2165,6 +2235,9 @@ celloMusic = \relative c {
 @node Four-part SATB vocal score
 @subsection Four-part SATB vocal score
 
+@cindex template, SATB
+@cindex SATB template
+
 Most vocal scores of music written for four-part mixed choir
 with orchestral accompaniment such as Mendelssohn's Elijah or
 Handel's Messiah have the choral music and words on four
@@ -2255,7 +2328,7 @@ the vocal parts are fine, but we shall need to add variables for
 the piano reduction.
 
 The order in which the contexts appear in the ChoirStaff of
-the template do not correspond with the order in the vocal 
+the template do not correspond with the order in the vocal
 score shown above.  We need to rearrange them so there are
 four staves with the words written directly underneath the
 notes for each part.
@@ -2263,7 +2336,7 @@ All the voices should be @code{\voiceOne}, which is
 the default, so the @code{\voiceXXX} commands should be removed.
 We also need to specify the tenor clef for the tenors.
 The way in which lyrics are specified in the template has not yet
-been encountered so we need to use the method with which we are 
+been encountered so we need to use the method with which we are
 familiar.  We should also add the names of each staff.
 
 Doing this gives for our ChoirStaff:
@@ -2313,7 +2386,7 @@ using angle brackets as we want them to be
 stacked one above the other:
 
 @example
-<<  % combine ChoirStaff and PianoStaff one above the other 
+<<  % combine ChoirStaff and PianoStaff one above the other
   \new ChoirStaff <<
     \new Staff = "sopranos" <<
       \new Voice = "sopranos" @{ \global \sopMusic @}
@@ -2418,16 +2491,18 @@ lower = \relative c, {
   >>
 }
 @end lilypond
-  
+
 
 @node Building a score from scratch
 @subsection Building a score from scratch
 
+@cindex template, writing your own
+
 After gaining some facility with writing LilyPond code you
 may find that it is easier to build a score from scratch
 rather than modifying one of the templates.  You can also
 develop your own style this way to suit the sort of music you
-like.  Let's see how to put together the score for an organ 
+like.  Let's see how to put together the score for an organ
 prelude as an example.
 
 We begin with a header section.  Here go the title, name
@@ -2487,7 +2562,7 @@ Next we need to add a staff for the pedal organ.
 This goes underneath the PianoStaff, but it must
 be simultaneous with it, so we need angle brackets
 round the two.  Missing these out would generate
-an error in the log file.  It's a common mistake 
+an error in the log file.  It's a common mistake
 which you'll make sooner or later!  Try copying
 the final example at the end of this section,
 remove these angle brackets, and compile it to
@@ -2511,10 +2586,13 @@ see what errors it generates.
 @end example
 
 It is not strictly necessary to use the simultaneous construct
-@code{<<  >>} for the manual two staff and the pedal organ staff,
+@code{<< .. >>} for the manual two staff and the pedal organ staff,
 since they contain only one music expression, but it does no harm
 and always using angle brackets after @code{\new Staff} is a good
-habit to cultivate in case there are multiple voices.  
+habit to cultivate in case there are multiple voices.  The opposite
+is true for Voices: these should habitually be followed by braces
+@code{@{ .. @}} in case your music is coded in several variables
+which need to run consecutively.
 
 Let's add this structure to the score block, and adjust the
 indenting.  We also add the appropriate clefs, ensure the
@@ -2549,7 +2627,7 @@ predefined variable, @code{\TimeKey}.
 
 That completes the structure.  Any three-staff organ music
 will have a similar structure, although the number of voices
-may vary.  All that remains now 
+may vary.  All that remains now
 is to add the music, and combine all the parts together.
 
 @lilypond[quote,verbatim,ragged-right,addversion]
index cfbae202ec7978384293bde034fb830758e1e5c3..4478c0d6cb8a93af87c00d25043989c9e3456a8f 100644 (file)
@@ -618,6 +618,10 @@ Set the amount by which the @code{quote} option indents a music snippet.
 Use relative octave mode.  By default, notes are specified relative to
 middle@tie{}C.  The optional integer argument specifies the octave of
 the starting note, where the default @code{1} is middle C.
+@code{relative} option only works when @code{fragment} option is set,
+so @code{fragment} is automatically implied by @code{relative},
+regardless of the presence of any @code{(no)fragment} option in the
+source.
 @end table
 
 LilyPond also uses @command{lilypond-book} to produce its own
diff --git a/VERSION b/VERSION
index d9dd0f5dede2b4b25cd0731672ec3d5c1da3941a..e792adf6371e53c4bc2f6fceaa9cae968203558f 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1,6 +1,6 @@
 PACKAGE_NAME=LilyPond
 MAJOR_VERSION=2
 MINOR_VERSION=11
-PATCH_LEVEL=45
+PATCH_LEVEL=46
 MY_PATCH_LEVEL=
 
index e687acf2d7a0d7026a430589ae2f795922542f78..47c4847c4048825f0d65904a0431a2e861779410 100644 (file)
@@ -40,7 +40,11 @@ struct Drul_array
   Drul_array ()
   {
   }
-  Drul_array (T t1, T t2)
+  Drul_array (T const &t1, T const &t2)
+  {
+    set (t1, t2);
+  }
+  void set (T const &t1, T const &t2)
   {
     array_[0] = t1;
     array_[1] = t2;
diff --git a/input/regression/arpeggio-parenthesis.ly b/input/regression/arpeggio-parenthesis.ly
new file mode 100644 (file)
index 0000000..b666015
--- /dev/null
@@ -0,0 +1,17 @@
+
+\header {
+
+  texidoc = "There is a variant of the arpeggio sign that uses a
+  `vertical slur' instead of the wiggle."
+
+}
+
+\version "2.11.46"
+
+\relative c' {
+  \override Arpeggio #'stencil = #ly:arpeggio::brew-chord-slur
+
+  % Note: does not work for cross staff arpeggios.
+  \override Arpeggio #'X-extent = #ly:grob::stencil-width
+  <c g' c>2\arpeggio ~ c
+}
diff --git a/input/regression/completion-heads-lyrics.ly b/input/regression/completion-heads-lyrics.ly
new file mode 100644 (file)
index 0000000..0df5fcd
--- /dev/null
@@ -0,0 +1,25 @@
+\header {
+  texidoc = "You can put lyrics under completion heads."
+}
+\version "2.11.45"
+
+mel = \relative c'' {
+ c1. c1.
+}
+
+lyr = \lyricmode {
+ One  two
+}
+
+\score {
+ \new Score <<
+   \new Staff <<
+     \new Voice = "completion" \with {
+       \remove "Note_heads_engraver"
+       \remove "Forbid_line_break_engraver"
+       \consists "Completion_heads_engraver"
+     } \mel
+   >>
+   \new Lyrics \lyricsto "completion" \lyr
+ >>
+}
diff --git a/input/regression/tie-direction-broken.ly b/input/regression/tie-direction-broken.ly
new file mode 100644 (file)
index 0000000..895f87f
--- /dev/null
@@ -0,0 +1,21 @@
+
+\version "2.11.45"
+
+\header {
+
+  texidoc = "In the single tie case, broken ties peek across line
+  boundaries to determine which direction to take."
+
+}
+
+
+\paper {
+  ragged-right = ##t
+}
+
+\relative c'' {
+ bes1~ \break
+ bes2.
+ \stemUp bes4 ~ \break
+ bes1 
+}
index daffa298fb1226d7c029034a81fa61aab3b2ebea..057e233f443d6522ddf4bddc5d74b7a515881dde 100644 (file)
@@ -7,16 +7,17 @@
 */
 
 #include "align-interface.hh"
-#include "spanner.hh"
-#include "item.hh"
 #include "axis-group-interface.hh"
-#include "pointer-group-interface.hh"
-#include "hara-kiri-group-spanner.hh"
 #include "grob-array.hh"
+#include "hara-kiri-group-spanner.hh"
 #include "international.hh"
+#include "item.hh"
+#include "paper-column.hh"
+#include "pointer-group-interface.hh"
+#include "spanner.hh"
+#include "skyline-pair.hh"
 #include "system.hh"
 #include "warn.hh"
-#include "paper-column.hh"
 
 /*
   TODO: for vertical spacing, should also include a rod & spring
index fe7b116821778f883f5b028d9a3717d50dbdf35f..80858426bc6eb43bc7f12e2f77a83aec4351d8b3 100644 (file)
@@ -8,15 +8,16 @@
 
 #include "arpeggio.hh"
 
+#include "bezier.hh"
+#include "font-interface.hh"
 #include "grob.hh"
+#include "lookup.hh"
 #include "output-def.hh"
-#include "stem.hh"
+#include "pointer-group-interface.hh"
 #include "staff-symbol-referencer.hh"
 #include "staff-symbol.hh"
+#include "stem.hh"
 #include "warn.hh"
-#include "font-interface.hh"
-#include "lookup.hh"
-#include "pointer-group-interface.hh"
 
 Grob *
 Arpeggio::get_common_y (Grob *me)
@@ -136,6 +137,28 @@ Arpeggio::brew_chord_bracket (SCM smob)
   return mol.smobbed_copy ();
 }
 
+MAKE_SCHEME_CALLBACK (Arpeggio, brew_chord_slur, 1);
+SCM
+Arpeggio::brew_chord_slur (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  Interval heads = robust_scm2interval (me->get_property ("positions"),
+                                       Interval())
+    * Staff_symbol_referencer::staff_space (me);
+
+  Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
+  Real dy = heads.length ();
+
+  Real height_limit = 1.5;
+  Real ratio = .33;
+  Bezier curve = slur_shape (dy, height_limit, ratio);
+  curve.rotate (M_PI / 2);
+
+  Stencil mol (Lookup::slur (curve, lt, lt));
+  mol.translate_axis (heads[LEFT], Y_AXIS);
+  return mol.smobbed_copy ();
+}
+
 /*
   We have to do a callback, because print () triggers a
   vertical alignment if it is cross-staff.
index 121b0ba1596e0736fddb246db07ef2b502083db6..044a392851df4ee626f48e6852b655e6762cd4a3 100644 (file)
@@ -18,6 +18,7 @@
 #include "paper-column.hh"
 #include "paper-score.hh"
 #include "separation-item.hh"
+#include "skyline-pair.hh"
 #include "stencil.hh"
 #include "system.hh"
 #include "warn.hh"
@@ -629,7 +630,6 @@ Axis_group_interface::calc_max_stretch (SCM smob)
   return scm_from_double (ret);
 }
 
-extern bool debug_skylines;
 MAKE_SCHEME_CALLBACK (Axis_group_interface, print, 1)
 SCM
 Axis_group_interface::print (SCM smob)
@@ -641,8 +641,10 @@ Axis_group_interface::print (SCM smob)
   Stencil ret;
   if (Skyline_pair *s = Skyline_pair::unsmob (me->get_property ("vertical-skylines")))
     {
-      ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[UP].to_points (X_AXIS)).in_color (255, 0, 255));
-      ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[DOWN].to_points (X_AXIS)).in_color (0, 255, 255));
+      ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[UP].to_points (X_AXIS))
+                      .in_color (255, 0, 255));
+      ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[DOWN].to_points (X_AXIS))
+                      .in_color (0, 255, 255));
     }
   return ret.smobbed_copy ();
 }
index a83c961727578ab5951a96d73e997ac83a369170..8734b861c2a2d15eadb9b7367b508da6200619fa 100644 (file)
@@ -166,6 +166,7 @@ Completion_heads_engraver::process_music ()
 
       event->set_property ("pitch", pits);
       event->set_property ("duration", note_dur.smobbed_copy ());
+      event->set_property ("length", Moment (note_dur.get_length ()).smobbed_copy ());
       event->set_property ("duration-log", scm_from_int (note_dur.duration_log ()));
 
       Item *note = make_note_head (event);
@@ -187,9 +188,8 @@ Completion_heads_engraver::process_music ()
     }
 
   left_to_do_ -= note_dur.get_length ();
-
   if (left_to_do_)
-    get_global_context ()->add_moment_to_process (now.main_part_ + left_to_do_);
+    get_global_context ()->add_moment_to_process (now.main_part_ + note_dur.get_length());
   /*
     don't do complicated arithmetic with grace notes.
   */
@@ -217,6 +217,8 @@ Completion_heads_engraver::start_translation_timestep ()
       note_events_.clear ();
       prev_notes_.clear ();
     }
+  context ()->set_property ("completionBusy",
+                           ly_bool2scm (note_events_.size ()));
 }
 
 Completion_heads_engraver::Completion_heads_engraver ()
@@ -240,5 +242,5 @@ ADD_TRANSLATOR (Completion_heads_engraver,
                "measureLength ",
 
                /* write */
-               ""
+               "completionBusy "
                );
diff --git a/lily/dynamic-align-engraver.cc b/lily/dynamic-align-engraver.cc
new file mode 100644 (file)
index 0000000..77feb08
--- /dev/null
@@ -0,0 +1,164 @@
+/* 
+  dynamic-align-engraver.cc -- implement Dynamic_align_engraver
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2008 Han-Wen Nienhuys <hanwen@lilypond.org>
+  
+*/
+
+#include <set>
+
+#include "engraver.hh"
+
+#include "axis-group-interface.hh"
+#include "directional-element-interface.hh"
+#include "item.hh"
+#include "side-position-interface.hh"
+#include "spanner.hh"
+#include "stream-event.hh"
+
+#include "translator.icc"
+
+class Dynamic_align_engraver : public Engraver
+{
+  TRANSLATOR_DECLARATIONS (Dynamic_align_engraver);
+  DECLARE_ACKNOWLEDGER (note_column);
+  DECLARE_ACKNOWLEDGER (dynamic);
+  DECLARE_END_ACKNOWLEDGER (dynamic);
+
+protected:
+  virtual void stop_translation_timestep ();
+
+private:
+  void create_line_spanner (Stream_event *cause);
+  Spanner* line_;
+
+  vector<Spanner*> ended_;
+  vector<Spanner*> started_;
+  vector<Grob*> scripts_;
+  vector<Grob*> support_;
+  
+  set<Spanner*> running_;
+};
+
+Dynamic_align_engraver::Dynamic_align_engraver ()
+{
+  line_ = 0;
+}
+
+ADD_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
+ADD_ACKNOWLEDGER (Dynamic_align_engraver, note_column);
+ADD_END_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
+
+void
+Dynamic_align_engraver::create_line_spanner (Stream_event* event)
+{
+  if (!line_)
+    line_ = make_spanner ("DynamicLineSpanner",
+                         event ? event->self_scm() : SCM_EOL);
+}
+
+void
+Dynamic_align_engraver::acknowledge_end_dynamic (Grob_info info)
+{
+  if (Spanner::has_interface(info.grob()))
+    ended_.push_back (info.spanner ());
+}
+
+void
+Dynamic_align_engraver::acknowledge_note_column (Grob_info info)
+{
+  support_.push_back (info.grob ());
+}
+
+void
+Dynamic_align_engraver::acknowledge_dynamic (Grob_info info)
+{
+  Stream_event *cause = info.event_cause ();
+  create_line_spanner (cause);
+  if (Spanner::has_interface(info.grob()))
+    started_.push_back (info.spanner ());
+  else if (info.item())
+    scripts_.push_back (info.item());
+  else
+    info.grob ()->programming_error ("Unknown dynamic grob.");
+
+  Axis_group_interface::add_element (line_, info.grob ());
+
+  if (cause)
+    {
+      if (Direction d = to_dir (cause->get_property ("direction")))
+       set_grob_direction (line_, d);
+    }
+}
+
+void
+Dynamic_align_engraver::stop_translation_timestep ()
+{
+  for (vsize i = 0; i < started_.size(); i++)
+    running_.insert (started_[i]);
+  for (vsize i = 0; i < ended_.size(); i++)
+    {
+      Spanner *sp = ended_[i];
+
+      set<Spanner*>::iterator it  = running_.find (sp);
+      if (it != running_.end())
+       running_.erase (it);
+      else
+       started_[i]->programming_error ("Lost track of this dynamic spanner.");
+    }
+
+  bool end = line_ && running_.empty ();
+  Direction d = LEFT;
+  do
+    {
+      if (line_
+         && ((d == LEFT && !line_->get_bound (LEFT))
+             || (end && d == RIGHT && !line_->get_bound (RIGHT))))
+       {
+         vector<Spanner*> const &spanners =
+           (d == LEFT) ? started_ : ended_;
+         
+         Grob *bound = 0;
+         if (scripts_.size())
+           bound = scripts_[0];
+         else if (spanners.size())
+           bound = spanners[0]->get_bound (d);
+         else
+           {
+             programming_error ("Started DynamicLineSpanner but have no left bound.");
+             bound = unsmob_grob (get_property ("currentMusicalColumn"));
+           }
+
+         line_->set_bound (d, bound);
+       }
+    }
+  while (flip (&d) != LEFT);
+
+  for (vsize i = 0; line_ && i < support_.size (); i++)
+    Side_position_interface::add_support (line_, support_[i]);
+
+  if (end) 
+    line_ = 0;
+
+  ended_.clear ();
+  started_.clear ();
+  scripts_.clear ();
+  support_.clear ();
+}
+
+
+ADD_TRANSLATOR (Dynamic_align_engraver,
+               /* doc */
+               "Align hairpins and dynamic texts on a horizontal line",
+
+               /* create */
+               "DynamicLineSpanner ",
+
+               /* read */
+               "currentMusicalColumn ",
+
+               /* write */
+               ""
+               );
index 2f66955d446317d3ad5682d633b992c579ee0c06..94057f0bde25ebe7ca50288758c73233d4c4f003 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "axis-group-interface.hh"
 #include "context.hh"
+#include "engraver.hh"
 #include "dimensions.hh"
 #include "directional-element-interface.hh"
 #include "engraver.hh"
@@ -253,7 +254,7 @@ Dynamic_engraver::process_music ()
              cresc_->set_property ("style", s);
              context ()->set_property ((start_type
                                         + "Spanner").c_str (), SCM_EOL);
-             s = get_property ((start_type + "Text").c_str ());
+             s = get_property ((start_type + "Text").c_str ());
              if (Text_interface::is_markup (s))
                {
                  cresc_->set_property ("text", s);
@@ -277,7 +278,6 @@ Dynamic_engraver::process_music ()
              cresc_->set_bound (LEFT, script_);
              add_bound_item (line_spanner_, cresc_->get_bound (LEFT));
            }
-
          Axis_group_interface::add_element (line_spanner_, cresc_);
        }
     }
index c749be110a169b2319d68059070dbb7f5f2bf1de..e9195564d79849deee822a51933b932948a720af 100644 (file)
@@ -70,7 +70,8 @@ Engraver::announce_end_grob (Grob *e, SCM cause)
     {
       cause = m->to_event ()->unprotect ();
     }
-  if (unsmob_stream_event (cause) || unsmob_grob (cause))
+  if (e->get_property ("cause") == SCM_EOL
+      && (unsmob_stream_event (cause) || unsmob_grob (cause)))
     e->set_property ("cause", cause);
 
   Grob_info i (this, e);
index 32ad86a9eb7592fa42c428ee857f4a6d8399802c..782574e5e6e97a491a977379d6f76a556e5199ec 100644 (file)
@@ -362,7 +362,8 @@ Figured_bass_engraver::process_music ()
            {
              if (!group.continuation_line_)
                {
-                 Spanner * line = make_spanner ("BassFigureContinuation", SCM_EOL);
+                 Spanner * line
+                   = make_spanner ("BassFigureContinuation", SCM_EOL);
                  Item * item = group.figure_item_;
                  group.continuation_line_ = line;
                  line->set_bound (LEFT, item);
@@ -412,7 +413,8 @@ Figured_bass_engraver::process_music ()
 void
 Figured_bass_engraver::create_grobs () 
 {
-  Grob *muscol = dynamic_cast<Item*> (unsmob_grob (get_property ("currentMusicalColumn")));
+  Grob *muscol
+    = dynamic_cast<Item*> (unsmob_grob (get_property ("currentMusicalColumn")));
   if (!alignment_)
     {
       alignment_ = make_spanner ("BassFigureAlignment", SCM_EOL);
index 8fbcc99b46eee93fee36d5a3c1d3952e300ebbdf..03c992303d7377885eada7c6625cfb4ac1dc9f16 100644 (file)
@@ -54,7 +54,7 @@ LY_DEFINE (ly_make_global_translator, "ly:make-global-translator",
 LY_DEFINE (ly_make_global_context, "ly:make-global-context",
           1, 0, 0, (SCM output_def),
           "Set up a global interpretation context, using the output"
-          " block @var{output_def}.  The context is returned.\n")
+          " block @var{output_def}.  The context is returned.")
 {
   LY_ASSERT_SMOB (Output_def, output_def, 1);
   Output_def *odef = unsmob_output_def (output_def); 
index 78be89e399f147c6cefb42428e7896bd204308c9..9479f17f41179cb3fbdc3cf6769fb533ffbbde9a 100644 (file)
@@ -722,14 +722,11 @@ common_refpoint_of_list (SCM elist, Grob *common, Axis a)
 Grob *
 common_refpoint_of_array (vector<Grob*> const &arr, Grob *common, Axis a)
 {
-  for (vsize i = arr.size (); i--;)
-    if (Grob *s = arr[i])
-      {
-       if (common)
-         common = common->common_refpoint (s, a);
-       else
-         common = s;
-      }
+  for (vsize i = 0; i < arr.size (); i++)
+    if (common)
+      common = common->common_refpoint (arr[i], a);
+    else
+      common = arr[i];
 
   return common;
 }
index 80f836d5b1ff89f74c0d84aab425183f8b899141..60366a0630fa7ee51dab702fe2444b6df12cb1f1 100644 (file)
@@ -47,7 +47,6 @@ Hairpin::consider_suicide (Spanner*me)
       && ly_is_equal (bounds[RIGHT]->get_column ()->get_property ("when"),
                      bounds[LEFT]->get_property ("when")))
     me->suicide ();
-  
 }
 
 MAKE_SCHEME_CALLBACK (Hairpin, print, 1);
@@ -207,7 +206,6 @@ Hairpin::print (SCM smob)
   /*
     should do relative to staff-symbol staff-space?
   */
-
   Stencil mol;
   Real x = 0.0;
 
index 7db201bb0004f5fba9b6e7373a2125a04036d82c..373045bfca740cbf80023aad6c64a5a55e4e59f6 100644 (file)
@@ -20,6 +20,7 @@ public:
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_positions, (SCM));
   DECLARE_SCHEME_CALLBACK (brew_chord_bracket, (SCM));
+  DECLARE_SCHEME_CALLBACK (brew_chord_slur, (SCM));
   DECLARE_SCHEME_CALLBACK (width, (SCM));
   DECLARE_SCHEME_CALLBACK (height, (SCM));
   DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM));
index 8de07c990bf4a316c9b9afbc292ff543de8f85af..e9a82a756b394d70952e356fb5d12a2ff2f95098 100644 (file)
@@ -154,6 +154,7 @@ class Simultaneous_music;
 class Simultaneous_music_iterator;
 class Skyline;
 class Skyline_entry;
+class Skyline_pair;
 class Slur_configuration;
 class Slur_score_state;
 class Source_file;
index b01fb4d42d6e8acc0ea9d389499c2c5f2ba037ca..feabb4cf784b47d6a4a25fc00c94b0dc7e1a82e3 100644 (file)
@@ -20,6 +20,7 @@
   formatted content of the grob is put into a
   Property_object. Page-breaking handles Property_object objects.
 */
+
 class Prob
 {
   DECLARE_SMOBS (Prob);
@@ -40,13 +41,17 @@ public:
   Prob (Prob const &);
   virtual string name () const;
   SCM type () const { return type_; }
-  SCM get_property_alist (bool mutble) const;
+  SCM get_property_alist (bool _mutable) const;
   SCM internal_get_property (SCM sym) const;
   void instrumented_set_property (SCM, SCM, const char*, int, const char*);
   void internal_set_property (SCM sym, SCM val);
 };
+
 DECLARE_UNSMOB(Prob,prob);
+
 SCM ly_prob_set_property_x (SCM system, SCM sym, SCM value);
 SCM ly_prob_property (SCM system, SCM sym, SCM dfault);
 
+SCM ly_prob_type_p (SCM obj, SCM sym);
+  
 #endif /* PROPERTY_OBJECT_HH */
diff --git a/lily/include/skyline-pair.hh b/lily/include/skyline-pair.hh
new file mode 100644 (file)
index 0000000..08fe3c7
--- /dev/null
@@ -0,0 +1,36 @@
+/* 
+  skyline-pair.hh -- declare Skyline_pair
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2008 Han-Wen Nienhuys <hanwen@lilypond.org>
+  
+*/
+
+#ifndef SKYLINE_PAIR_HH
+#define SKYLINE_PAIR_HH
+
+#include "skyline.hh"
+
+class Skyline_pair
+{
+private:
+  Drul_array<Skyline> skylines_;
+
+  DECLARE_SIMPLE_SMOBS(Skyline_pair);
+public:
+  Skyline_pair ();
+  Skyline_pair (vector<Box> const &boxes, Real horizon_padding, Axis a);
+  Skyline_pair (Box const &, Real horizon_padding, Axis a);
+  void raise (Real);
+  void shift (Real);
+  void insert (Box const &, Real horizon_padding, Axis);
+  void merge (Skyline_pair const &other);
+  Skyline &operator [] (Direction d);
+  Skyline const &operator [] (Direction d) const;
+  bool is_empty () const;
+  void print () const;
+  void print_points () const;
+};
+
+#endif /* SKYLINE_PAIR_HH */
index 5dadbacaf736f6503cf7e444c4bc448324556ad1..569d01f9c9ca11d59334845e0fe14858e5766713 100644 (file)
@@ -70,24 +70,7 @@ public:
   bool is_empty () const;
 };
 
-class Skyline_pair
-{
-private:
-  Drul_array<Skyline> skylines_;
-
-  DECLARE_SIMPLE_SMOBS(Skyline_pair);
-public:
-  Skyline_pair ();
-  Skyline_pair (vector<Box> const &boxes, Real horizon_padding, Axis a);
-  Skyline_pair (Box const &, Real horizon_padding, Axis a);
-  void raise (Real);
-  void shift (Real);
-  void insert (Box const &, Real horizon_padding, Axis);
-  void merge (Skyline_pair const &other);
-  Skyline &operator [] (Direction d);
-  Skyline const &operator [] (Direction d) const;
-  bool is_empty () const;
-};
+extern bool debug_skylines;
 
 #endif /* SKYLINE_HH */
 
index f0c82bb963dc31107129688f8440e6d88798bbb8..cf77c086c03066c55c9d2eeb16823f38e6e5c39e 100644 (file)
@@ -45,7 +45,6 @@ public:
   // todo: move to somewhere else.
   Real get_broken_left_end_align () const;
   void substitute_one_mutable_property (SCM sym, SCM val);
-  bool fast_substitute_grob_array (SCM sym, Grob_array *);
 
   Interval_t<Moment> spanned_time () const;
   virtual Interval_t<int> spanned_rank_interval () const;
@@ -69,6 +68,7 @@ protected:
   void set_my_columns ();
   virtual Grob *clone () const;
   virtual void do_break_processing ();
+  bool fast_substitute_grob_array (SCM sym, Grob_array *);
 };
 
 void add_bound_item (Spanner *, Grob *);
index 18b9127d1e83937c31f6395d504275117892c2a9..24402e56c56fcddce176339fa46d42d392e63540 100644 (file)
@@ -43,6 +43,7 @@ struct Tie_details
 
   int single_tie_region_size_;
   int multi_tie_region_size_;
+  Direction neutral_direction_;
   
   Tie_details ();
   void from_grob (Grob *);
index bf5d02d8b2876a2b1d154c2064cbab0f9d17bff9..c80fe02998b420660802cb8816d3ee5515daaecc 100644 (file)
@@ -97,13 +97,15 @@ Lyric_combine_music_iterator::set_music_context (Context *to)
 {
   if (music_context_)
     {
-      music_context_->event_source ()->remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("music-event"));
+      music_context_->event_source ()->
+       remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("music-event"));
     }
 
   music_context_ = to;
   if (to)
     {
-      to->event_source ()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("music-event"));
+      to->event_source ()->add_listener (GET_LISTENER (set_busy),
+                                        ly_symbol2scm ("music-event"));
     }
 }
 
diff --git a/lily/new-dynamic-engraver.cc b/lily/new-dynamic-engraver.cc
new file mode 100644 (file)
index 0000000..990dba0
--- /dev/null
@@ -0,0 +1,223 @@
+/* 
+  new-dynamic-engraver.cc -- implement New_dynamic_engraver
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2008 Han-Wen Nienhuys <hanwen@lilypond.org>
+  
+*/
+
+
+#include "engraver.hh"
+
+#include "item.hh"
+#include "pointer-group-interface.hh"
+#include "text-interface.hh"
+#include "note-column.hh"
+#include "self-alignment-interface.hh"
+#include "spanner.hh"
+#include "stream-event.hh"
+
+#include "translator.icc"
+
+class New_dynamic_engraver : public Engraver
+{
+  TRANSLATOR_DECLARATIONS (New_dynamic_engraver);
+  DECLARE_ACKNOWLEDGER (note_column);
+  DECLARE_TRANSLATOR_LISTENER (absolute_dynamic);
+  DECLARE_TRANSLATOR_LISTENER (span_dynamic);
+
+protected:
+  virtual void process_music ();
+  virtual void stop_translation_timestep ();
+private:
+  Drul_array<Stream_event *> accepted_spanevents_drul_;
+  Spanner *current_spanner_;
+  Spanner *finished_spanner_;
+  
+  Item *script_;
+  Stream_event *script_event_;
+  Stream_event *current_span_event_;
+};
+
+New_dynamic_engraver::New_dynamic_engraver ()
+{
+  script_event_ = 0;
+  current_span_event_ = 0;
+  script_ = 0;
+  finished_spanner_ = 0;
+  current_spanner_ = 0;
+  accepted_spanevents_drul_.set (0, 0);
+}
+
+IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver, absolute_dynamic);
+void
+New_dynamic_engraver::listen_absolute_dynamic (Stream_event *ev)
+{
+  ASSIGN_EVENT_ONCE (script_event_, ev);
+}
+
+IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver, span_dynamic);
+void
+New_dynamic_engraver::listen_span_dynamic (Stream_event *ev)
+{
+  Direction d = to_dir (ev->get_property ("span-direction"));
+
+  ASSIGN_EVENT_ONCE (accepted_spanevents_drul_[d], ev);
+}
+
+
+void
+New_dynamic_engraver::process_music ()
+{
+  if (current_spanner_
+      && (accepted_spanevents_drul_[STOP] || script_event_ || accepted_spanevents_drul_[START]))
+    {
+      Stream_event* ender = accepted_spanevents_drul_[STOP];
+      if (!ender)
+       ender = script_event_;
+
+      if (!ender)
+       ender = accepted_spanevents_drul_[START];
+      
+      finished_spanner_ = current_spanner_;
+      announce_end_grob (finished_spanner_, ender->self_scm ());
+      current_spanner_ = 0;
+      current_span_event_ = 0;
+    }
+
+  if (accepted_spanevents_drul_[START])
+    {
+      current_span_event_ = accepted_spanevents_drul_[START];
+      
+      SCM start_sym = current_span_event_->get_property ("class");
+      string start_type;
+         
+      if (start_sym == ly_symbol2scm ("decrescendo-event"))
+       start_type = "decrescendo";
+      else if (start_sym == ly_symbol2scm ("crescendo-event"))
+       start_type = "crescendo";
+      else
+       {
+         programming_error ("unknown dynamic spanner type");
+         return;
+       }
+      
+      SCM cresc_type = get_property ((start_type + "Spanner").c_str ());
+
+      if (cresc_type == ly_symbol2scm ("text"))
+       {
+         current_spanner_
+           = make_spanner ("DynamicTextSpanner",
+                           accepted_spanevents_drul_[START]->self_scm ());
+
+         SCM text = get_property ((start_type + "Text").c_str ());
+         if (Text_interface::is_markup (text))
+           {
+             current_spanner_->set_property ("text", text);
+           }
+       }
+      else
+       {
+         if (cresc_type != ly_symbol2scm ("hairpin"))
+           {
+             // Fixme: should put value in error message.
+             ly_display_scm (cresc_type);
+             current_span_event_
+               ->origin()->warning ("unknown crescendo style; defaulting to hairpin.");
+           }
+         current_spanner_ = make_spanner ("Hairpin",
+                                          current_span_event_->self_scm ());
+         if (finished_spanner_)
+           {
+             Pointer_group_interface::add_grob (finished_spanner_,
+                                                ly_symbol2scm ("adjacent-hairpins"),
+                                                current_spanner_);
+
+             Pointer_group_interface::add_grob (current_spanner_,
+                                                ly_symbol2scm ("adjacent-hairpins"),
+                                                finished_spanner_);
+           }
+       }
+    }
+
+  if (script_event_)
+    {
+      script_ = make_item ("DynamicText", script_event_->self_scm ());
+      script_->set_property ("text",
+                            script_event_->get_property ("text"));
+
+      if (finished_spanner_)
+       finished_spanner_->set_bound (RIGHT, script_);
+      if (current_spanner_)
+       {
+         current_spanner_->set_bound (LEFT, script_);
+         set_nested_property (current_spanner_,
+                              scm_list_3 (ly_symbol2scm ("bound-details"),
+                                          ly_symbol2scm ("left"),
+                                          ly_symbol2scm ("attach-dir")
+                                          ),
+                              scm_from_int (RIGHT));
+
+       }
+    }
+}
+
+
+
+void
+New_dynamic_engraver::stop_translation_timestep ()
+{
+  if (finished_spanner_ && !finished_spanner_->get_bound (RIGHT))
+    finished_spanner_->set_bound (RIGHT,
+                                 unsmob_grob (get_property ("currentMusicalColumn")));
+
+  if (current_spanner_ && !current_spanner_->get_bound (LEFT))
+    current_spanner_->set_bound (LEFT,
+                                unsmob_grob (get_property ("currentMusicalColumn")));
+  script_ = 0;
+  script_event_ = 0;
+  accepted_spanevents_drul_.set (0, 0);
+  finished_spanner_ = 0;
+}
+
+void
+New_dynamic_engraver::acknowledge_note_column (Grob_info info)
+{
+  if (script_ && !script_->get_parent (X_AXIS))
+    {
+      extract_grob_set (info.grob (), "note-heads", heads);
+      if (heads.size ())
+       {
+         Grob *head = heads[0];
+         script_->set_parent (head, X_AXIS);
+         Self_alignment_interface::set_center_parent (script_, X_AXIS);
+       }
+    }
+
+  if (current_spanner_ && !current_spanner_->get_bound (LEFT))
+    current_spanner_->set_bound (LEFT, info.grob ());
+  if (finished_spanner_ && !finished_spanner_->get_bound (RIGHT))
+    finished_spanner_->set_bound (RIGHT, info.grob ());
+}
+
+ADD_ACKNOWLEDGER (New_dynamic_engraver, note_column);
+ADD_TRANSLATOR (New_dynamic_engraver,
+               /* doc */
+               "Create hairpins, dynamic texts, and their vertical"
+               " alignments.  The symbols are collected onto a"
+               " @code{DynamicLineSpanner} grob which takes care of vertical"
+               " positioning.",
+
+               /* create */
+               "DynamicTextSpanner "
+               "DynamicText "
+               "Hairpin "
+               "TextSpanner ",
+
+               /* read */
+               "currentMusicalColumn ",
+
+               /* write */
+               ""
+               );
index 8c9e0aea4eec10a8607358dc777557f795834a72..0eb40d1b97a48c8297ff378de172d65de6cd5072 100644 (file)
@@ -8,23 +8,24 @@
 
 #include "paper-column.hh"
 
-#include "break-align-interface.hh"
-#include "moment.hh"
-#include "paper-score.hh"
-#include "warn.hh"
 #include "axis-group-interface.hh"
-#include "spaceable-grob.hh"
-#include "text-interface.hh"
-#include "lookup.hh"
+#include "break-align-interface.hh"
 #include "font-interface.hh"
-#include "output-def.hh"
-#include "pointer-group-interface.hh"
 #include "grob-array.hh"
-#include "system.hh"
-#include "spring.hh"
 #include "lookup.hh"
+#include "lookup.hh"
+#include "moment.hh"
+#include "output-def.hh"
+#include "paper-score.hh"
+#include "pointer-group-interface.hh"
 #include "separation-item.hh"
+#include "skyline-pair.hh"
+#include "spaceable-grob.hh"
+#include "spring.hh"
 #include "string-convert.hh"
+#include "system.hh"
+#include "text-interface.hh"
+#include "warn.hh"
 
 Grob *
 Paper_column::clone () const
diff --git a/lily/paper-system-scheme.cc b/lily/paper-system-scheme.cc
new file mode 100644 (file)
index 0000000..6935110
--- /dev/null
@@ -0,0 +1,44 @@
+/* 
+  paper-system-scheme.cc -- implement Paper_system bindings.
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2008 Han-Wen Nienhuys <hanwen@lilypond.org>
+  
+*/
+
+#include "prob.hh"
+
+#include "skyline-pair.hh"
+  
+LY_DEFINE (ly_paper_system_p, "ly:paper-system?",
+         1, 0, 0, (SCM obj),
+         "Type predicate.")
+{
+  return ly_prob_type_p (obj, ly_symbol2scm ("paper-system"));
+}
+
+LY_DEFINE (ly_paper_system_minimum_distance, "ly:paper-system-minimum-distance",
+          2, 0, 0, (SCM sys1, SCM sys2),
+          "Measure the minimum distance between these two paper-systems,"
+          " using their stored skylines if possible and falling back to"
+          " their extents otherwise.")
+{
+  Real ret = 0;
+  Prob *p1 = unsmob_prob (sys1);
+  Prob *p2 = unsmob_prob (sys2);
+  Skyline_pair *sky1 = Skyline_pair::unsmob (p1->get_property ("vertical-skylines"));
+  Skyline_pair *sky2 = Skyline_pair::unsmob (p2->get_property ("vertical-skylines"));
+
+  if (sky1 && sky2)
+    ret = (*sky1)[DOWN].distance ((*sky2)[UP]);
+  else
+    {
+      Stencil *s1 = unsmob_stencil (p1->get_property ("stencil"));
+      Stencil *s2 = unsmob_stencil (p2->get_property ("stencil"));
+      Interval iv1 = s1->extent (Y_AXIS);
+      Interval iv2 = s2->extent (Y_AXIS);
+      ret = iv2[UP] - iv1[DOWN];
+    }
+  return scm_from_double (ret);
+}
index 8c5d640ad0d3b5d9501c57c8f800d723504df8b3..717e32a945985358af74ee08f379b372e4363294 100644 (file)
@@ -7,7 +7,6 @@
 */
 
 #include "prob.hh"
-#include "skyline.hh"
 
 LY_DEFINE (ly_prob_set_property_x, "ly:prob-set-property!",
           2, 1, 0, (SCM obj, SCM sym, SCM value),
@@ -77,35 +76,24 @@ LY_DEFINE (ly_make_prob, "ly:make-prob",
   return pr->unprotect ();
 }
 
-  
-LY_DEFINE (ly_paper_system_p, "ly:paper-system?",
-         1, 0, 0, (SCM obj),
-         "Type predicate.")
+
+LY_DEFINE (ly_prob_mutable_properties, "ly:prob-mutable-properties",
+          1, 0, 0,
+          (SCM prob),
+          "Retrieve an alist of mutable properties.")
 {
-  return ly_prob_type_p (obj, ly_symbol2scm ("paper-system"));
+  LY_ASSERT_SMOB (Prob, prob, 1);
+  Prob *ps = unsmob_prob (prob);
+  return ps->get_property_alist (true);
 }
 
-LY_DEFINE (ly_paper_system_minimum_distance, "ly:paper-system-minimum-distance",
-          2, 0, 0, (SCM sys1, SCM sys2),
-          "Measure the minimum distance between these two paper-systems,"
-          " using their stored skylines if possible and falling back to"
-          " their extents otherwise.")
+LY_DEFINE (ly_prob_immutable_properties, "ly:prob-immutable-properties",
+          1, 0, 0,
+          (SCM prob),
+          "Retrieve an alist of mutable properties.")
 {
-  Real ret = 0;
-  Prob *p1 = unsmob_prob (sys1);
-  Prob *p2 = unsmob_prob (sys2);
-  Skyline_pair *sky1 = Skyline_pair::unsmob (p1->get_property ("vertical-skylines"));
-  Skyline_pair *sky2 = Skyline_pair::unsmob (p2->get_property ("vertical-skylines"));
-
-  if (sky1 && sky2)
-    ret = (*sky1)[DOWN].distance ((*sky2)[UP]);
-  else
-    {
-      Stencil *s1 = unsmob_stencil (p1->get_property ("stencil"));
-      Stencil *s2 = unsmob_stencil (p2->get_property ("stencil"));
-      Interval iv1 = s1->extent (Y_AXIS);
-      Interval iv2 = s2->extent (Y_AXIS);
-      ret = iv2[UP] - iv1[DOWN];
-    }
-  return scm_from_double (ret);
+  LY_ASSERT_SMOB (Prob, prob, 1);
+  Prob *ps = unsmob_prob (prob);
+  return ps->get_property_alist (false);
 }
+
index 5c9eb9ef10439826317203c17eee4547fc60988e..a567f3c6bd50c336e56773b14209efeb2d81eb45 100644 (file)
@@ -8,15 +8,15 @@
 
 #include "separation-item.hh"
 
+#include "accidental-placement.hh"
 #include "axis-group-interface.hh"
 #include "lookup.hh"
 #include "note-head.hh"
-#include "stencil.hh"
-#include "skyline.hh"
 #include "paper-column.hh"
-#include "warn.hh"
 #include "pointer-group-interface.hh"
-#include "accidental-placement.hh"
+#include "skyline-pair.hh"
+#include "stencil.hh"
+#include "warn.hh"
 
 void
 Separation_item::add_item (Grob *s, Item *i)
@@ -137,7 +137,6 @@ Separation_item::boxes (Grob *me, Grob *left)
   return out;      
 }
 
-extern bool debug_skylines;
 MAKE_SCHEME_CALLBACK (Separation_item, print, 1)
 SCM
 Separation_item::print (SCM smob)
diff --git a/lily/skyline-pair.cc b/lily/skyline-pair.cc
new file mode 100644 (file)
index 0000000..100061a
--- /dev/null
@@ -0,0 +1,109 @@
+/* 
+  skyline-pair.cc -- implement Skyline_pair
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2008 Han-Wen Nienhuys <hanwen@lilypond.org>
+  
+*/
+
+#include "skyline-pair.hh"
+
+#include "ly-smobs.icc"
+
+Skyline_pair::Skyline_pair ()
+  : skylines_ (Skyline (DOWN), Skyline (UP))
+{
+}
+
+Skyline_pair::Skyline_pair (vector<Box> const &boxes, Real padding, Axis a)
+  : skylines_ (Skyline (boxes, padding, a, DOWN), Skyline (boxes, padding, a, UP))
+{
+}
+
+Skyline_pair::Skyline_pair (Box const &b, Real padding, Axis a)
+  : skylines_ (Skyline (b, padding, a, DOWN), Skyline (b, padding, a, UP))
+{
+}
+
+void
+Skyline_pair::raise (Real r)
+{
+  skylines_[UP].raise (r);
+  skylines_[DOWN].raise (r);
+}
+
+void
+Skyline_pair::shift (Real r)
+{
+  skylines_[UP].shift (r);
+  skylines_[DOWN].shift (r);
+}
+
+void
+Skyline_pair::insert (Box const &b, Real padding, Axis a)
+{
+  skylines_[UP].insert (b, padding, a);
+  skylines_[DOWN].insert (b, padding, a);
+}
+
+void
+Skyline_pair::merge (Skyline_pair const &other)
+{
+  skylines_[UP].merge (other[UP]);
+  skylines_[DOWN].merge (other[DOWN]);
+}
+
+void
+Skyline_pair::print () const
+{
+  skylines_[UP].print ();
+  skylines_[DOWN].print ();
+}
+
+void
+Skyline_pair::print_points () const
+{
+  skylines_[UP].print ();
+  skylines_[DOWN].print ();
+}
+
+
+bool
+Skyline_pair::is_empty () const
+{
+  return skylines_[UP].is_empty ()
+    && skylines_[DOWN].is_empty ();
+}
+
+Skyline&
+Skyline_pair::operator [] (Direction d)
+{
+  return skylines_[d];
+}
+
+Skyline const&
+Skyline_pair::operator [] (Direction d) const
+{
+  return skylines_[d];
+}
+
+IMPLEMENT_SIMPLE_SMOBS (Skyline_pair);
+IMPLEMENT_TYPE_P (Skyline_pair, "ly:skyline-pair?");
+IMPLEMENT_DEFAULT_EQUAL_P (Skyline_pair);
+
+SCM
+Skyline_pair::mark_smob (SCM)
+{
+  return SCM_EOL;
+}
+
+int
+Skyline_pair::print_smob (SCM s, SCM port, scm_print_state *)
+{
+  Skyline_pair *r = (Skyline_pair *) SCM_CELL_WORD_1 (s);
+  (void) r;
+
+  scm_puts ("#<Skyline-pair>", port);
+  return 1;
+}
index e0139a68668ecc46f4a7682bed85abb8812c1786..5297f6359ab91ea58642e9f552eca313031217ac 100644 (file)
@@ -541,67 +541,6 @@ Skyline::is_empty () const
   return b.end_ == infinity_f && b.y_intercept_ == -infinity_f;
 }
 
-Skyline_pair::Skyline_pair ()
-  : skylines_ (Skyline (DOWN), Skyline (UP))
-{
-}
-
-Skyline_pair::Skyline_pair (vector<Box> const &boxes, Real padding, Axis a)
-  : skylines_ (Skyline (boxes, padding, a, DOWN), Skyline (boxes, padding, a, UP))
-{
-}
-
-Skyline_pair::Skyline_pair (Box const &b, Real padding, Axis a)
-  : skylines_ (Skyline (b, padding, a, DOWN), Skyline (b, padding, a, UP))
-{
-}
-
-void
-Skyline_pair::raise (Real r)
-{
-  skylines_[UP].raise (r);
-  skylines_[DOWN].raise (r);
-}
-
-void
-Skyline_pair::shift (Real r)
-{
-  skylines_[UP].shift (r);
-  skylines_[DOWN].shift (r);
-}
-
-void
-Skyline_pair::insert (Box const &b, Real padding, Axis a)
-{
-  skylines_[UP].insert (b, padding, a);
-  skylines_[DOWN].insert (b, padding, a);
-}
-
-void
-Skyline_pair::merge (Skyline_pair const &other)
-{
-  skylines_[UP].merge (other[UP]);
-  skylines_[DOWN].merge (other[DOWN]);
-}
-
-bool
-Skyline_pair::is_empty () const
-{
-  return skylines_[UP].is_empty ()
-    && skylines_[DOWN].is_empty ();
-}
-
-Skyline&
-Skyline_pair::operator [] (Direction d)
-{
-  return skylines_[d];
-}
-
-Skyline const&
-Skyline_pair::operator [] (Direction d) const
-{
-  return skylines_[d];
-}
 
 /****************************************************************/
 
@@ -610,10 +549,6 @@ IMPLEMENT_SIMPLE_SMOBS (Skyline);
 IMPLEMENT_TYPE_P (Skyline, "ly:skyline?");
 IMPLEMENT_DEFAULT_EQUAL_P (Skyline);
 
-IMPLEMENT_SIMPLE_SMOBS (Skyline_pair);
-IMPLEMENT_TYPE_P (Skyline_pair, "ly:skyline-pair?");
-IMPLEMENT_DEFAULT_EQUAL_P (Skyline_pair);
-
 SCM
 Skyline::mark_smob (SCM)
 {
@@ -631,19 +566,3 @@ Skyline::print_smob (SCM s, SCM port, scm_print_state *)
 
   return 1;
 }
-
-SCM
-Skyline_pair::mark_smob (SCM)
-{
-  return SCM_EOL;
-}
-
-int
-Skyline_pair::print_smob (SCM s, SCM port, scm_print_state *)
-{
-  Skyline_pair *r = (Skyline_pair *) SCM_CELL_WORD_1 (s);
-  (void) r;
-
-  scm_puts ("#<Skyline-pair>", port);
-  return 1;
-}
index 2033cfcac43898dfc6b68e3dbb87d6aca6847501..d494c318c5ef820ca7759264c30c9a0f880c3842 100644 (file)
@@ -17,6 +17,7 @@
 #include "paper-column.hh"
 #include "separation-item.hh"
 #include "skyline.hh"
+#include "skyline-pair.hh"
 #include "system.hh"
 
 /* return the right-pointing skyline of the left-items and the left-pointing
index e580e33267cda1879fa665b22c7d2aaa0c4820dd..74e54e7eac7d308672ecb44e73e8704c37244656 100644 (file)
@@ -21,6 +21,7 @@
 #include "paper-score.hh"
 #include "pointer-group-interface.hh"
 #include "separation-item.hh"
+#include "skyline-pair.hh"
 #include "spaceable-grob.hh"
 #include "spacing-interface.hh"
 #include "staff-spacing.hh"
index a2ad71ece35dc8cb8df9e1c4e1b691972b4faa5a..e686e3b58cad0585e3ea7303686e50bfeb5e13aa 100644 (file)
 #include "axis-group-interface.hh"
 #include "grob-array.hh"
 #include "international.hh"
+#include "lookup.hh"
 #include "main.hh"
 #include "output-def.hh"
 #include "paper-column.hh"
 #include "paper-score.hh"
 #include "paper-system.hh"
 #include "pointer-group-interface.hh"
+#include "skyline-pair.hh"
 #include "staff-symbol-referencer.hh"
 #include "warn.hh"
-#include "lookup.hh"
-
-extern bool debug_skylines;
 
 System::System (System const &src)
   : Spanner (src)
@@ -395,8 +394,12 @@ System::get_paper_system ()
       Skyline_pair *skylines = Skyline_pair::unsmob (get_property ("vertical-skylines"));
       if (skylines)
        {
-         sys_stencil.add_stencil (Lookup::points_to_line_stencil (0.1, (*skylines)[UP].to_points (X_AXIS)).in_color (255, 0, 0));
-         sys_stencil.add_stencil (Lookup::points_to_line_stencil (0.1, (*skylines)[DOWN].to_points (X_AXIS)).in_color (0, 255, 0));
+         Stencil up
+           = Lookup::points_to_line_stencil (0.1, (*skylines)[UP].to_points (X_AXIS));
+         Stencil down
+           = Lookup::points_to_line_stencil (0.1, (*skylines)[DOWN].to_points (X_AXIS));
+         sys_stencil.add_stencil (up.in_color (255, 0, 0));
+         sys_stencil.add_stencil (down.in_color (0, 255, 0));
        }
     }
 
index 7c39b1c717cf20bbca5c7fbf8f7b7e10dc32623a..75a32d5bb78a1aabc584815851d73442ddc80595 100644 (file)
@@ -28,7 +28,10 @@ Tie_details::from_grob (Grob *me)
 {
   staff_symbol_referencer_ = me;
   staff_space_ = Staff_symbol_referencer::staff_space (me);
-
+  
+  neutral_direction_ = to_dir (me->get_property ("neutral-direction"));
+  if (!neutral_direction_)
+    neutral_direction_ = DOWN;
   
   SCM details = me->get_property ("details");
 
index bb50c4fbc18c1cfb9cee8be9fbb49e9c54b3b443..6aa5feb3b1b04e139db3829810472c3590e58581 100644 (file)
@@ -977,7 +977,8 @@ Tie_formatting_problem::set_ties_config_standard_directions (Ties_configuration
        tie_configs->at (0).dir_ = Direction (sign (tie_configs->at (0).position_));
 
       if (!tie_configs->at (0).dir_)
-       tie_configs->at (0).dir_ = DOWN;
+       tie_configs->at (0).dir_
+         = (tie_configs->size() > 1) ? DOWN : details_.neutral_direction_;
     }
   
   if (!tie_configs->back ().dir_)
index aa265f504236aee5c4465eeec693610a247f9add..980484d21bcdaed4b0345b1fdee3f5891f5a7ffa 100644 (file)
@@ -17,6 +17,7 @@
 #include "note-head.hh"
 #include "output-def.hh"
 #include "paper-column.hh"
+#include "pointer-group-interface.hh"
 #include "rhythmic-head.hh"
 #include "spanner.hh"
 #include "staff-symbol-referencer.hh"
@@ -113,7 +114,11 @@ Tie::get_default_dir (Grob *me)
   Direction d = LEFT;
   do
     {
-      Grob *stem = head (me, d) ? Rhythmic_head::get_stem (head (me, d)) : 0;
+      Grob *one_head = head (me, d);
+      if (!one_head && dynamic_cast<Spanner*> (me)) 
+       one_head = Tie::head (dynamic_cast<Spanner*> (me)->broken_neighbor (d), d);
+      
+      Grob *stem = one_head ? Rhythmic_head::get_stem (one_head) : 0;
       if (stem)
        stem = Stem::is_invisible (stem) ? 0 : stem;
 
@@ -135,7 +140,7 @@ Tie::get_default_dir (Grob *me)
   else if (int p = get_position (me))
     return Direction (sign (p));
   
-  return UP;
+  return to_dir (me->get_property("neutral-direction"));
 }
 
 
@@ -218,6 +223,14 @@ Tie::calc_control_points (SCM smob)
       //      && unsmob_grob_array (yparent->get_object ("ties"))->size () > 1
       )
     {
+      extract_grob_set (yparent, "ties", ties);
+      if (ties.size() == 1
+         && !to_dir (me->get_property_data ("direction")))
+       {
+         assert (ties[0] == me);
+         set_grob_direction (me, Tie::get_default_dir (me));
+       }
+      
       /* trigger positioning. */
       (void) yparent->get_property ("positioning-done");
     }
@@ -310,10 +323,11 @@ ADD_INTERFACE (Tie,
               "dash-period "
               "details "
               "direction "
-              "separation-item "
               "head-direction "
               "line-thickness "
+              "neutral-direction "
               "quant-score "
+              "separation-item "
               "staff-position "
               "thickness "
               );
index c2239ec05424d3816f086e3296d4ffe5ea7a4de6..480a1ad6dc8551b8a629fc0eab5602c149549ebe 100644 (file)
@@ -222,7 +222,9 @@ multiple voices on the same staff."
   \consists "Part_combine_engraver"
 
   \consists "Text_engraver"
-  \consists "Dynamic_engraver"
+  \consists "New_dynamic_engraver"
+  \consists "Dynamic_align_engraver"
+%  \consists "Dynamic_engraver"
   \consists "Fingering_engraver"
   \consists "Bend_engraver"
 
@@ -505,6 +507,9 @@ automatically when an output definition (a @code{\score} or
   middleCClefPosition = #-6
   middleCPosition = #-6
   firstClef = ##t
+
+  crescendoSpanner = #'hairpin
+  decrescendoSpanner = #'hairpin
   
   defaultBarType = #"|"
   barNumberVisibility = #first-bar-number-invisible
index 60989ede0cd2ed21a70613b7cbe4060d62f4f90a..1425b22b14954315deea2483a50c4b3a110e737e 100644 (file)
@@ -51,31 +51,38 @@ endcresc =  {
 
 setTextCresc = {
     \set crescendoText = \markup { \italic "cresc." }
-    \set crescendoSpanner = #'dashed-line
+    \set crescendoSpanner = #'text
+    \override DynamicTextSpanner #'style = #'dashed-line
 }
 
 setTextDecresc = {
     \set decrescendoText = \markup { \italic "decresc." }
-    \set decrescendoSpanner = #'dashed-line
+    \set decrescendoSpanner = #'text
+    \override DynamicTextSpanner #'style = #'dashed-line
 }
 
 setTextDecr = {
     \set decrescendoText = \markup { \italic "decr." }
-    \set decrescendoSpanner = #'dashed-line
+    \set decrescendoSpanner = #'text
+    \override DynamicTextSpanner #'style = #'dashed-line
 }
 
 setTextDim = {
     \set decrescendoText = \markup { \italic "dim." }
-    \set decrescendoSpanner = #'dashed-line
+    \set decrescendoSpanner = #'text
+    \override DynamicTextSpanner #'style = #'dashed-line
 }
+
 setHairpinCresc = {
     \unset crescendoText 
     \unset crescendoSpanner 
 }
+
 setHairpinDecresc = {
     \unset decrescendoText 
     \unset decrescendoSpanner 
 }
+
 setHairpinDim = {
     \unset decrescendoText 
     \unset decrescendoSpanner 
index e506ed24fea8a978dffb9be277b99910a9374c92..f656942b1630e769a87b4f549201e2271bc7b56c 100644 (file)
@@ -148,6 +148,7 @@ Values of 7 and -7 are common.")
      (clefPosition ,number? "Where should the center of the clef
 symbol go, measured in half staff spaces from the center of the
 staff.")
+     (completionBusy ,boolean? "Whether a completion-note head is playing.")
      (connectArpeggios ,boolean? "If set, connect arpeggios across
 piano staff.")
      (countPercentRepeats ,boolean? "If set, produce counters for
@@ -581,4 +582,4 @@ and subscripts.  See @file{scm/script.scm} for more information.")
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public default-melisma-properties
-  '(melismaBusy slurMelismaBusy tieMelismaBusy beamMelismaBusy))
+  '(melismaBusy slurMelismaBusy tieMelismaBusy beamMelismaBusy completionBusy))
index 652a1392437143ba68ba4fc2d07c696ad9de5673..94e30465e9b7f36b09c88cd0ef45fe65636a1eb8 100644 (file)
        (springs-and-rods . ,ly:spanner::set-spacing-rods)
        (avoid-slur . inside)
        (direction . ,ly:tie::calc-direction)
+       (neutral-direction . ,UP)
        (stencil . ,ly:tie::print)
        (font-size . -6)
        (details . (
index d4d6784692e4022da6c5116c2a12555f37313e60..1dcd5fd7dc9c7f3be2982c70a37e496031746a5a 100644 (file)
@@ -103,7 +103,7 @@ thickness and padding around the markup."
 
 (define-builtin-markup-command (with-url layout props url arg)
   (string? markup?)
-  other
+  graphic
   ()
   "
 @cindex inserting URL links into text
@@ -151,7 +151,7 @@ Create a beam with the specified parameters."
 
 (define-builtin-markup-command (underline layout props arg)
   (markup?)
-  other
+  music
   ((thickness 1))
   "
 @cindex underlining text
@@ -172,7 +172,7 @@ thickness and y offset."
 
 (define-builtin-markup-command (box layout props arg)
   (markup?)
-  other
+  font
   ((thickness 1)
    (font-size 0)
    (box-padding 0.2))
@@ -190,7 +190,7 @@ thickness and padding around the markup."
 
 (define-builtin-markup-command (filled-box layout props xext yext blot)
   (number-pair? number-pair? number?)
-  other
+  graphic
   ()
   "
 @cindex drawing solid boxes within text
@@ -209,7 +209,7 @@ circle of diameter@tie{}0 (i.e. sharp corners)."
 
 (define-builtin-markup-command (rounded-box layout props arg)
   (markup?)
-  other
+  graphic
   ((thickness 1)
    (corner-radius 1)
    (font-size 0)
@@ -234,7 +234,7 @@ c,8. c16 c4 r
 
 (define-builtin-markup-command (rotate layout props ang arg)
   (number? markup?)
-  other
+  align
   ()
   "
 @cindex rotating text
@@ -255,7 +255,7 @@ Provide a white background for @var{arg}."
 
 (define-builtin-markup-command (pad-markup layout props padding arg)
   (number? markup?)
-  other
+  align
   ()
   "
 @cindex padding text
@@ -293,7 +293,7 @@ Create a box of the same height as the space in the current font."
 ;; todo: fix negative space
 (define-builtin-markup-command (hspace layout props amount)
   (number?)
-  other
+  align
   ()
   "
 @cindex creating horizontal spaces in text
@@ -430,7 +430,7 @@ An empty markup with extents of a single point."
 
 (define-builtin-markup-command (simple layout props str)
   (string?)
-  other
+  font
   ()
   "
 @cindex simple text strings
@@ -441,7 +441,7 @@ A simple text string; @code{\\markup @{ foo @}} is equivalent with
 
 (define-builtin-markup-command (tied-lyric layout props str)
   (string?)
-  other
+  music
   ()
   "
 @cindex simple text strings with tie characters
@@ -570,7 +570,7 @@ determines the space between each markup in @var{args}."
 
 (define-builtin-markup-command (concat layout props args)
   (markup-list?)
-  other
+  align
   ()
   "
 @cindex concatenating text
@@ -758,7 +758,7 @@ the line width, where @var{X} is the number of staff spaces."
 
 (define-builtin-markup-command (combine layout props m1 m2)
   (markup? markup?)
-  other
+  align
   ()
   "
 @cindex merging text
@@ -892,7 +892,7 @@ Set the dimensions of @var{arg} to @var{x} and@tie{}@var{y}."
 
 (define-builtin-markup-command (pad-around layout props amount arg)
   (number? markup?)
-  other
+  align
   ()
   "Add padding @var{amount} all around @var{arg}."  
   (let* ((m (interpret-markup layout props arg))
@@ -904,7 +904,7 @@ Set the dimensions of @var{arg} to @var{x} and@tie{}@var{y}."
 
 (define-builtin-markup-command (pad-x layout props amount arg)
   (number? markup?)
-  other
+  align
   ()
   "
 @cindex padding text horizontally
@@ -919,7 +919,7 @@ Add padding @var{amount} around @var{arg} in the X@tie{}direction."
 
 (define-builtin-markup-command (put-adjacent layout props arg1 axis dir arg2)
   (markup? integer? ly:dir? markup?)
-  other
+  align
   ()
   "Put @var{arg2} next to @var{arg1}, without moving @var{arg1}."
   (let ((m1 (interpret-markup layout props arg1))
@@ -938,7 +938,7 @@ Add padding @var{amount} around @var{arg} in the X@tie{}direction."
 
 (define-builtin-markup-command (pad-to-box layout props x-ext y-ext arg)
   (number-pair? number-pair? markup?)
-  other
+  align
   ()
   "Make @var{arg} take at least @var{x-ext}, @var{y-ext} space."
   (let* ((m (interpret-markup layout props arg))
@@ -950,7 +950,7 @@ Add padding @var{amount} around @var{arg} in the X@tie{}direction."
 
 (define-builtin-markup-command (hcenter-in layout props length arg)
   (number? markup?)
-  other
+  align
   ()
   "Center @var{arg} horizontally within a box of extending
 @var{length}/2 to the left and right."
@@ -1660,7 +1660,7 @@ a shortened down stem."
 
 (define-builtin-markup-command (lower layout props amount arg)
   (number? markup?)
-  other
+  align
   ()
   "
 @cindex lowering text
@@ -1688,7 +1688,7 @@ Translate @var{arg} by @var{offset}, scaling the offset by the
 
 (define-builtin-markup-command (raise layout props amount arg)
   (number? markup?)
-  other
+  align
   ()
   "
 @cindex raising text
@@ -1743,7 +1743,7 @@ Make a fraction of two markups."
 
 (define-builtin-markup-command (normal-size-super layout props arg)
   (markup?)
-  other
+  font
   ((baseline-skip))
   "
 @cindex setting superscript in standard font size
@@ -1755,7 +1755,7 @@ Set @var{arg} in superscript with a normal font size."
 
 (define-builtin-markup-command (super layout props arg)
   (markup?)
-  other
+  font
   ((font-size 0)
    (baseline-skip))
   "  
@@ -1777,7 +1777,7 @@ Raising and lowering texts can be done with @code{\\super} and
 
 (define-builtin-markup-command (translate layout props offset arg)
   (number-pair? markup?)
-  other
+  align
   ()
   "
 @cindex translating text
@@ -1797,7 +1797,7 @@ that."
 
 (define-builtin-markup-command (sub layout props arg)
   (markup?)
-  other
+  font
   ((font-size 0)
    (baseline-skip))
   "
@@ -1814,7 +1814,7 @@ Set @var{arg} in subscript."
 
 (define-builtin-markup-command (normal-size-sub layout props arg)
   (markup?)
-  other
+  font
   ((baseline-skip))
   "
 @cindex setting subscript in standard font size
@@ -1831,7 +1831,7 @@ Set @var{arg} in subscript, in a normal font size."
 
 (define-builtin-markup-command (hbracket layout props arg)
   (markup?)
-  other
+  graphic
   ()
   "
 @cindex placing horizontal brackets around text
@@ -1843,7 +1843,7 @@ Draw horizontal brackets around @var{arg}."
 
 (define-builtin-markup-command (bracket layout props arg)
   (markup?)
-  other
+  graphic
   ()
   "
 @cindex placing vertical brackets around text
index cffdf2afda238cac9da1d14a85db6ac3efa1c6d5..77ee9b97dce4fee30b81c818af65d53c310b1f56 100644 (file)
     #:name "Text markup commands"
     #:desc ""
     #:text "The following commands can all be used inside @code{\\markup @{ @}}."
-    #:children (let ((categories (sort (hash-fold (lambda (category function+properties categories)
-                                                    (cons category categories))
-                                                  (list)
-                                                  markup-functions-by-category)
-                                       (lambda (c1 c2)
-                                         (string<? (symbol->string c1)
-                                                   (symbol->string c2))))))
+    #:children (let* (;; when a new category is defined, update `ordered-categories'
+                      (ordered-categories '(font align graphic music fret-diagram other))
+                      (raw-categories (hash-fold (lambda (category functions categories)
+                                                   (cons category categories))
+                                                 (list)
+                                                 markup-functions-by-category))
+                      (categories (append ordered-categories
+                                          (filter (lambda (cat)
+                                                    (not (memq cat ordered-categories)))
+                                                  raw-categories))))
                  (map markup-category-doc-node categories))))
 
 (define (markup-list-doc-node)
index 1e7c524241141b0c4ab6e8dff817a59b077b0544..c700f190dbc5f287b2999a6047be3c436e733d0a 100644 (file)
@@ -340,7 +340,18 @@ i.e.  this is not an override"
              'grob-property gprop))
 
 (define direction-polyphonic-grobs
-  '(Stem Tie Rest Slur PhrasingSlur Script TextScript Dots DotColumn Fingering))
+  '(DotColumn
+    Dots
+    Fingering
+    LaissezVibrerTie
+    PhrasingSlur
+    RepeatTie
+    Rest
+    Script
+    Slur
+    Stem
+    TextScript
+    Tie))
 
 (define-safe-public (make-voice-props-set n)
   (make-sequential-music
index a57333e2338ac4b6a1e1b1b8f9af921b4395478a..f10e07c172633f19c4d273ee4c895a11f3a5fc1f 100644 (file)
@@ -991,6 +991,12 @@ class LilypondSnippet (Snippet):
             if k not in self.option_dict:
                 self.option_dict[k] = default_ly_options[k]
 
+        # RELATIVE does not work without FRAGMENT;
+        # make RELATIVE imply FRAGMENT
+        has_relative = self.option_dict.has_key (RELATIVE)
+        if has_relative and not self.option_dict.has_key (FRAGMENT):
+            self.option_dict[FRAGMENT] = None
+
         if not has_line_width:
             if type == 'lilypond' or FRAGMENT in self.option_dict:
                 self.option_dict[RAGGED_RIGHT] = None