-@c -*- coding: utf-8; mode: texinfo; -*-
+Elu@c -*- coding: utf-8; mode: texinfo; -*-
@node Issues
@chapter Issues
@example
Monday: Eluze
-Tuesday:
+Tuesday: Federico Bruni
Wednesday: Marek Klein
Thursday: Eluze
-Friday:
+Friday: Ralph Palmer
Saturday: Colin Campbell
Sunday:
@end example
@c line weights be scaled for small staves?
@c Grieg's Violin Sonata Op. 45
-@lilypond[indent=1.5cm]
+@lilypond[indent=1.5\cm]
global = {
\time 6/8
\key c \minor
Guide, node Updating translation committishes.
@end ignore
-@c \version "2.17.30"
+@c \version "2.19.12"
@c Translators: Till Paala
@example
\paper @{
- system-system-spacing #'basic-distance = #8
+ system-system-spacing.basic-distance = #8
score-system-spacing =
#'((basic-distance . 12)
(minimum-distance . 6)
würde in seiner finalen Version folgende @code{\layout}-Umgebung haben:
@example
- TextScript #'padding = #1
- TextScript #'color = #magenta
- Glissando #'thickness = #1.5
- NoteHead #' font-size = #4
- NoteHead #' color = #red
+ TextScript.padding = #1
+ TextScript.color = #magenta
+ Glissando.thickness = #1.5
+ NoteHead.font-size = #4
+ NoteHead.color = #red
@end example
plus die Veränderungen an Einrückung (@code{indent}) und @code{StaffGrouper}.
wird, würde die aktuelle Konfiguration nur enthalten:
@example
- NoteHead #' font-size= #4 % (written in the variable definition)
- NoteHead #' color = #red % (added after the use of the variable)
+ NoteHead.font-size= #4 % (written in the variable definition)
+ NoteHead.color = #red % (added after the use of the variable)
@end example
Wenn man sorgfältig plant, können @code{\layout}-Variablen ein wertvolles
@c line weights be scaled for small staves?
@c Grieg's Violin Sonata Op. 45
-@lilypond[indent=1.5cm]
+@lilypond[indent=1.5\cm]
global = {
\time 6/8
\key c \minor
version that you are working on. See TRANSLATION for details.
@end ignore
-@c \version "2.19.2"
+@c \version "2.19.12"
@node Interfaces para programadores
@chapter Interfaces para programadores
@example
\relative c'' @{
- \override Flag #'X-offset = #(lambda (flag)
+ \override Flag.X-offset = #(lambda (flag)
(let ((default (ly:flag::calc-x-offset flag)))
(* default 4.0)))
c4. d8 a4. g8
Guide, node Updating translation committishes..
@end ignore
-@c \version "2.17.30"
+@c \version "2.19.12"
@ignore
GDP TODO list
@example
\paper @{
- system-system-spacing #'basic-distance = #8
+ system-system-spacing.basic-distance = #8
score-system-spacing =
#'((basic-distance . 12)
(minimum-distance . 6)
used together on the same page:
@c Grieg's Violin Sonata Op. 45
-@lilypond[indent=1.5cm]
+@lilypond[indent=1.5\cm]
global = {
\time 6/8
\key c \minor
Guide, node Updating translation committishes..
@end ignore
-@c \version "2.19.2"
+@c \version "2.19.12"
@node Interfaces for programmers
@chapter Interfaces for programmers
@example
\relative c'' @{
- \override Flag #'X-offset = #(lambda (flag)
+ \override Flag.X-offset = #(lambda (flag)
(let ((default (ly:flag::calc-x-offset flag)))
(* default 4.0)))
c4. d8 a4. g8
@node Lists
@unnumberedsubsubsec Lists
-A very common Scheme data structure is the @emph{list}. Formally, a
-list is defined as either the empty list (represented as @code{'()},
-or a pair whose @code{cdr} is a list.
+A very common Scheme data structure is the @emph{list}. Formally,
+a @q{proper} list is defined to be either the empty list with its
+input form @code{'()} and length@tie{}0, or a pair whose
+@code{cdr} in turn is a shorter list.
There are many ways of creating lists. Perhaps the most common is
with the @code{list} procedure:
plusieurs portées de taille différente sur une même page :
@c Grieg's Violin Sonata Op. 45
-@lilypond[indent=1.5cm]
+@lilypond[indent=1.5\cm]
global = {
\time 6/8
\key c \minor
Guide, node Updating translation committishes..
@end ignore
-@c \version "2.19.2"
+@c \version "2.19.12"
@c Translators: Valentin Villenave, Jean-Charles Malahieude
@c Translation checkers: Gilles Thibault
@example
\relative c'' @{
- \override Flag #'X-offset = #(lambda (flag)
+ \override Flag.X-offset = #(lambda (flag)
(let ((default (ly:flag::calc-x-offset flag)))
(* default 4.0)))
c4. d8 a4. g8
Guide, node Updating translation committishes..
@end ignore
-@c \version "2.17.11"
+@c \version "2.18.0"
@c Translators: Jean-Charles Malahieude
Guide, node Updating translation committishes..
@end ignore
-@c \version "2.17.30"
+@c \version "2.19.12"
@c Translators: Frédéric Chiasson, Jean-Charles Malahieude
@example
\paper @{
- system-system-spacing #'basic-distance = #8
+ system-system-spacing.basic-distance = #8
score-system-spacing =
#'((padding . 1)
Guide, node Updating translation committishes..
@end ignore
-@c \version "2.17.30"
+@c \version "2.19.12"
@c Translators: Yoshiki Sawada
@example
\paper @{
- system-system-spacing #'basic-distance = #8
+ system-system-spacing.basic-distance = #8
score-system-spacing =
#'((basic-distance . 12)
(minimum-distance . 6)
@code{\layout} ブロックの構成は以下のようになります:
@example
- TextScript #'padding = #1
- TextScript #'color = #magenta
- Glissando #'thickness = #1.5
- NoteHead #' font-size = #4
- NoteHead #' color = #red
+ TextScript.padding = #1
+ TextScript.color = #magenta
+ Glissando.thickness = #1.5
+ NoteHead.font-size = #4
+ NoteHead.color = #red
@end example
これに @code{indent} と @code{StaffGrouper} の設定がプラスしたものです。
場合、カレントの構成は以下だけになってしまいます:
@example
- NoteHead #' font-size= #4 % (変数定義で記述されたものです)
- NoteHead #' color = #red % (変数が使用された後に追加されたものです)
+ NoteHead.font-size= #4 % (変数定義で記述されたものです)
+ NoteHead.color = #red % (変数が使用された後に追加されたものです)
@end example
注意深く計画を立てれば、@code{\layout} 変数はソースのレイアウト設計を構築@c
-\version "2.17.30"
+\version "2.19.12"
\layout {
indent = #0
printfirst-page-number = ##t
print-page-number = ##t
ragged-last-bottom = ##t
- markup-system-spacing #'minimum-distance = #25
+ markup-system-spacing.minimum-distance = #25
}
#(set-global-staff-size 14)
The way in which the notation contained within an input file is
interpreted is determined by the current input mode.
-@strong{Chord mode}
+@subsubsubheading Chord mode
This is activated with the @code{\chordmode} command, and causes
input to be interpreted with the syntax of chord notation, see
chord notation and rendered as chord names in the @code{ChordNames}
context, see @ref{Printing chord names}.
-@strong{Drum mode}
+@subsubsubheading Drum mode
This is activated with the @code{\drummode} command, and causes
input to be interpreted with the syntax of drum notation, see
Drum mode is also activated with the @code{\drums} command.
This also creates a new @code{DrumStaff} context and causes the
following input to be interpreted with the syntax of drum notation
-and rendered as drum symbols on a drum staff, see @ref{Basic
-percussion notation}.
+and rendered as drum symbols on a drum staff, see
+@ref{Basic percussion notation}.
-@strong{Figure mode}
+@subsubsubheading Figure mode
This is activated with the @code{\figuremode} command, and causes
input to be interpreted with the syntax of figured bass, see
and rendered as figured bass symbols in the @code{FiguredBass}
context, see @ref{Introduction to figured bass}.
-@strong{Fret and tab modes}
+@subsubsubheading Fret and tab modes
There are no special input modes for entering fret and tab symbols.
above the notes using the @code{\fret-diagram} command (see
@ref{Fret diagram markups}).
-@strong{Lyrics mode}
+@subsubsubheading Lyrics mode
This is activated with the @code{\lyricmode} command, and causes
input to be interpreted as lyric syllables with optional durations
@code{\lyricsto} command which associates the following lyrics
with the preceding music.
-@strong{Markup mode}
+@subsubsubheading Markup mode
This is activated with the @code{\markup} command, and causes
input to be interpreted with the syntax of markup, see
@ref{Text markup commands}.
-@c silly work-around for texinfo broken-ness
-@c (@strong{Note...} causes a spurious cross-reference in Info)
-@b{Note mode}
+@subsubsubheading Note mode
This is the default mode or it may be activated with the
@code{\notemode} command. Input is interpreted as pitches,
are in lyric mode, chord mode or any other mode and want to insert
something that only can be done with note mode syntax.
-For example, to indicate dynamic markings for the verses of a
-choral pieces it is necessary to enter note mode to interpret
-the markings:
-
-@lilypond[verbatim,relative=2,quote]
-{ c4 c4 c4 c4 }
-\addlyrics {
- \notemode{\set stanza = \markup{ \dynamic f 1. } }
- To be sung loudly
-}
-\addlyrics {
- \notemode{\set stanza = \markup{ \dynamic p 2. } }
- To be sung quietly
-}
-@end lilypond
-
-
@node Direction and placement
@subsection Direction and placement
of the mode of entry, unless there are inversions or added bass notes:
@lilypond[verbatim,quote]
-chordmusic = \relative c' {
+chordmusic = \relative c' {
<c e g>2 <f bes c>
<f c' e g>1
\chordmode {
Guide, node Updating translation committishes..
@end ignore
-@c \version "2.17.11"
+@c \version "2.18.0"
@node Editorial annotations
@section Editorial annotations
@end multitable
+@cindex drums, various
+@cindex acoustic bass
+@cindex bass
+@cindex snare
+@cindex electric snare
+@cindex acoustic snare
+@cindex tom tom
+@cindex bongo
+@cindex conga
+@cindex timbale
+@cindex sidestick
+@cindex floor tom tom
+@cindex low tom tom
+@cindex high tom tom
+@cindex mid tom tom
+@cindex high hat
+@cindex pedal high hat
+@cindex open high hat
+@cindex half-open high hat
+@cindex cymbal, various
+@cindex crash cymbal
+@cindex ride cymbal
+@cindex chinese cymbal
+@cindex splash cymbal
+@cindex ride bell
+@cindex cowbell
+@cindex agogo
+@cindex high bongo
+@cindex low bongo
+@cindex mute bongo
+@cindex open bongo
+@cindex high conga
+@cindex low conga
+@cindex mute conga
+@cindex open conga
+@cindex high timbale
+@cindex low timbale
+@cindex mute timbale
+@cindex open timbale
+@cindex sidestick
+@cindex guiro
+@cindex cabasa
+@cindex maracas
+@cindex whistle
+@cindex handclap
+@cindex tambourine
+@cindex vibraslap
+@cindex tam tam
+@cindex claves
+@cindex woodblock
+@cindex cuica
+@cindex triangle
@node Percussion notes
@appendixsec Percussion notes
-@lilypondfile[quote]{percussion-chart.ly}
+@multitable @columnfractions .22 .25 .25 .25
+
+@item
+@code{bassdrum @* bd @*}
+@lilypond[notime,ragged-right]
+\drums { bd4 bd1 }
+@end lilypond
+@tab
+@code{acousticbassdrum @* bda @*}
+@lilypond[notime,ragged-right]
+\drums { bda4 bda1 }
+@end lilypond
+@tab
+@code{snare @* sn @*}
+@lilypond[notime,ragged-right]
+\drums { sn4 sn1 }
+@end lilypond
+@tab
+@code{acousticsnare @* sna @*}
+@lilypond[notime,ragged-right]
+\drums { sna4 sna1 }
+@end lilypond
+
+@item
+@code{electricsnare @* sne @*}
+@lilypond[notime,ragged-right]
+\drums { sne4 sne1 }
+@end lilypond
+@tab
+@code{lowfloortom @* tomfl @*}
+@lilypond[notime,ragged-right]
+\drums { tomfl4 tomfl1 }
+@end lilypond
+@tab
+@code{highfloortom @* tomfh @*}
+@lilypond[notime,ragged-right]
+\drums { tomfh4 tomfh1 }
+@end lilypond
+@tab
+@code{lowtom @* toml @*}
+@lilypond[notime,ragged-right]
+\drums { toml4 toml1 }
+@end lilypond
+
+@item
+@code{hightom @* tomh @*}
+@lilypond[notime,ragged-right]
+\drums { tomh4 tomh1 }
+@end lilypond
+@tab
+@code{lowmidtom @* tomml @*}
+@lilypond[notime,ragged-right]
+\drums { tomml4 tomml1 }
+@end lilypond
+@tab
+@code{highmidtom @* tommh @*}
+@lilypond[notime,ragged-right]
+\drums { tommh4 tommh1 }
+@end lilypond
+@tab
+@code{highhat @* hh @*}
+@lilypond[notime,ragged-right]
+\drums { hh4 hh1 }
+@end lilypond
+
+@item
+@code{closedhihat @* hhc @*}
+@lilypond[notime,ragged-right]
+\drums { hhc4 hhc1 }
+@end lilypond
+@tab
+@code{openhighhat @* hho @*}
+@lilypond[notime,ragged-right]
+\drums { hho4 hho1 }
+@end lilypond
+@tab
+@code{halfopenhihat @* hhho @*}
+@lilypond[notime,ragged-right]
+\drums { hhho4 hhho1 }
+@end lilypond
+@tab
+@code{pedalhihat @* hhp @*}
+@lilypond[notime,ragged-right]
+\drums { hhp4 hhp1 }
+@end lilypond
+
+
+@item
+@code{crashcymbal @* cymc @*}
+@lilypond[notime,ragged-right]
+\drums { cymc4 cymc1 }
+@end lilypond
+@tab
+@code{crashcymbala @* cymca @*}
+@lilypond[notime,ragged-right]
+\drums { cymca4 cymca1 }
+@end lilypond
+@tab
+@code{crashcymbalb @* cymcb @*}
+@lilypond[notime,ragged-right]
+\drums { cymcb4 cymcb1 }
+@end lilypond
+@tab
+@code{ridecymbal @* cymr @*}
+@lilypond[notime,ragged-right]
+\drums { cymr4 cymr1 }
+@end lilypond
+
+@item
+@code{ridecymbala @* cymra @*}
+@lilypond[notime,ragged-right]
+\drums { cymra4 cymra1 }
+@end lilypond
+@tab
+@code{ridecymbalb @* cymrb @*}
+@lilypond[notime,ragged-right]
+\drums { cymrb4 cymrb1 }
+@end lilypond
+@tab
+@code{chinesecymbal @* cymch @*}
+@lilypond[notime,ragged-right]
+\drums { cymch4 cymch1 }
+@end lilypond
+@tab
+@code{splashcymbal @* cyms @*}
+@lilypond[notime,ragged-right]
+\drums { cyms4 cyms1 }
+@end lilypond
+
+@item
+@code{ridebell @* rb @*}
+@lilypond[notime,ragged-right]
+\drums { rb4 rb1 }
+@end lilypond
+@tab
+@code{cowbell @* cb @*}
+@lilypond[notime,ragged-right]
+\drums { cb4 cb1 }
+@end lilypond
+@tab
+@code{hibongo @* boh @*}
+@lilypond[notime,ragged-right]
+\drums { boh4 boh1 }
+@end lilypond
+@tab
+@code{openhibongo @* boho @*}
+@lilypond[notime,ragged-right]
+\drums { boho4 boho1 }
+@end lilypond
+
+@item
+@code{mutehibongo @* bohm @*}
+@lilypond[notime,ragged-right]
+\drums { bohm4 bohm1 }
+@end lilypond
+@tab
+@code{lobongo @* bol @*}
+@lilypond[notime,ragged-right]
+\drums { bol4 bol1 }
+@end lilypond
+@tab
+@code{openlobongo @* bolo @*}
+@lilypond[notime,ragged-right]
+\drums { bolo4 bolo1 }
+@end lilypond
+@tab
+@code{mutelobongo @* bolm @*}
+@lilypond[notime,ragged-right]
+\drums { bolm4 bolm1 }
+@end lilypond
+
+
+@item
+@code{hiconga @* cgh @*}
+@lilypond[notime,ragged-right]
+\drums { cgh4 cgh1 }
+@end lilypond
+@tab
+@code{openhiconga @* cgho @*}
+@lilypond[notime,ragged-right]
+\drums { cgho4 cgho1 }
+@end lilypond
+@tab
+@code{mutehiconga @* cghm @*}
+@lilypond[notime,ragged-right]
+\drums { cghm4 cghm1 }
+@end lilypond
+@tab
+@code{loconga @* cgl @*}
+@lilypond[notime,ragged-right]
+\drums { cgl4 cgl1 }
+@end lilypond
+
+@item
+@code{openloconga @* cglo @*}
+@lilypond[notime,ragged-right]
+\drums { cglo4 cglo1 }
+@end lilypond
+@tab
+@code{muteloconga @* cglm @*}
+@lilypond[notime,ragged-right]
+\drums { cglm4 cglm1 }
+@end lilypond
+@tab
+@code{hitimbale @* timh @*}
+@lilypond[notime,ragged-right]
+\drums { timh4 timh1 }
+@end lilypond
+@tab
+@code{lotimbale @* timl @*}
+@lilypond[notime,ragged-right]
+\drums { timl4 timl1 }
+@end lilypond
+
+@item
+@code{hiagogo @* agh @*}
+@lilypond[notime,ragged-right]
+\drums { agh4 agh1 }
+@end lilypond
+@tab
+@code{loagogo @* agl @*}
+@lilypond[notime,ragged-right]
+\drums { agl4 agl1 }
+@end lilypond
+@tab
+@code{sidestick @* ss @*}
+@lilypond[notime,ragged-right]
+\drums { ss4 ss1 }
+@end lilypond
+@tab
+@code{hisidestick @* ssh @*}
+@lilypond[notime,ragged-right]
+\drums { ssh4 ssh1 }
+@end lilypond
+
+@item
+@code{losidestick @* ssl @*}
+@lilypond[notime,ragged-right]
+\drums { ssl4 ssl1 }
+@end lilypond
+@tab
+@code{guiro @* gui @*}
+@lilypond[notime,ragged-right]
+\drums { gui4 gui1 }
+@end lilypond
+@tab
+@code{shortguiro @* guis @*}
+@lilypond[notime,ragged-right]
+\drums { guis4 guis1 }
+@end lilypond
+@tab
+@code{longguiro @* guil @*}
+@lilypond[notime,ragged-right]
+\drums { guil4 guil1 }
+@end lilypond
+
+@item
+@code{cabasa @* cab @*}
+@lilypond[notime,ragged-right]
+\drums { cab4 cab1 }
+@end lilypond
+@tab
+@code{maracas @* mar @*}
+@lilypond[notime,ragged-right]
+\drums { mar4 mar1 }
+@end lilypond
+@tab
+@code{shortwhistle @* whs @*}
+@lilypond[notime,ragged-right]
+\drums { whs4 whs1 }
+@end lilypond
+@tab
+@code{longwhistle @* whl @*}
+@lilypond[notime,ragged-right]
+\drums { whl4 whl1 }
+@end lilypond
+
+@item
+@code{handclap @* hc @*}
+@lilypond[notime,ragged-right]
+\drums { hc4 hc1 }
+@end lilypond
+@tab
+@code{tambourine @* tamb @*}
+@lilypond[notime,ragged-right]
+\drums { tamb4 tamb1 }
+@end lilypond
+@tab
+@code{vibraslap @* vibs @*}
+@lilypond[notime,ragged-right]
+\drums { vibs4 vibs1 }
+@end lilypond
+@tab
+@code{tamtam @* tt @*}
+@lilypond[notime,ragged-right]
+\drums { tt4 tt1 }
+@end lilypond
+
+@item
+@code{claves @* cl @*}
+@lilypond[notime,ragged-right]
+\drums { cl4 cl1 }
+@end lilypond
+@tab
+@code{hiwoodblock @* wbh @*}
+@lilypond[notime,ragged-right]
+\drums { wbh4 wbh1 }
+@end lilypond
+@tab
+@code{lowoodblock @* wbl @*}
+@lilypond[notime,ragged-right]
+\drums { wbl4 wbl1 }
+@end lilypond
+@tab
+@code{opencuica @* cuio @*}
+@lilypond[notime,ragged-right]
+\drums { cuio4 cuio1 }
+@end lilypond
+
+@item
+@code{mutecuica @* cuim @*}
+@lilypond[notime,ragged-right]
+\drums { cuim4 cuim1 }
+@end lilypond
+@tab
+@code{triangle @* tri @*}
+@lilypond[notime,ragged-right]
+\drums { tri4 tri1 }
+@end lilypond
+@tab
+@code{opentriangle @* trio @*}
+@lilypond[notime,ragged-right]
+\drums { trio4 trio1 }
+@end lilypond
+@tab
+@code{mutetriangle @* trim}
+@lilypond[notime,ragged-right]
+\drums { trim4 trim1 }
+@end lilypond
+
+@item
+@code{oneup @* ua @*}
+@lilypond[notime,ragged-right]
+\drums { ua4 ua1 }
+@end lilypond
+@tab
+@code{twoup @* ub @*}
+@lilypond[notime,ragged-right]
+\drums { ub4 ub1 }
+@end lilypond
+@tab
+@code{threeup @* uc @*}
+@lilypond[notime,ragged-right]
+\drums { uc4 uc1 }
+@end lilypond
+@tab
+@code{fourup @* ud @*}
+@lilypond[notime,ragged-right]
+\drums { ud4 ud1 }
+@end lilypond
+
+@item
+@code{fiveup @* ue @*}
+@lilypond[notime,ragged-right]
+\drums { ue4 ue1 }
+@end lilypond
+@tab
+@code{onedown @* da @*}
+@lilypond[notime,ragged-right]
+\drums { da4 da1 }
+@end lilypond
+@tab
+@code{twodown @* db @*}
+@lilypond[notime,ragged-right]
+\drums { db4 db1 }
+@end lilypond
+@tab
+@code{threedown @* dc @*}
+@lilypond[notime,ragged-right]
+\drums { dc4 dc1 }
+@end lilypond
+
+@item
+@code{fourdown @* dd @*}
+@lilypond[notime,ragged-right]
+\drums { dd4 dd1 }
+@end lilypond
+@tab
+@code{fivedown @* de @*}
+@lilypond[notime,ragged-right]
+\drums { de4 de1 }
+@end lilypond
+
+
+@end multitable
@node Technical glossary
Guide, node Updating translation committishes..
@end ignore
-@c \version "2.17.30"
+@c \version "2.19.12"
@ignore
GDP TODO list
@example
\paper @{
- system-system-spacing #'basic-distance = #8
+ system-system-spacing.basic-distance = #8
score-system-spacing =
#'((basic-distance . 12)
(minimum-distance . 6)
>>
@end lilypond
-The @code{NullVoice} context must be placed within a @code{Staff}
-context and contain notes that are already being displayed in that staff and that are also in the same octave. Otherwise the
-@code{NullVoice} may interact with the printed voices in
-unexpected ways. For example, arbitrary notes in the
-@code{NullVoice} may cause accidentals to appear (or disappear) on
-the staff.
-
This method also can be used with the @code{\partcombine}
function, which does not allow lyrics on its own:
words = \lyricmode { la __ la __ }
\new ChoirStaff <<
- \new Staff <<
- \soprano
- \new NullVoice = "aligner" \aligner
- >>
+ \new Staff \soprano
+ \new NullVoice = "aligner" \aligner
\new Lyrics \lyricsto "aligner" \words
\new Staff \partcombine \altoOne \altoTwo
>>
@end lilypond
-However, note that in the second half of the measure above, the
-notes in the @code{NullVoice} context reflect the rhythm of the
-lower staff, but they do not deviate from the single pitch being
-displayed in the staff to which the @code{NullVoice} belongs.
-While not actually required in this particular example, it is a
-good idea in general to enter the notes in this way.
-
-
@node Stanzas
@subsection Stanzas
Alternatively, if there are many character changes, it may be
easier to set up @qq{instrument} definitions for each character at
the top level so that @code{\instrumentSwitch} can be used to
-indicate each change.
+indicate each change. As notes for vocal parts are usually entered
+at sounding pitch no instrument transposition is required, even
+when, as here, the tenor line is printed an octave higher.
@lilypond[quote,verbatim]
\addInstrumentDefinition #"kaspar"
- #`((instrumentTransposition . ,(ly:make-pitch -1 0 0))
+ #`((instrumentTransposition . ,(ly:make-pitch 0 0 0))
(shortInstrumentName . "Kas.")
(clefGlyph . "clefs.G")
(clefTransposition . -7)
-%% DO NOT EDIT this file manually; it is automatically
-%% generated from LSR http://lsr.di.unimi.it
-%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
-%% and then run scripts/auxiliar/makelsr.py
-%%
-%% This file is in the public domain.
-\version "2.18.0"
+% DO NOT EDIT this file manually; it is automatically
+% generated from Documentation/snippets/new
+% Make any changes in Documentation/snippets/new/
+% and then run scripts/auxiliar/makelsr.py
+%
+% This file is in the public domain.
+%% Note: this file works from version 2.19.12
+\version "2.19.12"
\header {
lsrtags = "devel, scheme-language, tweaks-and-overrides"
@{
- \\once \\override NoteHead #'before-line-breaking = #display-ancestry
+ \\once \\override NoteHead.before-line-breaking = #display-ancestry
c @}
--- /dev/null
+\version "2.19.12"
+
+\header {
+ lsrtags = "devel, scheme-language, tweaks-and-overrides"
+
+ texidoc = "
+When working with grob callbacks, it can be helpful to understand a
+grob's @qq{ancestry}. Most grobs have @qq{parents} which influence the
+positioning of the grob. X- and Y-parents influence the horizontal and
+vertical positions for the grob, respectively. Additionally, each
+parent may have parents of its own.
+
+
+Unfortunately, there are several aspects of a grob's ancestry that can
+lead to confusion:
+
+* The types of parents a grob has may depend on context. * For some
+grobs, the X- and Y-parents are the same. * A particular @qq{ancestor}
+may be related to a grob in multiple ways. * The concept of
+@qq{generations} is misleading.
+
+
+For example, the @code{System} grob can be both parent (on the Y-side)
+and grandparent (twice on the X-side) to a @code{VerticalAlignment}
+grob.
+
+
+This macro prints (to the console) a textual representation of a grob's
+ancestry.
+
+
+When called this way
+
+
+@{
+ \\once \\override NoteHead.before-line-breaking = #display-ancestry
+ c @}
+
+
+The following output is generated:
+
+
+------------------------------------
+
+NoteHead X,Y: NoteColumn
+ X: PaperColumn
+ X,Y: System
+ Y: VerticalAxisGroup
+ X: NonMusicalPaperColumn
+ X,Y: System
+ Y: VerticalAlignment
+ X: NonMusicalPaperColumn
+ X,Y: System
+ Y: System
+
+
+
+"
+ doctitle = "Displaying grob ancestry"
+}
+%% http://lsr.di.unimi.it/LSR/Item?id=622
+%% see also http://www.lilypond.org/doc/v2.18/Documentation/snippets/tweaks-and-overrides#tweaks-and-overrides-displaying-grob-ancestry
+
+#(define (grob-name grob)
+ (if (ly:grob? grob)
+ (assoc-ref (ly:grob-property grob 'meta) 'name)
+ #f))
+
+#(define (get-ancestry grob)
+ (if (not (null? (ly:grob-parent grob X)))
+ (list (grob-name grob)
+ (get-ancestry (ly:grob-parent grob X))
+ (get-ancestry (ly:grob-parent grob Y)))
+ (grob-name grob)))
+
+#(define (format-ancestry lst padding)
+ (string-append
+ (symbol->string (car lst))
+ "\n"
+ (let ((X-ancestry
+ (if (list? (cadr lst))
+ (format-ancestry (cadr lst) (+ padding 3))
+ (symbol->string (cadr lst))))
+ (Y-ancestry
+ (if (list? (caddr lst))
+ (format-ancestry (caddr lst) (+ padding 3))
+ (symbol->string (caddr lst)))))
+ (if (equal? X-ancestry Y-ancestry)
+ (string-append
+ (format #f "~&")
+ (make-string padding #\space)
+ "X,Y: "
+ (if (list? (cadr lst))
+ (format-ancestry (cadr lst) (+ padding 5))
+ (symbol->string (cadr lst))))
+ (string-append
+ (format #f "~&")
+ (make-string padding #\space)
+ "X: " X-ancestry
+ "\n"
+ (make-string padding #\space)
+ "Y: " Y-ancestry
+ (format #f "~&"))))
+ (format #f "~&")))
+
+#(define (display-ancestry grob)
+ (format (current-error-port)
+ "~3&~a~2%~a~&"
+ (make-string 36 #\-)
+ (format-ancestry (get-ancestry grob) 0)))
+
+\relative c' {
+ \once \override NoteHead.before-line-breaking = #display-ancestry
+ f4
+ \once \override Accidental.before-line-breaking = #display-ancestry
+ \once \override Arpeggio.before-line-breaking = #display-ancestry
+ <f as c>4\arpeggio
+}
--- /dev/null
+\version "2.19.12"
+
+\header {
+ lsrtags = "automatic-notation, keyboards, template, vocal-music"
+
+ texidoc = "
+This template adds an automatic piano reduction to the standard SATB
+vocal score demonstrated in @qq{Vocal ensemble template}. This
+demonstrates one of the strengths of LilyPond – you can use a music
+definition more than once. If any changes are made to the vocal notes
+(say, @code{tenorMusic}), then the changes will also apply to the piano
+reduction.
+
+"
+ doctitle = "Vocal ensemble template with automatic piano reduction"
+}
+\paper {
+ top-system-spacing.basic-distance = #10
+ score-system-spacing.basic-distance = #20
+ system-system-spacing.basic-distance = #20
+ last-bottom-spacing.basic-distance = #10
+}
+
+global = {
+ \key c \major
+ \time 4/4
+}
+
+sopMusic = \relative c'' {
+ c4 c c8[( b)] c4
+}
+sopWords = \lyricmode {
+ hi hi hi hi
+}
+
+altoMusic = \relative c' {
+ e4 f d e
+}
+altoWords =\lyricmode {
+ ha ha ha ha
+}
+
+tenorMusic = \relative c' {
+ g4 a f g
+}
+tenorWords = \lyricmode {
+ hu hu hu hu
+}
+
+bassMusic = \relative c {
+ c4 c g c
+}
+bassWords = \lyricmode {
+ ho ho ho ho
+}
+
+\score {
+ <<
+ \new ChoirStaff <<
+ \new Lyrics = "sopranos" \with {
+ % This is needed for lyrics above a staff
+ \override VerticalAxisGroup.staff-affinity = #DOWN
+ }
+ \new Staff = "women" <<
+ \new Voice = "sopranos" { \voiceOne << \global \sopMusic >> }
+ \new Voice = "altos" { \voiceTwo << \global \altoMusic >> }
+ >>
+ \new Lyrics = "altos"
+ \new Lyrics = "tenors" \with {
+ % This is needed for lyrics above a staff
+ \override VerticalAxisGroup.staff-affinity = #DOWN
+ }
+
+ \new Staff = "men" <<
+ \clef bass
+ \new Voice = "tenors" { \voiceOne << \global \tenorMusic >> }
+ \new Voice = "basses" { \voiceTwo << \global \bassMusic >> }
+ >>
+ \new Lyrics = "basses"
+ \context Lyrics = "sopranos" \lyricsto "sopranos" \sopWords
+ \context Lyrics = "altos" \lyricsto "altos" \altoWords
+ \context Lyrics = "tenors" \lyricsto "tenors" \tenorWords
+ \context Lyrics = "basses" \lyricsto "basses" \bassWords
+ >>
+ \new PianoStaff <<
+ \new Staff <<
+ \set Staff.printPartCombineTexts = ##f
+ \partcombine
+ << \global \sopMusic >>
+ << \global \altoMusic >>
+ >>
+ \new Staff <<
+ \clef bass
+ \set Staff.printPartCombineTexts = ##f
+ \partcombine
+ << \global \tenorMusic >>
+ << \global \bassMusic >>
+ >>
+ >>
+ >>
+}
--- /dev/null
+\version "2.19.12"
+
+\header {
+ lsrtags = "really-simple, template, vocal-music"
+
+ texidoc = "
+Here is a standard four-part SATB vocal score. With larger ensembles,
+it is often useful to include a section which is included in all parts.
+For example, the time signature and key signature are almost always the
+same for all parts. Like in the @qq{Hymn} template, the four voices are
+regrouped on only two staves.
+
+"
+ doctitle = "Vocal ensemble template"
+}
+\paper {
+ top-system-spacing.basic-distance = #10
+ score-system-spacing.basic-distance = #20
+ system-system-spacing.basic-distance = #20
+ last-bottom-spacing.basic-distance = #10
+}
+
+global = {
+ \key c \major
+ \time 4/4
+}
+
+sopMusic = \relative c'' {
+ c4 c c8[( b)] c4
+}
+sopWords = \lyricmode {
+ hi hi hi hi
+}
+
+altoMusic = \relative c' {
+ e4 f d e
+}
+altoWords = \lyricmode {
+ ha ha ha ha
+}
+
+tenorMusic = \relative c' {
+ g4 a f g
+}
+tenorWords = \lyricmode {
+ hu hu hu hu
+}
+
+bassMusic = \relative c {
+ c4 c g c
+}
+bassWords = \lyricmode {
+ ho ho ho ho
+}
+
+\score {
+ \new ChoirStaff <<
+ \new Lyrics = "sopranos" \with {
+ % this is needed for lyrics above a staff
+ \override VerticalAxisGroup.staff-affinity = #DOWN
+ }
+ \new Staff = "women" <<
+ \new Voice = "sopranos" {
+ \voiceOne
+ << \global \sopMusic >>
+ }
+ \new Voice = "altos" {
+ \voiceTwo
+ << \global \altoMusic >>
+ }
+ >>
+ \new Lyrics = "altos"
+ \new Lyrics = "tenors" \with {
+ % this is needed for lyrics above a staff
+ \override VerticalAxisGroup.staff-affinity = #DOWN
+ }
+ \new Staff = "men" <<
+ \clef bass
+ \new Voice = "tenors" {
+ \voiceOne
+ << \global \tenorMusic >>
+ }
+ \new Voice = "basses" {
+ \voiceTwo << \global \bassMusic >>
+ }
+ >>
+ \new Lyrics = "basses"
+ \context Lyrics = "sopranos" \lyricsto "sopranos" \sopWords
+ \context Lyrics = "altos" \lyricsto "altos" \altoWords
+ \context Lyrics = "tenors" \lyricsto "tenors" \tenorWords
+ \context Lyrics = "basses" \lyricsto "basses" \bassWords
+ >>
+}
-%% DO NOT EDIT this file manually; it is automatically
-%% generated from LSR http://lsr.di.unimi.it
-%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
-%% and then run scripts/auxiliar/makelsr.py
-%%
-%% This file is in the public domain.
-\version "2.18.0"
+% DO NOT EDIT this file manually; it is automatically
+% generated from Documentation/snippets/new
+% Make any changes in Documentation/snippets/new/
+% and then run scripts/auxiliar/makelsr.py
+%
+% This file is in the public domain.
+%% Note: this file works from version 2.19.12
+\version "2.19.12"
\header {
lsrtags = "automatic-notation, keyboards, template, vocal-music"
} % begin verbatim
\paper {
- top-system-spacing #'basic-distance = #10
- score-system-spacing #'basic-distance = #20
- system-system-spacing #'basic-distance = #20
- last-bottom-spacing #'basic-distance = #10
+ top-system-spacing.basic-distance = #10
+ score-system-spacing.basic-distance = #20
+ system-system-spacing.basic-distance = #20
+ last-bottom-spacing.basic-distance = #10
}
global = {
-%% DO NOT EDIT this file manually; it is automatically
-%% generated from LSR http://lsr.di.unimi.it
-%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
-%% and then run scripts/auxiliar/makelsr.py
-%%
-%% This file is in the public domain.
-\version "2.18.0"
+% DO NOT EDIT this file manually; it is automatically
+% generated from Documentation/snippets/new
+% Make any changes in Documentation/snippets/new/
+% and then run scripts/auxiliar/makelsr.py
+%
+% This file is in the public domain.
+%% Note: this file works from version 2.19.12
+\version "2.19.12"
\header {
lsrtags = "really-simple, template, vocal-music"
} % begin verbatim
\paper {
- top-system-spacing #'basic-distance = #10
- score-system-spacing #'basic-distance = #20
- system-system-spacing #'basic-distance = #20
- last-bottom-spacing #'basic-distance = #10
+ top-system-spacing.basic-distance = #10
+ score-system-spacing.basic-distance = #20
+ system-system-spacing.basic-distance = #20
+ last-bottom-spacing.basic-distance = #10
}
global = {
@c used for news about the upcoming release; see CG 10.2
@newsItem
-@subsubheading LilyPond 2.19.11 released @emph{August 3, 2014}
+@subsubheading LilyPond 2.19.12 released @emph{August 17, 2014}
-We are happy to announce the release of LilyPond 2.19.11. This
+We are happy to announce the release of LilyPond 2.19.12. This
release includes a number of enhancements, and contains some work
in progress. You will have access to the very latest features, but
some may be incomplete, and you may encounter bugs and crashes. If you
* don't duplicate entries from news-front.itexi
@end ignore
+@newsItem
+@subsubheading LilyPond 2.19.11 released @emph{August 3, 2014}
+
+We are happy to announce the release of LilyPond 2.19.11. This
+release includes a number of enhancements, and contains some work
+in progress. You will have access to the very latest features, but
+some may be incomplete, and you may encounter bugs and crashes. If you
+require a stable version of Lilypond, we recommend using the 2.18
+version.
+
+@newsEnd
+
@newsItem
@subsubheading LilyPond 2.19.10 released @emph{July 13, 2014}
PACKAGE_NAME=LilyPond
MAJOR_VERSION=2
MINOR_VERSION=19
-PATCH_LEVEL=12
+PATCH_LEVEL=13
MY_PATCH_LEVEL=
VERSION_STABLE=2.18.2
-VERSION_DEVEL=2.19.11
+VERSION_DEVEL=2.19.12
\header {
-texidoc = "Tied notes with accidentals do not cause problems with spacing."
+texidoc = "Space is allowed for the actual size of accidentals on tied notes."
}
-\version "2.16.0"
-
+\version "2.19.13"
+\paper {ragged-right = ##t }
\relative c' {
\clef treble
\time 3/4
c8 b2 <g b des f>8 ~ |
- <g b des f>8
+ <g b des f>8 r
+ % Large accidental
+ \override Staff.Accidental.stencil =
+ #(lambda (g)
+ (let ((alt (ly:grob-property g 'alteration)))
+ (grob-interpret-markup g
+ (make-circle-markup (number->string alt)))))
+ bes4 ~ bes ~ | bes ~ bes bes ~ | \break
+ bes ~ bes bes
}
-\version "2.17.10"
+\version "2.19.12"
\header {
texidoc = "@code{add-stem-support} can be removed or implemented
{
\music
- \override Fingering #'add-stem-support = ##f
+ \override Fingering.add-stem-support = ##f
\music
- \override Fingering #'add-stem-support = #only-if-beamed
+ \override Fingering.add-stem-support = #only-if-beamed
\music
}
\ No newline at end of file
-\version "2.17.6"
+\version "2.19.12"
forcedLastBreak = {} %% { \break } if needed to match original breaks
ragged-bottom = ##t
indent = 7. \mm
line-width =183.5 \mm
- system-system-spacing #'basic-distance = 14.22 % 25mm, in staff-spaces
- system-system-spacing #'padding = #0
- score-system-spacing #'basic-distance = #0
- score-system-spacing #'padding = #0
+ system-system-spacing.basic-distance = 14.22 % 25mm, in staff-spaces
+ system-system-spacing.padding = #0
+ score-system-spacing.basic-distance = #0
+ score-system-spacing.padding = #0
system-count = 6
%% annotatespacing = ##t
-\version "2.16.0"
+\version "2.18.0"
\header {
texidoc="Transposition symbols should be correctly positioned
-close to the parent clef."
+close to the parent clef. Horizontal alignment is fine-tuned
+for standard C, G and F clefs: for example, downwards transposition
+of a G clef should be centered exactly under the middle of clef hook.
+For clefs that don't have fine-tuned alignment the transposition
+number should be centered."
}
+
+% use huge staff-size to see the tiny differencies better.
+#(set-global-staff-size 35)
+
+clefVariations =
+#(define-music-function (parser location type)(string?)
+ #{
+ \once \omit Staff.Clef s4
+ \override Staff.Clef.full-size-change = ##t
+ \clef #(string-append type "8") s4
+ \clef #(string-append type "15") s4
+ \clef #(string-append type "(8)") s4
+ \clef #(string-append type "(141)") s4
+ % change clefs are omitted - too similar to regular ones
+ \cueClef #(string-append type "8") s4
+ \cueClef #(string-append type "15") s4
+ \cueClef #(string-append type "(8)") s4
+ \cueClef #(string-append type "(141)") s4
+ #})
+
+\markup "Even the smallest positioning changes may indicate a problem!"
\score {
<<
- \new Staff { \clef "G^8" g''1 }
- \new Staff { \clef "F^8" c'1 }
- \new Staff { \clef "C^8" c''1 }
- \new Staff { \clef "G_8" g1 }
- \new Staff { \clef "F_8" c,1 }
- \new Staff { \clef "C_8" c1 }
+ \new Staff { \clefVariations "C_" }
+ \new Staff { \clefVariations "C^" }
+ \new Staff { \clefVariations "G_" }
+ \new Staff { \clefVariations "G^" }
+ \new Staff { \clefVariations "F_" }
+ \new Staff { \clefVariations "F^" }
>>
}
+
+\layout {
+ \context {
+ \Staff
+ \remove Time_signature_engraver
+ }
+}
\ No newline at end of file
--- /dev/null
+\version "2.19.13"
+
+\header {
+ texidoc = "The @code{VerticalAxisGroup.remove-layer}
+property can be used for typesetting temporary divisi staves where
+the switch to split staves is done only at line breaks such that all
+complex passages are rendered in separate staves."
+}
+
+boring = \set Staff.keepAliveInterfaces = #'()
+tricky = \unset Staff.keepAliveInterfaces
+
+violI=\relative d' {
+ \boring \repeat unfold 100 d4
+ \tricky <d g'>2
+ \boring \repeat unfold 98 d4
+ \bar "|."
+}
+
+violII=\relative g {
+ \boring \repeat unfold 100 g4
+ \tricky <g d'>2
+ \boring \repeat unfold 98 g4
+ \bar "|."
+}
+
+\score {
+ \new StaffGroup \with { \consists "Keep_alive_together_engraver" }
+ <<
+ \new Staff \with { instrumentName = "Violin I"
+ shortInstrumentName = "V I"
+ \override VerticalAxisGroup.remove-empty = ##t
+ \override VerticalAxisGroup.remove-first = ##t
+ \override VerticalAxisGroup.remove-layer = 1
+ }
+ \violI
+ \new Staff \with { instrumentName = "Violin II"
+ shortInstrumentName = "V II"
+ \override VerticalAxisGroup.remove-empty = ##t
+ \override VerticalAxisGroup.remove-first = ##t
+ \override VerticalAxisGroup.remove-layer = 1
+ }
+ \violII
+ \new Staff \with { instrumentName = "Violins"
+ shortInstrumentName = "V I&II"
+ \override VerticalAxisGroup.remove-layer = 2
+ }
+ << \violI \\ \violII >>
+ >>
+ \layout {
+ short-indent = 2\cm
+ indent = 3\cm
+ }
+}
-\version "2.17.18"
+\version "2.19.12"
\header {
texidoc = "An empty Dynamics context does not confuse the spacing."
\layout {
\context {
\Dynamics
- \override VerticalAxisGroup #'nonstaff-relatedstaff-spacing
+ \override VerticalAxisGroup.nonstaff-relatedstaff-spacing
= #'((minimum-distance . 5))
}
}
-\version "2.17.14"
+\version "2.19.12"
\header {
texidoc = "LilyPond creates hairpins found in Ferneyhough scores.
}
\relative c'' {
- \override Hairpin #'stencil = #flared-hairpin
+ \override Hairpin.stencil = #flared-hairpin
a4\< a a a\f
a4\p\< a a a\ff
a4\sfz\< a a a\!
- \override Hairpin #'stencil = #constante-hairpin
+ \override Hairpin.stencil = #constante-hairpin
a4\< a a a\f
a4\p\< a a a\ff
a4\sfz\< a a a\!
- \override Hairpin #'stencil = #flared-hairpin
+ \override Hairpin.stencil = #flared-hairpin
a4\> a a a\f
a4\p\> a a a\ff
a4\sfz\> a a a\!
- \override Hairpin #'stencil = #constante-hairpin
+ \override Hairpin.stencil = #constante-hairpin
a4\> a a a\f
a4\p\> a a a\ff
a4\sfz\> a a a\!
XML_FILES = $(filter-out include%,$(call src-wildcard,*.xml))
-local-test: $(OUT_FILES)
+local-test:
+ make LYS_OUTPUT_DIR=$(top-build-dir)/out/lybook-testdb $(OUT_FILES)
$(outdir)/collated-files.list: $(OUT_FILES)
echo $(sort $(filter-out %.xml,$(OUT_FILES))) > $@
\version "2.16.0"
+\include "melody.ly"
\score {
- \relative c'' { \key c \minor c4 es g2 }
+ \melody
}
--- /dev/null
+\version "2.16.0"
+\include "include/myvar.ily"
+melody = \relative c'' { \key c \minor c4 es g2 \myVar }
\include "include/myvar.ily"
\relative c'' { \myVar }
\end{lilypond}
+
+Include a file that includes a file:
+
+\lilypondfile{include.ly}
+
\end{document}
\include "include/myvar.ily"
\relative c'' { \myVar }
\end{lilypond}
+
+Include a file that includes a file:
+
+\lilypondfile[quote,noindent]{include.ly}
+
\end{document}
\relative c'' { \myVar }
@end lilypond
+Include a file that includes a file:
+
+@lilypondfile{include.ly}
+
@bye
--- /dev/null
+\version "2.19.11"
+\header {
+ texidoc ="Lyrics can be aligned to a @code{NullVoice} context,
+ which prints no notes, with the usual mechanisms for melismata."
+}
+\paper { ragged-right = ##f }
+\score { <<
+ \new Staff <<
+ { c''4. g'8 c''2 | g'8( f' g'4)~ g'2 } \\
+ { c'4 b c'8 e' g' e' | c'1 }
+ \new NullVoice = "nv" {
+ \autoBeamOff c4 r16 b,8. c8[ e8 g8 e8] | g8( f g4)~ g2 }
+ >>
+ \new Lyrics \lyricsto "nv" { free a -- lign -- ment }
+>> }
-\version "2.16.0"
+\version "2.19.13"
#(ly:set-option 'warning-as-error #f)
-#(ly:expect-warning (ly:translate-cpp-warning-scheme "Cyclic markup detected: %s") 'cycle-markup)
-#(ly:expect-warning (ly:translate-cpp-warning-scheme "Cyclic markup detected: %s") 'cycleI-markup)
+#(ly:expect-warning (ly:translate-cpp-warning-scheme "Markup depth exceeds maximal value of %d; Markup: %s") 1024 'cycle-markup)
+#(ly:expect-warning (ly:translate-cpp-warning-scheme "Markup depth exceeds maximal value of %d; Markup: %s") 1024 'cycleI-markup)
\header {
texidoc = "Cyclic markup definitions should cause a warning, but
}
-\version "2.19.2"
+\version "2.19.12"
manuscriptBreak = { \break }
%#(set-global-staff-size (* 5.8 mm))
line-width = #(* mm 160)
indent = 8\mm
- system-system-spacing #'basic-distance = #10.3
+ system-system-spacing.basic-distance = #10.3
ragged-bottom = ##t
}
"
}
-\version "2.16.0"
+\version "2.19.12"
\include "mozart-hrn3-defs.ily"
\include "mozart-hrn3-allegro.ily"
\include "mozart-hrn3-rondo.ily"
\paper {
- system-system-spacing #'basic-distance = 10
- score-system-spacing #'basic-distance = 20
+ system-system-spacing.basic-distance = 10
+ score-system-spacing.basic-distance = 20
}
\book {
-\version "2.16.0"
+\version "2.19.12"
\header {
}
\paper {
- system-system-spacing
- #'basic-distance = #10 % increase this value for more space
+ system-system-spacing.basic-distance = #10 % increase this value for more space
}
notes = \relative c {
\relative c' {
\override Stem.details.beamed-lengths = #'(6 10 8)
c8[ c] c16[ c] c32[ c]
- \revert Stem.details
+ \revert Stem.details.beamed-lengths
c8[ c] c16[ c] c32[ c]
}
-\version "2.16.0"
+\version "2.19.12"
\header {
texidoc = "minimum-distance is correctly accounted for in page breaking."
\book {
\paper {
- score-system-spacing #'minimum-distance = #'20
+ score-system-spacing.minimum-distance = #'20
paper-height = 8\cm
}
}
-\version "2.17.6"
+\version "2.19.12"
#(set-global-staff-size 11)
ragged-last-bottom = ##f
annotate-spacing = ##t
obsolete-between-system-space = 1.0
- system-system-spacing #'basic-distance = #(/ obsolete-between-system-space staff-space)
- score-system-spacing #'basic-distance = #(/ obsolete-between-system-space staff-space)
+ system-system-spacing.basic-distance = #(/ obsolete-between-system-space staff-space)
+ score-system-spacing.basic-distance = #(/ obsolete-between-system-space staff-space)
#(set! text-font-defaults
(acons
'font-size 6
first system can be forced to be uniform."
}
-\version "2.17.6"
+\version "2.19.12"
#(set-default-paper-size "a6")
\paper {
obsolete-page-top-space = 3 \cm
- top-system-spacing #'basic-distance = #(/ obsolete-page-top-space staff-space)
+ top-system-spacing.basic-distance = #(/ obsolete-page-top-space staff-space)
}
}
-\version "2.16.0"
+\version "2.19.12"
\header {
texidoc = "Nested properties can be set in the paper block."
}
\paper {
- system-system-spacing #'minimum-distance = #0.0
+ system-system-spacing.minimum-distance = #0.0
}
{ c1 \break c1 }
-\version "2.16.0"
+\version "2.19.12"
\header {
texidoc = "Setting individual nested paper properties does not
\paper {
annotate-spacing = ##t
system-system-spacing = #'((basic-distance . 12) (minimum-distance . 8))
- system-system-spacing #'padding = #1
+ system-system-spacing.padding = #1
}
\relative c' {
\repeat unfold 10 { a4 d e f }
-\version "2.17.6"
+\version "2.19.12"
\header {
texidoc = "Use @code{define-event-class}, scheme engraver methods,
(let* ((meta-entry (assoc-get 'meta grob-entry))
(class (assoc-get 'class meta-entry))
(ifaces-entry (assoc-get 'interfaces meta-entry)))
- (set-object-property! grob-name 'translation-type? list?)
+ (set-object-property! grob-name 'translation-type? ly:grob-properties?)
(set-object-property! grob-name 'is-grob? #t)
(set! ifaces-entry (append (case class
((Item) '(item-interface))
-\version "2.17.15"
+\version "2.19.12"
\header {
texidoc = "The @code{Script} grobs should follow the descending melody line,
}
{
- \override Script #'direction = #DOWN
- \override NoteHead #'stencil = #point-stencil
+ \override Script.direction = #DOWN
+ \override NoteHead.stencil = #point-stencil
c'2.-> b8-- a-- g1->
}
}
-\version "2.19.2"
+\version "2.19.12"
#(ly:expect-warning (_ "(De)crescendo with unspecified starting volume in MIDI."))
ignoreMelisma = \set ignoreMelismata = ##t
%#(set-global-staff-size (* 5.8 mm))
indent = #(* mm 4)
line-width = #(* mm 140)
- system-system-spacing #'basic-distance = #10.3
+ system-system-spacing.basic-distance = #10.3
ragged-bottom = ##t
}
#include "paper-column.hh"
#include "pitch.hh"
#include "stencil.hh"
+#include "system.hh"
#include "skyline-pair.hh"
Stencil
return m;
}
-/* If this gets called before line breaking, we will return a non-trivial
- extent even if we belong to a tie and won't actually get printed. */
-static SCM
-get_extent (Grob *me, Axis a)
-{
- Stencil *s = Stencil::unsmob (Accidental_interface::get_stencil (me));
-
- if (s)
- return ly_interval2scm (s->extent (a));
- return ly_interval2scm (Interval ());
-}
-
-MAKE_SCHEME_CALLBACK (Accidental_interface, height, 1);
-SCM
-Accidental_interface::height (SCM smob)
-{
- return get_extent (Grob::unsmob (smob), Y_AXIS);
-}
-
-MAKE_SCHEME_CALLBACK (Accidental_interface, width, 1);
-SCM
-Accidental_interface::width (SCM smob)
-{
- return get_extent (Grob::unsmob (smob), X_AXIS);
-}
-
MAKE_SCHEME_CALLBACK (Accidental_interface, horizontal_skylines, 1);
SCM
Accidental_interface::horizontal_skylines (SCM smob)
if (!me->is_live ())
return Skyline_pair ().smobbed_copy ();
- /*
- * Using the print function may trigger a suicide
- * before line breaking. It is therefore `unpure' (c).
- * We use the more basic get_stencil.
- */
- Stencil *my_stencil = Stencil::unsmob (get_stencil (me));
+ Stencil *my_stencil = Stencil::unsmob (me->get_property ("stencil"));
if (!my_stencil)
return Skyline_pair ().smobbed_copy ();
return sky->smobbed_copy ();
}
-MAKE_SCHEME_CALLBACK (Accidental_interface, pure_height, 3);
+MAKE_SCHEME_CALLBACK (Accidental_interface, height, 1);
SCM
-Accidental_interface::pure_height (SCM smob, SCM start_scm, SCM)
+Accidental_interface::height (SCM smob)
{
- Item *me = dynamic_cast<Item *> (Grob::unsmob (smob));
- int start = scm_to_int (start_scm);
- int rank = me->get_column ()->get_rank ();
-
- if (to_boolean (me->get_property ("forced"))
- || !Grob::unsmob (me->get_object ("tie"))
- || (rank == start + 1 && /* we are at the start of a line */
- !to_boolean (me->get_property ("hide-tied-accidental-after-break"))))
- {
- Stencil *s = Stencil::unsmob (get_stencil (me));
- if (s)
- return ly_interval2scm (s->extent (Y_AXIS));
- }
+ Grob *me = Grob::unsmob (smob);
+ Grob *tie = Grob::unsmob (me->get_object ("tie"));
+
+ if (tie
+ && !to_boolean (me->get_property ("forced"))
+ && to_boolean (me->get_property ("hide-tied-accidental-after-break")))
+ return ly_interval2scm (Interval ());
- return ly_interval2scm (Interval ());
+ return Grob::stencil_height (smob);
}
-MAKE_SCHEME_CALLBACK (Accidental_interface, print, 1);
+MAKE_SCHEME_CALLBACK (Accidental_interface, remove_tied, 1);
SCM
-Accidental_interface::print (SCM smob)
+Accidental_interface::remove_tied (SCM smob)
{
Grob *me = Grob::unsmob (smob);
Grob *tie = Grob::unsmob (me->get_object ("tie"));
if (tie
+ && !to_boolean (me->get_property ("forced"))
&& (to_boolean (me->get_property ("hide-tied-accidental-after-break"))
- || (!tie->original () && !to_boolean (me->get_property ("forced")))))
- {
- me->suicide ();
- return SCM_EOL;
- }
+ || !tie->original()))
+ me->suicide ();
+
+ return SCM_UNSPECIFIED;
+}
+
+MAKE_SCHEME_CALLBACK (Accidental_interface, print, 1);
+SCM
+Accidental_interface::print (SCM smob)
+{
+ Grob *me = Grob::unsmob (smob);
return get_stencil (me);
}
#include "context-handle.hh"
#include "duration.hh"
#include "engraver.hh"
+#include "grob-properties.hh"
#include "item.hh"
#include "rest.hh"
#include "spanner.hh"
stems_ = new vector<Item *>;
grouping_ = new Beaming_pattern ();
beaming_options_.from_context (context ());
- beam_settings_ = updated_grob_properties (context (), ly_symbol2scm ("Beam"));
+ beam_settings_ = Grob_property_info (context (), ly_symbol2scm ("Beam")).updated ();
beam_start_context_.set_context (context ()->get_parent_context ());
beam_start_moment_ = now_mom ();
--- /dev/null
+/*
+ This file is part of LilyPond, the GNU music typesetter.
+
+ Copyright (C) 2014--2014 Janek Warchoł <lemniskata.bernoullego@gmail.com>
+
+ LilyPond is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ LilyPond is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "item.hh"
+
+struct Clef_modifier
+{
+ DECLARE_SCHEME_CALLBACK (calc_parent_alignment, (SCM));
+ DECLARE_GROB_INTERFACE ();
+};
+
+MAKE_SCHEME_CALLBACK (Clef_modifier, calc_parent_alignment, 1)
+SCM
+Clef_modifier::calc_parent_alignment (SCM smob)
+{
+ Grob *me = Grob::unsmob (smob);
+ Grob *clef = me->get_parent (X_AXIS);
+ string full_clef_name = ly_scm2string (clef->get_property ("glyph"));
+ string clef_name = replace_all(&full_clef_name, "clefs.", "");
+
+ // find entry with keyname clef_type in clef-alignments
+ SCM alist_entry = scm_assq (ly_symbol2scm (clef_name.c_str ()),
+ me->get_property ("clef-alignments"));
+
+ if (scm_is_pair (alist_entry))
+ {
+ SCM entry_value = scm_cdr (alist_entry);
+ // the value should be a pair of numbers - first is the alignment
+ // for modifiers below the clef, second for those above.
+ if (scm_is_pair (entry_value))
+ if (robust_scm2dir (me->get_property ("direction"), DOWN) == DOWN)
+ return scm_car (entry_value);
+ else
+ return scm_cdr (entry_value);
+
+ else // default alignment = centered
+ return scm_from_double (0);
+ }
+ else // default alignment = centered
+ return scm_from_double (0);
+}
+
+ADD_INTERFACE (Clef_modifier,
+ "The number describing transposition of the clef, placed below\n"
+ "or above clef sign. Usually this is 8 (octave transposition)\n"
+ "or 15 (two octaves), but LilyPond allows any integer here.",
+
+ /* properties */
+ "clef-alignments "
+ );
+
#include "context.hh"
#include "engraver.hh"
#include "global-context.hh"
+#include "grob-properties.hh"
#include "international.hh"
#include "item.hh"
#include "main.hh"
#include "simple-closure.hh"
+#include "smobs.hh"
#include "spanner.hh"
#include "unpure-pure-container.hh"
#include "warn.hh"
assert (false);
}
- sloppy_general_pushpop_property (context, context_property,
- grob_property_path, new_value);
+ Grob_property_info (context, context_property).pushpop
+ (grob_property_path, new_value);
}
bool
|| type_check_assignment (symbol, value, ly_symbol2scm ("backend-type?"));
}
+class Grob_properties {
+ friend class Grob_property_info;
+ friend SCM ly_make_grob_properties (SCM);
+ // alist_ may contain unexpanded nested overrides
+ SCM alist_;
+ // based_on_ is the cooked_ value from the next higher context that
+ // alist_ is based on
+ SCM based_on_;
+ // cooked_ is a version of alist_ where nested overrides have been
+ // expanded
+ SCM cooked_;
+ // cooked_from_ is the value of alist_ from which the expansion has
+ // been done
+ SCM cooked_from_;
+ // nested_ is a count of nested overrides in alist_
+ int nested_;
+
+ Grob_properties (SCM alist, SCM based_on) :
+ alist_ (alist), based_on_ (based_on),
+ // if the constructor was called with lists possibly containing
+ // partial overrides, we would need to initialize with based_on in
+ // order to trigger an initial update. But this should never
+ // happen, so we initialize straight with alist.
+ cooked_ (alist), cooked_from_ (alist), nested_ (0) { }
+ DECLARE_SIMPLE_SMOBS (Grob_properties);
+};
+
+#include "ly-smobs.icc"
+IMPLEMENT_SIMPLE_SMOBS (Grob_properties);
+IMPLEMENT_DEFAULT_EQUAL_P (Grob_properties);
+IMPLEMENT_TYPE_P (Grob_properties, "ly:grob-properties?");
+
+SCM
+Grob_properties::mark_smob (SCM smob)
+{
+ Grob_properties *gp = (Grob_properties *) SCM_SMOB_DATA (smob);
+ scm_gc_mark (gp->alist_);
+ scm_gc_mark (gp->based_on_);
+ scm_gc_mark (gp->cooked_);
+ return gp->cooked_from_;
+}
+
+int
+Grob_properties::print_smob (SCM /*smob*/, SCM port, scm_print_state *)
+{
+ scm_puts ("#<Grob_properties>", port);
+
+ return 1;
+}
+
+LY_DEFINE (ly_make_grob_properties, "ly:make-grob-properties",
+ 1, 0, 0, (SCM alist),
+ "This packages the given property list @var{alist} in"
+ " a grob property container stored in a context property"
+ " with the name of a grob.")
+{
+ LY_ASSERT_TYPE (ly_is_list, alist, 1);
+ return Grob_properties (alist, SCM_EOL).smobbed_copy ();
+}
+
+
+Grob_property_info
+Grob_property_info::find ()
+{
+ if (props_)
+ return *this;
+ SCM res = SCM_UNDEFINED;
+ if (Context *c = context_->where_defined (symbol_, &res))
+ if (c != context_)
+ return Grob_property_info (c, symbol_, Grob_properties::unsmob (res));
+ props_ = Grob_properties::unsmob (res);
+ return *this;
+}
+
+bool
+Grob_property_info::check ()
+{
+ if (props_)
+ return true;
+ SCM res = SCM_UNDEFINED;
+ if (context_->here_defined (symbol_, &res))
+ props_ = Grob_properties::unsmob (res);
+ return props_;
+}
+
+bool
+Grob_property_info::create ()
+{
+ // Using scm_hashq_create_handle_x would seem like the one-lookup
+ // way to create a handle if it does not exist yet. However, we
+ // need to check that there is a corresponding grob in this
+ // particular output first, and we have to do this in the global
+ // context. By far the most frequent case will be that a
+ // Grob_properties for this context already exists, so we optimize
+ // for that and only check the global handle when the local
+ // context is pristine.
+ if (check ())
+ return true;
+ SCM current_context_val = SCM_EOL;
+ Context *g = context_->get_global_context ();
+ if (!g)
+ return false; // Context is probably dead
+
+ /*
+ Don't mess with MIDI.
+ */
+ if (g == context_
+ || !g->here_defined (symbol_, ¤t_context_val))
+ return false;
+
+ Grob_properties *def = Grob_properties::unsmob (current_context_val);
+
+ if (!def)
+ {
+ programming_error ("Grob definition expected");
+ return false;
+ }
+
+ // We create the new Grob_properties from the default definition
+ // since this is what we have available right now. It may or may
+ // not be accurate since we don't take into account any
+ // prospective overrides in intermediate contexts. If there are
+ // any, they will be factored in when `updated' is being called.
+ SCM props = Grob_properties (def->alist_, def->alist_).smobbed_copy ();
+ context_->set_property (symbol_, props);
+ props_ = Grob_properties::unsmob (props);
+ return props_;
+}
+
/*
Grob descriptions (ie. alists with layout properties) are
represented as a (ALIST . BASED-ON) pair, where BASED-ON is the
indicates nested alists, eg. '(beamed-stem-lengths details)
*/
void
-execute_override_property (Context *context,
- SCM context_property,
- SCM grob_property_path,
- SCM new_value)
+Grob_property_info::push (SCM grob_property_path, SCM new_value)
{
- SCM current_context_val = SCM_EOL;
-
- if (!context->here_defined (context_property, ¤t_context_val))
- {
- Context *g = context->get_global_context ();
- if (!g)
- return; // Context is probably dead
-
- /*
- Don't mess with MIDI.
- */
- if (g == context
- || !g->here_defined (context_property, ¤t_context_val))
- return;
-
- /* where != context */
-
- SCM base = updated_grob_properties (context->get_parent_context (),
- context_property);
- current_context_val = scm_cons (base, base);
- context->set_property (context_property, current_context_val);
- }
-
- if (!scm_is_pair (current_context_val))
- {
- programming_error ("Grob definition should be cons");
- return;
- }
-
- SCM target_alist = scm_car (current_context_val);
+ /*
+ Don't mess with MIDI.
+ */
+ if (!create ())
+ return;
SCM symbol = scm_car (grob_property_path);
- if (scm_is_pair (scm_cdr (grob_property_path)))
+ SCM rest = scm_cdr (grob_property_path);
+ if (scm_is_pair (rest))
{
- new_value = nested_property_alist (ly_assoc_get (symbol, target_alist,
- SCM_EOL),
- scm_cdr (grob_property_path),
- new_value);
+ // poor man's typechecking
+ if (typecheck_grob (symbol, nested_create_alist (rest, new_value))) {
+ props_->alist_ = scm_acons (grob_property_path, new_value, props_->alist_);
+ props_->nested_++;
+ }
+ return;
}
/* it's tempting to replace the head of the list if it's the same
property. However, we have to keep this info around, in case we have to
\revert back to it.
*/
- target_alist = scm_acons (symbol, new_value, target_alist);
-
- /*
- tack onto alist. We can use set_car, since
- updated_grob_properties () in child contexts will check
- for changes in the car.
- */
if (typecheck_grob (symbol, new_value))
- {
- scm_set_car_x (current_context_val, target_alist);
- }
-}
-
-/*
- do a pop (indicated by new_value==SCM_UNDEFINED) or push
- */
-void
-sloppy_general_pushpop_property (Context *context,
- SCM context_property,
- SCM grob_property_path,
- SCM new_value)
-{
- if (new_value == SCM_UNDEFINED)
- execute_revert_property (context, context_property,
- grob_property_path);
- else
- execute_override_property (context, context_property,
- grob_property_path,
- new_value);
+ props_->alist_ = scm_acons (symbol, new_value, props_->alist_);
}
/*
Revert the property given by property_path.
*/
void
-execute_revert_property (Context *context,
- SCM context_property,
- SCM grob_property_path)
+Grob_property_info::pop (SCM grob_property_path)
{
- SCM current_context_val = SCM_EOL;
- if (context->here_defined (context_property, ¤t_context_val))
- {
- SCM current_alist = scm_car (current_context_val);
- SCM daddy = scm_cdr (current_context_val);
+ if (!check ())
+ return;
- if (!scm_is_pair (grob_property_path)
- || !scm_is_symbol (scm_car (grob_property_path)))
- {
- programming_error ("Grob property path should be list of symbols.");
- return;
- }
+ SCM current_alist = props_->alist_;
+ SCM daddy = props_->based_on_;
- SCM symbol = scm_car (grob_property_path);
- if (scm_is_pair (scm_cdr (grob_property_path)))
- {
- SCM current_sub_alist = ly_assoc_get (symbol, current_alist, SCM_EOL);
- SCM new_val
- = nested_property_revert_alist (current_sub_alist,
- scm_cdr (grob_property_path));
-
- if (scm_is_pair (current_alist)
- && scm_caar (current_alist) == symbol
- && current_alist != daddy)
- current_alist = scm_cdr (current_alist);
-
- current_alist = scm_acons (symbol, new_val, current_alist);
- scm_set_car_x (current_context_val, current_alist);
- }
- else
- {
- SCM new_alist = evict_from_alist (symbol, current_alist, daddy);
+ if (!scm_is_pair (grob_property_path)
+ || !scm_is_symbol (scm_car (grob_property_path)))
+ {
+ programming_error ("Grob property path should be list of symbols.");
+ return;
+ }
- if (new_alist == daddy)
- context->unset_property (context_property);
- else
- context->set_property (context_property,
- scm_cons (new_alist, daddy));
- }
+ if (scm_is_pair (scm_cdr (grob_property_path)))
+ {
+ SCM old_alist = current_alist;
+ current_alist = evict_from_alist (grob_property_path, current_alist, daddy);
+ if (scm_is_eq (old_alist, current_alist))
+ return;
+ props_->nested_--;
}
+ else
+ current_alist = evict_from_alist (scm_car (grob_property_path),
+ current_alist, daddy);
+
+ if (scm_is_eq (current_alist, daddy))
+ {
+ assert (props_->nested_ == 0);
+ props_ = 0;
+ context_->unset_property (symbol_);
+ return;
+ }
+ props_->alist_ = current_alist;
}
/*
Convenience: a push/pop grob property using a single grob_property
*/
void
execute_pushpop_property (Context *context,
- SCM context_property,
+ SCM grob,
SCM grob_property,
SCM new_value)
{
- general_pushpop_property (context, context_property,
- scm_list_1 (grob_property),
- new_value);
+ Grob_property_info (context, grob).pushpop (scm_list_1 (grob_property), new_value);
}
/*
SCM context_prop = scm_car (entry);
SCM val = scm_cadr (entry);
SCM grob_prop_path = scm_cddr (entry);
- sloppy_general_pushpop_property (tg, context_prop, grob_prop_path, val);
+ Grob_property_info (tg, context_prop).push (grob_prop_path, val);
}
else if (type == ly_symbol2scm ("pop"))
{
SCM context_prop = scm_car (entry);
- SCM val = SCM_UNDEFINED;
SCM grob_prop_path = scm_cdr (entry);
- sloppy_general_pushpop_property (tg, context_prop, grob_prop_path, val);
+ Grob_property_info (tg, context_prop).pop (grob_prop_path);
}
else if (type == ly_symbol2scm ("assign"))
tg->set_property (scm_car (entry), scm_cadr (entry));
Return the object alist for SYM, checking if its base in enclosing
contexts has changed. The alist is updated if necessary.
*/
-SCM
-updated_grob_properties (Context *tg, SCM sym)
+SCM Grob_property_info::updated ()
{
- assert (scm_is_symbol (sym));
+ assert (scm_is_symbol (symbol_));
+
+ Grob_property_info where = find ();
- SCM props;
- tg = tg->where_defined (sym, &props);
- if (!tg)
+ if (!where)
return SCM_EOL;
+ Context *dad = where.context_->get_parent_context ();
+
SCM daddy_props
- = (tg->get_parent_context ())
- ? updated_grob_properties (tg->get_parent_context (), sym)
- : SCM_EOL;
+ = dad ? Grob_property_info (dad, symbol_).updated () : SCM_EOL;
- if (!scm_is_pair (props))
+ SCM based_on = where.props_->based_on_;
+ SCM alist = where.props_->alist_;
+ if (!scm_is_eq (based_on, daddy_props))
{
- programming_error ("grob props not a pair?");
- return SCM_EOL;
- }
-
- SCM based_on = scm_cdr (props);
- if (based_on == daddy_props)
- return scm_car (props);
- else
- {
- SCM copy = daddy_props;
- SCM *tail = ©
- SCM p = scm_car (props);
- while (p != based_on)
- {
- *tail = scm_cons (scm_car (p), daddy_props);
- tail = SCM_CDRLOC (*tail);
- p = scm_cdr (p);
- }
-
- scm_set_car_x (props, copy);
- scm_set_cdr_x (props, daddy_props);
-
- return copy;
+ where.props_->based_on_ = daddy_props;
+ alist = partial_list_copy (alist, based_on, daddy_props);
+ where.props_->alist_ = alist;
}
+ if (scm_is_eq (where.props_->cooked_from_, alist))
+ return where.props_->cooked_;
+ where.props_->cooked_from_ = alist;
+ where.props_->cooked_ = nalist_to_alist (alist, where.props_->nested_);
+ return where.props_->cooked_;
}
#include "context.hh"
#include "context-def.hh"
#include "dispatcher.hh"
+#include "grob-properties.hh"
LY_DEFINE (ly_context_current_moment,
"ly:context-current-moment",
LY_ASSERT_SMOB (Context, context, 1);
LY_ASSERT_TYPE (ly_is_symbol, name, 2);
- return updated_grob_properties (tr, name);
+ return Grob_property_info (tr, name).updated ();
}
LY_DEFINE (ly_context_pushpop_property, "ly:context-pushpop-property",
#include "dispatcher.hh"
#include "engraver-group.hh"
#include "grob.hh"
+#include "grob-properties.hh"
#include "paper-score.hh"
#include "translator-dispatch-list.hh"
#include "warn.hh"
{
Stream_event *ev = Stream_event::unsmob (sev);
- sloppy_general_pushpop_property (context (),
- ev->get_property ("symbol"),
- ev->get_property ("property-path"),
- ev->get_property ("value"));
+ Grob_property_info (context (), ev->get_property ("symbol"))
+ .push (ev->get_property ("property-path"),
+ ev->get_property ("value"));
}
IMPLEMENT_LISTENER (Engraver_group, revert);
{
Stream_event *ev = Stream_event::unsmob (sev);
- sloppy_general_pushpop_property (context (),
- ev->get_property ("symbol"),
- ev->get_property ("property-path"),
- SCM_UNDEFINED);
+ Grob_property_info (context (), ev->get_property ("symbol"))
+ .pop (ev->get_property ("property-path"));
}
void
#include "engraver.hh"
#include "context.hh"
+#include "grob-properties.hh"
#include "international.hh"
#include "music.hh"
#include "paper-column.hh"
(void)fun;
#endif
- SCM props = updated_grob_properties (context (), symbol);
+ SCM props = Grob_property_info (context (), symbol).updated ();
Grob *grob = 0;
bool
Hara_kiri_group_spanner::request_suicide (Grob *me, int start, int end)
{
+ extract_grob_set (me, "make-dead-when", foes);
+ for (vsize i = 0; i < foes.size (); i++)
+ if (foes[i]->is_live () && !request_suicide_alone (foes[i], start, end))
+ return true;
+
if (!request_suicide_alone (me, start, end))
return false;
ADD_INTERFACE (Hara_kiri_group_spanner,
"A group spanner that keeps track of interesting items. If it"
" doesn't contain any after line breaking, it removes itself"
- " and all its children.",
+ " and all its children. Children may be prioritized in layers"
+ " via @code{remove-layer}, in which case only the"
+ " lowest-numbered non-empty layer is retained.",
/* properties */
"items-worth-living "
"important-column-ranks "
"keep-alive-with "
+ "make-dead-when "
"remove-empty "
"remove-first "
+ "remove-layer "
);
-
{
public:
DECLARE_SCHEME_CALLBACK (print, (SCM));
- DECLARE_SCHEME_CALLBACK (height, (SCM));
- DECLARE_SCHEME_CALLBACK (width, (SCM));
DECLARE_SCHEME_CALLBACK (horizontal_skylines, (SCM));
- DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM));
+ DECLARE_SCHEME_CALLBACK (height, (SCM));
+ DECLARE_SCHEME_CALLBACK (remove_tied, (SCM));
DECLARE_GROB_INTERFACE ();
static SCM get_stencil (Grob *me);
*/
void apply_property_operations (Context *tg, SCM pre_init_ops);
-void execute_revert_property (Context *context,
- SCM context_property,
- SCM grob_property_path);
void execute_pushpop_property (Context *trg, SCM prop, SCM eltprop, SCM val);
-void sloppy_general_pushpop_property (Context *context,
- SCM context_property, SCM grob_property_path, SCM val);
-SCM updated_grob_properties (Context *tg, SCM sym);
+
Context *find_context_below (Context *where,
SCM type_sym, const string &id);
bool melisma_busy (Context *);
}
SCM nested_property_alist (SCM alist, SCM prop_path, SCM value);
-SCM nested_property_revert_alist (SCM alist, SCM prop_path);
+SCM nested_create_alist (SCM prop_path, SCM value);
+SCM partial_list_copy (SCM alist, SCM tail, SCM newtail);
SCM evict_from_alist (SCM, SCM, SCM);
+SCM nalist_to_alist (SCM nalist, int nested);
#endif /* CONTEXT_HH */
--- /dev/null
+/*
+ This file is part of LilyPond, the GNU music typesetter.
+
+ Copyright (C) 2014 David Kastrup <dak@gnu.org>
+
+ LilyPond is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ LilyPond is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// This module is concerned with managing grob-properties (more
+// exactly, grob property templates, as they are not yet part of a
+// grob) inside of context properties, in a context-hierarchical
+// manner, with one stack for properties and subproperties per
+// context.
+
+#ifndef GROB_PROPERTIES_HH
+#define GROB_PROPERTIES_HH
+
+#include "lily-proto.hh"
+
+// Several algorithms on Grob_properties need self-identifying
+// information to work properly, but there is no point in storing them
+// in the Grob_properties data structure itself. Instead we create a
+// reflective data structure containing all necessary information for
+// the algorithms processing Grob_properties.
+
+class Grob_property_info {
+ Context * const context_;
+ SCM const symbol_;
+ Grob_properties *props_;
+public:
+ Grob_property_info (Context *context, SCM symbol, Grob_properties *props = 0)
+ : context_ (context), symbol_ (symbol), props_ (props)
+ { }
+ operator bool () { return props_; }
+ Grob_property_info find ();
+ bool check ();
+ bool create ();
+ SCM updated ();
+ void push (SCM path, SCM value);
+ void pop (SCM path);
+ void pushpop (SCM path, SCM value)
+ {
+ if (SCM_UNBNDP (value))
+ return pop (path);
+ push (path, value);
+ }
+};
+#endif
#endif
/*
- TODO: rename me to ly_c_lily_module_eval
-
we don't have to protect the result; it's already part of the
exports list of the module.
*/
if (__builtin_constant_p ((x))) \
{ \
if (!cached) \
- value = cached = scm_eval (scm_from_locale_symbol (x), \
- global_lily_module); \
+ value = cached = \
+ scm_variable_ref (scm_c_module_lookup (global_lily_module, (x))); \
} \
else \
- value = scm_eval (scm_from_locale_symbol (x), global_lily_module); \
+ value = \
+ scm_variable_ref (scm_c_module_lookup (global_lily_module, (x))); \
value; \
})
class Audio_staff;
class Audio_tempo;
class Audio_text;
-class Audio_tie;
class Audio_time_signature;
class Auto_change_iterator;
-class Auto_change_music;
class Axis_group_engraver;
class Bar_engraver;
-class Bar_req_collect_engraver;
class Beaming_pattern;
class Beam_scoring_problem;
class Beam_configuration;
class Beam_quant_parameters;
class Bezier;
-class Bezier_bow;
class Book;
class Box;
-class Break_algorithm;
class Change_iterator;
-class Change_translator;
class Chord_tremolo_iterator;
-class Cluster_engraver;
class Column_x_positions;
class Context;
class Context_def;
class Font_metric;
class Font_size_engraver;
class Global_context;
-class Gourlay_breaking;
class Grace_fixup;
class Grace_iterator;
class Grace_music;
class Grob;
class Grob_array;
class Grob_info;
-class Hara_kiri_line_group_engraver;
+class Grob_properties;
class Includable_lexer;
class Input;
-class Input_file_results;
class Item;
class Key_performer;
class Keyword_ent;
class Ligature_engraver;
class Lily_lexer;
class Lily_parser;
-class Lilypond_context_key;
-class Lilypond_grob_key;
-class Line_group_engraver_group;
class Listener;
class Lookup;
class Lyric_combine_music;
class Lyric_combine_music_iterator;
class Lyric_engraver;
class Lyric_performer;
-class Lyric_phrasing_engraver;
class Mensural_ligature_engraver;
class Midi_chunk;
class Midi_control_function_value_change;
class Moment;
class Music;
class Music_iterator;
-class Music_list;
class Music_output;
class Music_sequence;
class Music_wrapper;
class Performance;
class Performer;
class Performer_group;
-class Piano_bar_engraver;
class Pitch;
class Pitch_squash_engraver;
class Prob;
class Property_iterator;
-class Rational;
class Relative_octave_music;
class Repeated_music;
class Rhythmic_music_iterator;
class Scheme_hash_table;
class Scheme_engraver;
class Score;
-class Score_context;
class Score_engraver;
class Score_performer;
-class Sequential_music;
-class Sequential_music_iterator;
class Simple_music_iterator;
class Simple_spacer;
-class Simple_spacer_wrapper;
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;
class Sources;
class Spacing_options;
-class Span_score_bar_engraver;
class Spanner;
-class Staff_group_bar_engraver;
class Staff_performer;
class Stencil;
class Stream_event;
class Time_scaled_music;
class Time_scaled_music_iterator;
class Time_signature_performer;
-class Timing_engraver;
class Timing_translator;
-class Translation_property;
class Translator;
-class Translator_change;
class Translator_group;
-class Transposed_music;
-class yyFlexLexer;
typedef void (Engraver::*Engraver_void_function_engraver_grob_info) (Grob_info);
typedef void (Translator::*Translator_void_method_ptr) ();
static Grob *accidentals (Grob *me);
static Slice head_positions_interval (Grob *me);
static Grob *first_head (Grob *me);
- static Interval calc_main_heads_extent (Grob *me);
+ static Interval calc_main_extent (Grob *me);
static Grob *get_rest (Grob *me);
static void set_stem (Grob *me, Grob *);
static void add_head (Grob *me, Grob *);
return cached_pure_height_ + pure_relative_y_coordinate (g, start, end);
/* Note: cached_pure_height_ does not notice if start changes, implicitly
assuming that Items' pure_heights do not depend on 'start' or 'end'.
- Accidental_interface::pure_height(), however, does depend on 'start'.
*/
cache_pure_height (Grob::pure_height (this, start, end));
{
for (vsize i = 0; i < group_spanners_.size (); ++i)
{
- SCM grob_array_scm = Grob_array::make_array ();
- Grob_array *ga = Grob_array::unsmob (grob_array_scm);
-
- // It would make Hara_kiri_group_spanner::request_suicide a _little_
- // faster if we removed each grob from its own array. It seems
- // unnecessary for now, though.
- ga->set_array (group_spanners_);
- group_spanners_[i]->set_object ("keep-alive-with", grob_array_scm);
+ SCM this_layer = group_spanners_[i]->get_property ("remove-layer");
+ if (scm_is_false (this_layer))
+ continue;
+
+ SCM live_scm = Grob_array::make_array ();
+ Grob_array *live = Grob_array::unsmob (live_scm);
+ SCM dead_scm = Grob_array::make_array ();
+ Grob_array *dead = Grob_array::unsmob (dead_scm);
+
+ for (vsize j = 0; j < group_spanners_.size (); ++j)
+ {
+ if (i == j)
+ continue;
+ SCM that_layer = group_spanners_[j]->get_property ("remove-layer");
+ if (scm_is_false (that_layer))
+ continue;
+ if (!scm_is_integer (this_layer))
+ {
+ // Unspecified layers are kept alive by anything else
+ live->add (group_spanners_[j]);
+ continue;
+ }
+ // an explicit layer is only affected by explicit layers
+ if (!scm_is_integer (that_layer))
+ continue;
+ if (scm_is_true (scm_num_eq_p (that_layer, this_layer)))
+ live->add (group_spanners_[j]);
+ else if (scm_is_true (scm_less_p (that_layer, this_layer)))
+ dead->add (group_spanners_[j]);
+ }
+ if (!live->empty ())
+ group_spanners_[i]->set_object ("keep-alive-with", live_scm);
+ if (!dead->empty ())
+ group_spanners_[i]->set_object ("make-dead-when", dead_scm);
}
}
return token;
}
-<INITIAL,notes,lyrics>{
+<INITIAL,notes,lyrics,chords>{
\<\< {
yylval = SCM_UNSPECIFIED;
return DOUBLE_ANGLE_OPEN;
}
}
-<INITIAL,notes>{
+<INITIAL,notes,chords>{
\< {
yylval = SCM_UNSPECIFIED;
return ANGLE_OPEN;
#include "context.hh"
#include "grob.hh"
-/*
- Drop symbol from the list alist..alist_end.
- */
+// scm_reverse_x without the checks
SCM
-evict_from_alist (SCM symbol, SCM alist, SCM alist_end)
+fast_reverse_x (SCM lst, SCM tail)
{
- SCM new_alist = SCM_EOL;
- SCM *tail = &new_alist;
-
- while (alist != alist_end)
+ while (!scm_is_null (lst))
{
- if (ly_is_equal (scm_caar (alist), symbol))
- {
- alist = scm_cdr (alist);
- break;
- }
-
- *tail = scm_cons (scm_car (alist), SCM_EOL);
- tail = SCM_CDRLOC (*tail);
- alist = scm_cdr (alist);
+ SCM n = scm_cdr (lst);
+ scm_set_cdr_x (lst, tail);
+ tail = lst;
+ lst = n;
}
+ return tail;
+}
- *tail = alist;
- return new_alist;
+// copy the spine of lst not including tail, appending newtail
+// returns new list.
+SCM
+partial_list_copy (SCM lst, SCM tail, SCM newtail)
+{
+ SCM p = SCM_EOL;
+ for (; !scm_is_eq (lst, tail); lst = scm_cdr (lst))
+ p = scm_cons (scm_car (lst), p);
+ return fast_reverse_x (p, newtail);
}
-/*
- PROP_PATH should be big-to-small ordering
- */
SCM
-nested_property_alist (SCM alist, SCM prop_path, SCM value)
+assq_tail (SCM key, SCM alist, SCM based_on = SCM_EOL)
{
- SCM new_value = SCM_BOOL_F;
- if (scm_is_pair (scm_cdr (prop_path)))
+ for (SCM p = alist; !scm_is_eq (p, based_on); p = scm_cdr (p))
{
- SCM sub_alist = ly_assoc_get (scm_car (prop_path), alist, SCM_EOL);
- new_value = nested_property_alist (sub_alist, scm_cdr (prop_path), value);
+ if (scm_is_eq (scm_caar (p), key))
+ return p;
}
- else
+ return SCM_BOOL_F;
+}
+
+SCM
+assoc_tail (SCM key, SCM alist, SCM based_on = SCM_EOL)
+{
+ for (SCM p = alist; !scm_is_eq (p, based_on); p = scm_cdr (p))
{
- new_value = value;
+ if (ly_is_equal (scm_caar (p), key))
+ return p;
}
+ return SCM_BOOL_F;
+}
- return scm_acons (scm_car (prop_path), new_value, alist);
+// Like assq, but removes the found element destructively
+SCM assq_pop_x (SCM key, SCM *alist)
+{
+ for (SCM p = *alist; scm_is_pair (p); p = *(alist = SCM_CDRLOC (p)))
+ {
+ if (scm_is_eq (scm_caar (p), key))
+ {
+ *alist = scm_cdr (p);
+ return scm_car (p);
+ }
+ }
+ return SCM_BOOL_F;
}
/*
- Recursively purge alist of prop_path:
+ Drop key from the list alist..alist_end.
+ */
+SCM
+evict_from_alist (SCM key, SCM alist, SCM alist_end)
+{
+// shortcircuit to an eq-using assoc_tail variant when key is a symbol
+// (common case)
+ SCM p = scm_is_symbol (key) ? assq_tail (key, alist, alist_end)
+ : assoc_tail (key, alist, alist_end);
+ if (scm_is_true (p))
+ return partial_list_copy (alist, p, scm_cdr (p));
+ return alist;
+}
- revert ((sym, val) : L, [sym]) = L
- revert ((sym, val) : L, sym : props) =
- (sym, revert (val, rest-props)) ++ L
- revert ((sym, val) : L, p ++ rest-props) =
- (sym, val) : revert (L, p ++ rest-props)
+// This is the same as
+// nested_property_alist (SCM_EOL, prop_path, value) but faster
+SCM
+nested_create_alist (SCM prop_path, SCM value)
+{
+ if (scm_is_null (prop_path))
+ return value;
+ return scm_acons (scm_car (prop_path),
+ nested_create_alist (scm_cdr (prop_path), value),
+ SCM_EOL);
+}
+/*
+ PROP_PATH should be big-to-small ordering
*/
+
+// Take the given alist and replace the given nested property with the
+// given value. Multiple overrides of the same property path are not
+// coalesced for efficiency reasons: they are considered rare enough
+// to not be worth the cost of detecting them. When sublists are
+// modified, however, we remove the original sublist and copy the
+// spine before it. The cost for finding the sublist has already been
+// paid anyway.
+
+// A typical use case for this routine is applying (possibly nested)
+// tweaks to a grob property list.
+
SCM
-nested_property_revert_alist (SCM alist, SCM prop_path)
+nested_property_alist (SCM alist, SCM prop_path, SCM value)
{
- assert (scm_is_pair (prop_path));
+ // replacement moves to the front.
+ SCM key = scm_car (prop_path);
+ SCM rest = scm_cdr (prop_path);
+ if (scm_is_pair (rest))
+ {
+ SCM where = assq_tail (key, alist);
+ if (scm_is_false (where))
+ return scm_acons (key, nested_create_alist (rest, value), alist);
+ return scm_acons (key, nested_property_alist (scm_cdar (where),
+ rest,
+ value),
+ partial_list_copy (alist, where, scm_cdr (where)));
+ }
+ // Outcommented code would coalesce multiple overrides of the same
+ // property
+#if 0
+ SCM where = assq_tail (alist, key);
+ if (scm_is_true (where))
+ return scm_acons (key, value,
+ partial_list_copy (alist, where, scm_cdr (where)));
+#endif
+ return scm_acons (key, value, alist);
+}
- SCM wanted_sym = scm_car (prop_path);
+void
+set_nested_property (Grob *me, SCM big_to_small, SCM value)
+{
+ SCM alist = me->get_property (scm_car (big_to_small));
- SCM new_list = SCM_EOL;
- SCM *tail = &new_list;
- for (SCM s = alist; scm_is_pair (s); s = scm_cdr (s))
- {
- SCM sub_sym = scm_caar (s);
- SCM old_val = scm_cdar (s);
+ alist = nested_property_alist (alist, scm_cdr (big_to_small), value);
- if (sub_sym == wanted_sym)
- {
- if (scm_is_pair (scm_cdr (prop_path)))
- {
- SCM new_val = nested_property_revert_alist (old_val, scm_cdr (prop_path));
+ me->set_property (scm_car (big_to_small), alist);
+}
- /* nothing changed: drop newly constructed list. */
- if (old_val == new_val)
- return alist;
+// This converts an alist with nested overrides in it to a proper
+// alist. The number of nested overrides is known in advance,
+// everything up to the last nested override is copied, the tail is
+// shared
- *tail = scm_acons (sub_sym, new_val, SCM_EOL);
- tail = SCM_CDRLOC (*tail);
- }
+SCM
+nalist_to_alist (SCM nalist, int nested)
+{
+ if (!nested)
+ return nalist;
+ SCM copied = SCM_EOL;
+ SCM partials = SCM_EOL;
+ // partials is a alist of partial overrides
+ for (;;)
+ {
+ SCM elt = scm_car (nalist);
+ nalist = scm_cdr (nalist);
+ SCM key = scm_car (elt);
+ if (scm_is_pair (key))
+ // nested override: record for key in partial
+ {
+ SCM pair = scm_sloppy_assq (scm_car (key), partials);
+ if (scm_is_false (pair))
+ partials = scm_acons (scm_car (key), scm_list_1 (elt),
+ partials);
else
+ scm_set_cdr_x (pair, scm_cons (elt, scm_cdr (pair)));
+ if (!--nested)
+ break;
+ }
+ else
+ // plain override: apply any known corresponding partials
+ {
+ SCM pair = assq_pop_x (key, &partials);
+ if (scm_is_true (pair))
{
- /* old value is dropped. */
+ SCM value = scm_cdr (elt);
+ for (SCM pp = scm_cdr (pair); scm_is_pair (pp); pp = scm_cdr (pp))
+ value = nested_property_alist (value, scm_cdaar (pp), scm_cdar (pp));
+ copied = scm_acons (key, value, copied);
}
-
- *tail = scm_cdr (s);
- return new_list;
+ else
+ copied = scm_cons (elt, copied);
}
-
- *tail = scm_acons (sub_sym, old_val, SCM_EOL);
- tail = SCM_CDRLOC (*tail);
}
+ // Now need to work off the remaining partials. All of them are
+ // unique, so we can push them to `copied' after resolving without
+ // losing information.
- /* Wanted symbol not found: drop newly constructed list. */
- return alist;
+ for (;scm_is_pair (partials); partials = scm_cdr (partials))
+ {
+ SCM pair = scm_car (partials);
+ SCM key = scm_car (pair);
+ SCM elt = scm_sloppy_assq (key, nalist);
+ SCM value = SCM_EOL;
+ if (scm_is_true (elt))
+ value = scm_cdr (elt);
+
+ for (SCM pp = scm_cdr (pair); scm_is_pair (pp); pp = scm_cdr (pp))
+ value = nested_property_alist (value, scm_cdaar (pp), scm_cdar (pp));
+
+ copied = scm_acons (key, value, copied);
+ }
+ return fast_reverse_x (copied, nalist);
}
-void
-set_nested_property (Grob *me, SCM big_to_small, SCM value)
+#if 0
+// Alternative approach: don't unfold those partial overrides while
+// they are part of contexts but instead use a special accessor for
+// subproperties in the grob. Not used or tested for now.
+
+SCM
+nassq_ref (SCM key, SCM nalist, SCM fallback)
{
- SCM alist = me->get_property (scm_car (big_to_small));
+ SCM partials = SCM_EOL;
+ // partials is list of partial overrides for the given property
+ for (SCM p = nalist; scm_is_pair (p); p = scm_cdr (p))
+ {
+ SCM elt = scm_car (p);
+ SCM pkey = scm_car (elt);
+ if (scm_is_pair (pkey))
+ {
+ if (scm_is_eq (scm_car (pkey), key))
+ partials = scm_cons (elt, partials);
+ }
+ else if (scm_is_eq (pkey, key))
+ {
+ SCM value = scm_cdr (elt);
+ for (; scm_is_pair (partials); partials = scm_cdr (partials))
+ {
+ value = nested_property_alist (value, scm_cdaar (partials),
+ scm_cdar (partials));
+ }
+ return value;
+ }
+ }
+ if (scm_is_pair (partials))
+ {
+ // Bit of a quandary here: we have only subproperty overrides
+ // but no main property. Could be a programming error, but we
+ // instead override an empty list.
+ SCM value = nested_create_alist (scm_cdaar (partials), scm_cdar (partials));
+ partials = scm_cdr (partials);
+ for (; scm_is_pair (partials); partials = scm_cdr (partials))
+ value = nested_property_alist (value, scm_cdaar (partials),
+ scm_cdar (partials));
+ return value;
+ }
+ return SCM_UNBNDP (fallback) ? SCM_EOL : fallback;
+}
- alist = nested_property_alist (alist, scm_cdr (big_to_small), value);
+// Also needed for this approach to make sense: an accessor for true
+// subproperties.
+SCM
+nassq_nested_ref (SCM key, SCM subpath, SCM nalist, SCM fallback);
+// To be implemented
- me->set_property (scm_car (big_to_small), alist);
-}
+#endif
/*
Return extent of the noteheads in the "main column",
- i.e. excluding any suspended noteheads.
+ (i.e. excluding any suspended noteheads), or extent
+ of the rest (if there are no heads).
*/
Interval
-Note_column::calc_main_heads_extent (Grob *me)
+Note_column::calc_main_extent (Grob *me)
{
- if (get_stem (me))
- return first_head (me)->extent (me, X_AXIS);
- else
- {
- // no stems => no suspended noteheads.
- extract_grob_set (me, "note-heads", heads);
- if (heads.size())
- return heads[0]->extent (me, X_AXIS);
- else
- return Interval (0, 0);
- }
+ Grob *main_head;
+ if (get_stem (me))
+ main_head = first_head (me);
+ else
+ {
+ // no stems => no suspended noteheads.
+ extract_grob_set (me, "note-heads", heads);
+ if (heads.size())
+ main_head = heads[0];
+ }
+ Grob *main_item = main_head
+ ? main_head
+ : Grob::unsmob (me->get_object ("rest"));
+
+ return main_item
+ ? main_item->extent (me, X_AXIS)
+ : Interval (0, 0);
}
/*
;
chord_body_element:
- pitch exclamations questions octave_check post_events
+ pitch_or_tonic_pitch exclamations questions octave_check post_events
{
bool q = to_boolean ($3);
bool ex = to_boolean ($2);
}
;
+pitch_or_tonic_pitch:
+ pitch
+ | steno_tonic_pitch
+ ;
+
gen_text_def:
full_markup {
Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
{
Grob *column = g->get_parent (X_AXIS);
if (!column)
- {
- g->warning (_ ("rhythmic head is not part of a rhythmic column"));
continue;
- }
// Only include rests that start now. Include notes that started any time.
Paper_column *paper_column = dynamic_cast<Item *> (column)->get_column ();
#include "context-def.hh"
#include "dispatcher.hh"
#include "global-context.hh"
+#include "grob-properties.hh"
#include "international.hh"
#include "main.hh"
#include "open-type-font.hh"
pscore_->unprotect ();
context ()->set_property ("output", pscore_->self_scm ());
- SCM props = updated_grob_properties (context (), ly_symbol2scm ("System"));
+ SCM props = Grob_property_info (context (), ly_symbol2scm ("System")).updated ();
pscore_->typeset_system (new System (props));
(him, ly_symbol2scm ("note-column-interface"), a);
else
{
- if (ly_scm2bool(me->internal_get_property (ly_symbol2scm ("X-align-on-main-noteheads")))
+ if (to_boolean (me->get_property ("X-align-on-main-noteheads"))
&& Note_column::has_interface (him))
- he = Note_column::calc_main_heads_extent(him);
+ he = Note_column::calc_main_extent(him);
else
he = him->extent (him, a);
}
#include "align-interface.hh"
#include "context.hh"
#include "grob.hh"
+#include "grob-properties.hh"
#include "item.hh"
#include "pointer-group-interface.hh"
#include "engraver.hh"
for (vsize j = 0; j < affected_contexts.size (); j++)
{
- Item *it = new Item (updated_grob_properties (affected_contexts[j], ly_symbol2scm ("SpanBarStub")));
+ Item *it = new Item (Grob_property_info (affected_contexts[j], ly_symbol2scm ("SpanBarStub")).updated ());
it->set_parent (spanbars_[i], X_AXIS);
Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ());
gi.rerouting_daddy_context_ = affected_contexts[j];
return fm->text_stencil (layout, str, is_music).smobbed_copy ();
}
+static size_t markup_depth = 0;
+
+void markup_up_depth (void *) { ++markup_depth; }
+void markup_down_depth (void *) { --markup_depth; }
+
MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Text_interface, interpret_markup, 3, 0,
"Convert a text markup into a stencil."
" Takes three arguments, @var{layout}, @var{props}, and @var{markup}.\n"
SCM func = scm_car (markup);
SCM args = scm_cdr (markup);
- /* Use a hare/tortoise algorithm to detect whether we are in a cycle,
- * i.e. whether we have already encountered the same markup in the
- * current branch of the markup tree structure. */
- static vector<SCM> encountered_markups;
- size_t depth = encountered_markups.size ();
- if (depth > 0)
- {
- int slow = depth / 2;
- if (ly_is_equal (encountered_markups[slow], markup))
- {
- string name = ly_symbol2string (scm_procedure_name (func));
- // TODO: Also print the arguments of the markup!
- non_fatal_error (_f ("Cyclic markup detected: %s", name));
- return Stencil ().smobbed_copy ();
- }
- }
-
/* Check for non-terminating markups, e.g. recursive calls with
* changing arguments */
SCM opt_depth = ly_get_option (ly_symbol2scm ("max-markup-depth"));
size_t max_depth = robust_scm2int (opt_depth, 1024);
- if (depth > max_depth)
+
+ // Don't use SCM_F_DYNWIND_REWINDABLE since it may be expensive
+ // without any obvious use for retaining continuations into
+ // markup expansion
+ scm_dynwind_begin ((scm_t_dynwind_flags)0);
+ // scm_dynwind_rewind_handler (markup_up_depth, 0, SCM_F_WIND_EXPLICITLY);
+ markup_up_depth (0);
+ scm_dynwind_unwind_handler (markup_down_depth, 0, SCM_F_WIND_EXPLICITLY);
+ if (markup_depth > max_depth)
{
string name = ly_symbol2string (scm_procedure_name (func));
// TODO: Also print the arguments of the markup!
return Stencil ().smobbed_copy ();
}
- encountered_markups.push_back (markup);
SCM retval = scm_apply_2 (func, layout_smob, props, args);
- encountered_markups.pop_back ();
+ scm_dynwind_end ();
return retval;
}
else
Grob *acc = Grob::unsmob (heads[i]->get_object ("accidental-grob"));
if (acc)
- acc->get_property ("stencil"); /* trigger tie-related suicide */
+ acc->get_property ("after-line-breaking"); /* trigger tie-related suicide */
if (acc && acc->is_live () && dir == RIGHT)
{
%}
-\version "2.19.11" % necessary for upgrading to future LilyPond versions.
+\version "2.19.12" % necessary for upgrading to future LilyPond versions.
\header{
title = "A scale in LilyPond"
%}
-\version "2.19.11" % necessary for upgrading to future LilyPond versions.
+\version "2.19.12" % necessary for upgrading to future LilyPond versions.
\header{
title = "A scale in LilyPond"
\defaultchild "Voice"
\accepts "Voice"
\accepts "CueVoice"
- \accepts "NullVoice"
\description "Handles clefs, bar lines, keys, accidentals. It can contain
@code{Voice} contexts."
\accepts "ChoirStaff"
\accepts "PianoStaff"
\accepts "Devnull"
+ \accepts "NullVoice"
\accepts "NoteNames"
\accepts "FiguredBass"
\context {
\name "NullVoice"
\type "Engraver_group"
-
- \description "Non-printing context, typically used for aligning
-lyrics in polyphonic situations, or with @code{\partcombine}."
+ \description "For aligning lyrics without printing notes"
%% don't route anything out of here
\alias "Staff"
\alias "Voice"
- %% all three are needed for ties to work with lyrics
+ % provide non-printing NoteHeads with proper extents for lyric alignment
\consists "Note_heads_engraver"
- \consists "Rhythmic_column_engraver"
- \consists "Tie_engraver"
-
- %% both are needed for melismas to work with \autoBeamOff
- \consists "Beam_engraver"
- \consists "Stem_engraver"
-
- %% needed for slurs to work with lyrics
- \consists "Slur_engraver"
-
- %% keep noteheads inside the staff
- \consists "Pitch_squash_engraver"
- squashedPosition = 0
+ \omit NoteHead
+ \override NoteHead.X-extent = #(lambda (g)
+ (ly:stencil-extent (ly:note-head::print g) X))
- %% `\omit NoteHead' would give slur attachment errors
\omit Accidental
+ \omit AccidentalCautionary
+ \omit AccidentalSuggestion
+
+ % the engravers that control the 'busy' flags for note-onsets and melismata
+ \consists "Grob_pq_engraver"
+ \consists "Tie_engraver"
+ \omit Tie
+ \consists "Beam_engraver"
\omit Beam
- \omit Dots
- \omit Flag
- \omit Rest
+ \consists "Slur_engraver"
\omit Slur
- \omit Stem
- \omit Tie
-
- %% let these take up space (for lyric extenders, etc.)
- \override NoteHead.transparent = ##t
- \override TabNoteHead.transparent = ##t
-
- %% don't let notes shift
- \override NoteHead.X-offset = 0
- \override NoteColumn.ignore-collision = ##t
-
- %% keep beams and stems inside the staff
- \override Beam.positions = #'(1 . 1)
- \override Stem.length = 0
-
- %% prevent "weird stem size" warnings
- \override Stem.direction = #UP
}
\context {
#(define (format-textspan engraver event)
(let* ((context (ly:translator-context engraver))
(moment (ly:context-current-moment context))
- (spanner-props (ly:context-property context 'TextSpanner))
- (details (chain-assoc-get 'bound-details spanner-props))
+ (spanner-props (ly:context-grob-definition context 'TextSpanner))
+ (details (assoc-get 'bound-details spanner-props))
(left-props (assoc-get 'left details '()))
(left-text (assoc-get 'text left-props '())))
(print-line engraver
in the format of @code{all-grob-descriptions}.")
(ly:make-context-mod
(map (lambda (p)
- (list 'assign (car p) (list (cdr p))))
- descriptions)))
+ (list 'assign (car p) (ly:make-grob-properties (cdr p))))
+ descriptions)))
harmonicByFret = #(define-music-function (parser location fret music) (number? ly:music?)
(_i "Convert @var{music} into mixed harmonics; the resulting notes resemble
\name Staff
\accepts Voice
\accepts CueVoice
- \accepts NullVoice
\defaultchild Voice
\consists "Staff_performer"
\alias Staff
\alias Voice
%% needed for melismata
- %% TODO: at least the tie performer likely does not work without the
- %% Note_performer, but I don't know how to shut note output off in
- %% MIDI.
\consists "Tie_performer"
\consists "Beam_performer"
\consists "Slur_performer"
\accepts TabStaff
\accepts StaffGroup
\accepts Devnull
+ \accepts NullVoice
\accepts ChoirStaff
\accepts RhythmicStaff
\accepts ChordNames
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: lilypond 2.19.11\n"
+"Project-Id-Version: lilypond 2.19.12\n"
"Report-Msgid-Bugs-To: http://post.gmane.org/post.php?group=gmane.comp.gnu."
"lilypond.bugs\n"
-"POT-Creation-Date: 2014-08-03 14:21+0100\n"
+"POT-Creation-Date: 2014-08-17 16:01+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgid "cannot find line breaking that satisfies constraints"
msgstr ""
-#: context-property.cc:43
+#: context-property.cc:44
msgid "need symbol arguments for \\override and \\revert"
msgstr ""
msgid "no such internal option: %s"
msgstr ""
-#: property-iterator.cc:119
+#: property-iterator.cc:115
#, c-format
msgid "not a grob name, `%s'"
msgstr ""
if not os.path.isdir (dst_path):
os.makedirs (dst_path)
try:
- os.link (src, dst)
- except AttributeError:
- shutil.copyfile (src, dst)
- except OSError:
+ if (self.global_options.use_source_file_names
+ and isinstance (self, LilypondFileSnippet)):
+ fout = open (dst, 'w')
+ fin = open (src, 'r')
+ for line in fin.readlines ():
+ fout.write (line.replace (self.basename (), self.final_basename ()))
+ fout.close ()
+ fin.close ()
+ else:
+ try:
+ os.link (src, dst)
+ except AttributeError:
+ shutil.copyfile (src, dst)
+ except (IOError, OSError):
error (_ ('Could not overwrite file %s') % dst)
raise CompileError(self.basename())
"The number describing transposition of the clef, placed below
or above clef sign. Usually this is 8 (octave transposition)
or 15 (two octaves), but LilyPond allows any integer here."
- '())
+ '(clef-alignments))
(ly:add-interface
'dynamic-interface
@code{chord-dots-limit} staff-positions.")
(circled-tip ,boolean? "Put a circle at start/@/end of
hairpins (al/@/del niente).")
+ (clef-alignments ,list? "An alist of parent-alignments
+that should be used for clef modifiers with various clefs")
(clip-edges ,boolean? "Allow outward pointing beamlets at the
edges of beams?")
(collapse-height ,ly:dimension? "Minimum height of system start
;;; h
;;;
(hair-thickness ,number? "Thickness of the thin line in a bar
-line, expressed as a multiple of the default staff-line thickness
-(i.e. the visual output is @emph{not} influenced by changes to
-@code{@var{Staff}.StaffSymbol.thickness}).")
+line, expressed as a multiple of the default staff-line
+thickness (i.e. the visual output is @emph{not} influenced by changes
+to @code{@var{Staff}.StaffSymbol.thickness}).")
(harp-pedal-details ,list? "An alist of detailed grob properties
for harp pedal diagrams. Each alist entry consists of a
@code{(@var{property} . @var{value})} pair. The properties which can
(line-positions ,list? "Vertical positions of staff lines.")
(line-thickness ,number? "For slurs and ties, this is the
diameter of the virtual @qq{pen} that draws the two arcs of the
-curve's outline, which intersect at the endpoints. This property
-is expressed as a multiple of the current staff-line thickness
-(i.e. the visual output is influenced by changes to
+curve's outline, which intersect at the endpoints. This property is
+expressed as a multiple of the current staff-line thickness (i.e. the
+visual output is influenced by changes to
@code{@var{Staff}.StaffSymbol.thickness}).")
(long-text ,markup? "Text markup. See @ruser{Formatting text}.")
interesting items.")
(remove-first ,boolean? "Remove the first staff of an orchestral
score?")
+ (remove-layer ,integer? "The @code{Keep_alive_together_engraver}
+removes all @code{VerticalAxisGroup} grobs with a @code{remove-layer}
+larger than the smallest retained @code{remove-layer}. Set to
+@code{#f} to make a layer invisible to the
+@code{Keep_alive_together_engraver}, set to @code{'()} to have it not
+participate in the layering decisions.")
(replacement-alist ,list? "Alist of strings.
The key is a string of the pattern to be replaced. The value is a
string of what should be displayed. Useful for ligatures.")
(left-neighbor ,ly:grob? "The right-most column that has a spacing-wish
for this column.")
+ (make-dead-when ,ly:grob-array? "An array of other
+@code{VerticalAxisGroup}s. If any of them are alive, then we will turn dead.")
(melody-spanner ,ly:grob? "The @code{MelodyItem} object for a stem.")
(minimum-translations-alist ,list? "An list of translations for a given
start and end point.")
`(
(Accidental
. (
+ (after-line-breaking . ,ly:accidental-interface::remove-tied)
(alteration . ,accidental-interface::calc-alteration)
(avoid-slur . inside)
(glyph-name . ,accidental-interface::glyph-name)
(stencil . ,ly:accidental-interface::print)
(horizontal-skylines . ,(ly:make-unpure-pure-container ly:accidental-interface::horizontal-skylines))
(vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
- (X-extent . ,ly:accidental-interface::width)
(Y-extent . ,accidental-interface::height)
(meta . ((class . Item)
(interfaces . (accidental-interface
(AccidentalCautionary
. (
+ (after-line-breaking . ,ly:accidental-interface::remove-tied)
(alteration . ,accidental-interface::calc-alteration)
(avoid-slur . inside)
(glyph-name-alist . ,standard-alteration-glyph-name-alist)
(AccidentalSuggestion
. (
+ (after-line-breaking . ,ly:accidental-interface::remove-tied)
(alteration . ,accidental-interface::calc-alteration)
(direction . ,UP)
(font-size . -2)
(side-axis . ,Y)
(staff-padding . 0.25)
(stencil . ,ly:accidental-interface::print)
- (X-extent . ,ly:accidental-interface::width)
(X-offset . ,ly:self-alignment-interface::aligned-on-x-parent)
(Y-extent . ,accidental-interface::height)
(Y-offset . ,side-position-interface::y-aligned-side)
. (
(break-visibility . ,(grob::inherit-parent-property
X 'break-visibility))
+ (clef-alignments . ((G . (-0.2 . 0.1))
+ (F . (-0.3 . -0.2))
+ (C . (0 . 0))))
(color . ,(grob::inherit-parent-property
X 'color))
(font-shape . italic)
(font-size . -4)
- (parent-alignment-X . ,CENTER)
+ (parent-alignment-X . ,ly:clef-modifier::calc-parent-alignment)
(self-alignment-X . ,CENTER)
(staff-padding . 0.7)
(stencil . ,ly:text-interface::print)
(extra-spacing-width . (+inf.0 . -inf.0))
(outside-staff-priority . 500)
(padding . 0.5)
+ (parent-alignment-X . #f)
(self-alignment-X . ,LEFT)
(side-axis . ,Y)
(staff-padding . 0.5)
(stencil . ,ly:text-interface::print)
(Y-extent . ,grob::always-Y-extent-from-stencil)
- (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
+ (X-offset . ,ly:self-alignment-interface::aligned-on-x-parent)
(Y-offset . ,side-position-interface::y-aligned-side)
(meta . ((class . Item)
(interfaces . (font-interface
(font-encoding . fetaMusic)
(horizon-padding . 0.1) ; to avoid interleaving with accidentals
(positioning-done . ,ly:script-interface::calc-positioning-done)
+ (self-alignment-X . ,CENTER)
(side-axis . ,Y)
;; padding set in script definitions.
(interfaces . (font-interface
outside-staff-interface
script-interface
+ self-alignment-interface
side-position-interface))))))
(ScriptColumn
(extra-spacing-width . (+inf.0 . -inf.0))
(font-shape . italic)
(padding . 0.0) ;; padding relative to SostenutoPedalLineSpanner
+ (parent-alignment-X . #f)
(self-alignment-X . ,CENTER)
(stencil . ,ly:text-interface::print)
(vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
- (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
+ (X-offset . ,ly:self-alignment-interface::aligned-on-x-parent)
(Y-extent . ,grob::always-Y-extent-from-stencil)
(meta . ((class . Item)
(interfaces . (font-interface
. (
(extra-spacing-width . (+inf.0 . -inf.0))
(padding . 0.0) ;; padding relative to SustainPedalLineSpanner
+ (parent-alignment-X . #f)
(self-alignment-X . ,CENTER)
(stencil . ,ly:sustain-pedal::print)
(vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
- (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
+ (X-offset . ,ly:self-alignment-interface::aligned-on-x-parent)
(Y-extent . ,grob::always-Y-extent-from-stencil)
(meta . ((class . Item)
(interfaces . (font-interface
(extra-spacing-width . (+inf.0 . -inf.0))
(font-shape . italic)
(padding . 0.0) ;; padding relative to UnaCordaPedalLineSpanner
+ (parent-alignment-X . #f)
(self-alignment-X . ,CENTER)
(stencil . ,ly:text-interface::print)
(vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
(Y-extent . ,grob::always-Y-extent-from-stencil)
- (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
+ (X-offset . ,ly:self-alignment-interface::aligned-on-x-parent)
(meta . ((class . Item)
(interfaces . (font-interface
piano-pedal-script-interface
(for-each (lambda (x)
;; (display (car x)) (newline)
- (set-object-property! (car x) 'translation-type? list?)
+ (set-object-property! (car x) 'translation-type? ly:grob-properties?)
(set-object-property! (car x) 'is-grob? #t))
all-grob-descriptions)
(define (dump-profile base last this)
(let* ((outname (format #f "~a.profile" (dir-basename base ".ly")))
(diff (map - this last)))
- (ly:progress "\nWriting timing to ~a..." outname)
+ (ly:progress "\nWriting timing to ~a...\n" outname)
(format (open-file outname "w")
"time: ~a\ncells: ~a\n"
(if (ly:get-option 'dump-cpu-profile)
(define-public accidental-interface::height
(ly:make-unpure-pure-container
- ly:accidental-interface::height
- ly:accidental-interface::pure-height))
+ ly:accidental-interface::height))
(define-public cancellation-glyph-name-alist
'((0 . "accidentals.natural")))
(ly:grob-property grob 'positioning-done)
(let* ((shift (ly:grob-property grob 'toward-stem-shift 0.0))
(note-head-location
- (ly:self-alignment-interface::centered-on-x-parent grob))
+ (ly:self-alignment-interface::aligned-on-x-parent grob))
(note-head-grob (ly:grob-parent grob X))
(stem-grob (ly:grob-object note-head-grob 'stem)))
### make sure convert-ly is up-to-date
cd $BUILD_DIR
-make pythonmodules
+make python-modules
cd $TOP_SRC_DIR
### update manuals
logfile = name.replace('.ly', '')
file (name, 'wb').write (contents)
- system_in_directory (' '.join ([cmd, ly.mkarg (name)]),
+ system_in_directory (' '.join ([cmd, ly.mkarg (name.replace (os.path.sep, '/'))]),
lily_output_dir,
logfile)
progress (_ ("Removing `%s'") % output_filename)
raise BookSnippet.CompileError
+def adjust_include_path (path, outpath):
+ """Rewrite an include path relative to the dir where lilypond is launched.
+ Always use forward slashes since this is what lilypond expects."""
+ path = os.path.expanduser (path)
+ path = os.path.expandvars (path)
+ path = os.path.normpath (path)
+ if os.path.isabs (outpath):
+ return os.path.abspath (path).replace (os.path.sep, '/')
+ if os.path.isabs (path):
+ return path.replace (os.path.sep, '/')
+ return os.path.join (inverse_relpath (original_dir, outpath), path).replace (os.path.sep, '/')
+
def inverse_relpath (path, relpath):
"""Given two paths, the second relative to the first,
- return the first path relative to the second."""
+ return the first path relative to the second.
+ Always use forward slashes since this is what lilypond expects."""
if os.path.isabs (relpath):
- return os.path.abspath (path)
- relparts = []
+ return os.path.abspath (path).replace (os.path.sep, '/')
+ relparts = ['']
parts = os.path.normpath (path).split (os.path.sep)
for part in os.path.normpath (relpath).split (os.path.sep):
if part == '..':
else:
relparts.append ('..')
parts.append (part)
- return os.path.sep.join (relparts[::-1])
+ return '/'.join (relparts[::-1])
def do_options ():
global global_options
if global_options.lily_output_dir:
global_options.lily_output_dir = os.path.expanduser (global_options.lily_output_dir)
+ for i, path in enumerate(global_options.include_path):
+ global_options.include_path[i] = adjust_include_path (path, global_options.lily_output_dir)
global_options.include_path.insert (0, inverse_relpath (original_dir, global_options.lily_output_dir))
- if global_options.output_dir:
+ elif global_options.output_dir:
global_options.output_dir = os.path.expanduser (global_options.output_dir)
+ for i, path in enumerate(global_options.include_path):
+ global_options.include_path[i] = adjust_include_path (path, global_options.output_dir)
global_options.include_path.insert (0, inverse_relpath (original_dir, global_options.output_dir))
- global_options.include_path.insert (0, ".")
+ global_options.include_path.insert (0, "./")
# Load the python packages (containing e.g. custom formatter classes)
# passed on the command line
if global_options.process_cmd:
includes = global_options.include_path
- if global_options.lily_output_dir:
- # This must be first, so lilypond prefers to read .ly
- # files in the other lybookdb dir.
- includes = [global_options.lily_output_dir] + includes
global_options.process_cmd += ' '.join ([' -I %s' % ly.mkarg (p)
for p in includes])