nur (@code{mensural}) unterstützt.
@lilypond[quote,fragment,ragged-right,verbatim]
-\override Stem #'flag-style = #'mensural
+\override Flag #'style = #'mensural
\override Stem #'thickness = #1.0
\override NoteHead #'style = #'mensural
\autoBeamOff
% extend the stems to reach the other staff
\override Stem #'length = #12
% do not print extra flags
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
% prevent beaming as needed
a8 g4 f8 f bes\noBeam g4
}
contemplado el estilo @code{mensural}
@lilypond[quote,fragment,ragged-right,verbatim]
-\override Stem #'flag-style = #'mensural
+\override Flag #'style = #'mensural
\override Stem #'thickness = #1.0
\override NoteHead #'style = #'mensural
\autoBeamOff
% extend the stems to reach the other staff
\override Stem #'length = #12
% do not print extra flags
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
% prevent beaming as needed
a8 g4 f8 f bes\noBeam g4
}
@code{mensural}.
@lilypond[quote,fragment,ragged-right,verbatim]
-\override Stem #'flag-style = #'mensural
+\override Flag #'style = #'mensural
\override Stem #'thickness = #1.0
\override NoteHead #'style = #'mensural
\autoBeamOff
% extend the stems to reach the other staff
\override Stem #'length = #12
% do not print extra flags
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
% prevent beaming as needed
a8 g4 f8 f bes\noBeam g4
}
<<
{
\once \override Stem #'transparent = ##t
+ \once \override Flag #'transparent = ##t
b8~ b\noBeam
}
\\
<<
{
\once \override Stem #'transparent = ##t
+ \once \override Flag #'transparent = ##t
\once \override Stem #'length = #8
b8~ b\noBeam
}
only the @code{mensural} style is supported.
@lilypond[quote,fragment,ragged-right,verbatim]
-\override Stem #'flag-style = #'mensural
+\override Flag #'style = #'mensural
\override Stem #'thickness = #1.0
\override NoteHead #'style = #'mensural
\autoBeamOff
\override Staff.StaffSymbol #'color = #red
\override Staff.LedgerLineSpanner #'color = #red
\override Voice.Stem #'transparent = ##t
+ \override Voice.Flag #'transparent = ##t
\override NoteHead #'style = #'vaticana.punctum
\clef "vaticana-do2"
c
\override Staff.StaffSymbol #'color = #red
\override Staff.LedgerLineSpanner #'color = #red
\override Voice.Stem #'transparent = ##t
+ \override Voice.Flag #'transparent = ##t
\override NoteHead #'style = #'vaticana.punctum
\clef "vaticana-fa2"
c
\override Staff.StaffSymbol #'color = #red
\override Staff.LedgerLineSpanner #'color = #red
\override Voice.Stem #'transparent = ##t
+ \override Voice.Flag #'transparent = ##t
\override NoteHead #'style = #'medicaea.punctum
\clef "medicaea-do2"
c
\override Staff.StaffSymbol #'color = #red
\override Staff.LedgerLineSpanner #'color = #red
\override Voice.Stem #'transparent = ##t
+ \override Voice.Flag #'transparent = ##t
\override NoteHead #'style = #'medicaea.punctum
\clef "medicaea-fa2"
c
\override Staff.StaffSymbol #'color = #red
\override Staff.LedgerLineSpanner #'color = #red
\override Voice.Stem #'transparent = ##t
+ \override Voice.Flag #'transparent = ##t
\override NoteHead #'style = #'hufnagel.punctum
\clef "hufnagel-do2"
c
\override Staff.StaffSymbol #'color = #red
\override Staff.LedgerLineSpanner #'color = #red
\override Voice.Stem #'transparent = ##t
+ \override Voice.Flag #'transparent = ##t
\override NoteHead #'style = #'hufnagel.punctum
\clef "hufnagel-fa2"
c
\override Staff.StaffSymbol #'color = #red
\override Staff.LedgerLineSpanner #'color = #red
\override Voice.Stem #'transparent = ##t
+ \override Voice.Flag #'transparent = ##t
\override NoteHead #'style = #'hufnagel.punctum
\clef "hufnagel-do-fa"
c
one can use either @code{\override Stem #'transparent = ##t} or
@code{\override Stem #'length = #0} instead, and restore the stem
when needed with the corresponding @code{\once \override Stem
-#'transparent = ##f} (see example below).
+#'transparent = ##f} (see example below). When using stems that
+carry flags, make sure to set @code{\override Flag #'transparent
+= ##t} as well.
@b{Timing.} For unmetered chant, there are several alternatives.
\remove "Time_signature_engraver"
\override BarLine #'X-extent = #'(-1 . 1)
\override Stem #'transparent = ##t
+ \override Flag #'transparent = ##t
\override Beam #'transparent = ##t
\override BarLine #'transparent = ##t
\override TupletNumber #'transparent = ##t
@example
\override NoteHead #'style = #'slash
\override Stem #'transparent = ##t
+\override Flag #'transparent = ##t
@end example
All these plug-ins have to cooperate, and this is achieved with a
squashedPosition = #0
\override NoteHead #'style = #'slash
\override Stem #'transparent = ##t
+ \override Flag #'transparent = ##t
\alias Voice
@}
@end example
% extend the stems to reach the other staff
\override Stem #'length = #12
% do not print extra flags
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
% prevent beaming as needed
a8 g4 f8 f bes\noBeam g4
}
Al escribir un bajo cifrado, podemos situar las cifras encima o debajo
de las notas del bajo, mediante la definición de la propiedad
@code{BassFigureAlignmentPositioning #'direction} (exclusivamente
-dentro de un contexto @code{Staff}). Se puede elegir entre @code{UP}
-(o @code{1}, arriba), @code{CENTER} (o @code{0}, centrado) y
-@code{DOWN} (o @w{@code{-1}}, abajo).
+dentro de un contexto @code{Staff}). Se puede elegir entre @code{#UP}
+(o @code{#1}, arriba), @code{#CENTER} (o @code{#0}, centrado) y
+@code{#DOWN} (o @code{#-1}, abajo).
Esta propiedad se puede cambiar tantas veces como queramos. Utilice
@code{\\once \\override} si no quiere que la sobreescritura se aplique
notas guía orquestales a la reducción de piano en una partitura vocal.
La función musical @code{\\cueWhile} toma cuatro argumentos: la música
de la que se toma la cita, como viene definida por @code{\\addQuote},
-el nombre que insertar antes de las notas guía, y después @code{UP} o
-@code{DOWN} para especificar @code{\\voiceOne} con el nombre encima
+el nombre que insertar antes de las notas guía, y después @code{#UP} o
+@code{#DOWN} para especificar @code{\\voiceOne} con el nombre encima
del pentagrama o bien @code{\\voiceTwo} con el nombre debajo del
pentagrama, y finalmente la música de piano con la que las notas guía
deben aparecer en paralelo. El nombre del instrumento citado se
@code{\\cueWhile} braucht vier Argumente: Die Noten, von denen die
Stichnoten formatiert werden sollen, definiert durch @code{\\addQuote},
die Bezeichnung, die mit den Noten angegeben werden soll, dann entweder
-@code{UP} (hoch) oder @code{DOWN} (runter) zur Angabe von entweder
+@code{#UP} (hoch) oder @code{#DOWN} (runter) zur Angabe von entweder
@code{\\voiceOne} mit der Bezeichnung über dem System oder @code{\\voiceTwo}
mit der Bezeichnung unter dem System, und schließlich die Klaviermusik,
die parallel zu den Stichnoten gespielt werden soll. Die Bezeichnung des
pour gérer ces repères. La fonction musicale @code{\\cueWhile} prend
quatre arguments@tie{}: la musique d'où provient la citation, telle que
définie par @code{\\addQuote}, le nom qui sera mentionné en regard de
-cette citation, son positionnement -- @code{UP} ou @code{DOWN} selon
+cette citation, son positionnement -- @code{#UP} ou @code{#DOWN} selon
qu'il sera attribué à @code{\\voiceOne} et placé au-dessus ou
@code{\\voiceTwo} et placé en dessous -- et enfin la musique du piano
qui interviendra en parallèle. Le nom de l'instrument en question
-%% DO NOT EDIT this file manually; it is automatically
-%% generated from LSR http://lsr.dsi.unimi.it
-%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
-%% and then run scripts/auxiliar/makelsr.py
-%%
+% 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.15.9
%% This file is in the public domain.
-\version "2.15.7"
+\version "2.15.9"
\header {
- lsrtags = "ancient-notation"
-
%% Translation of GIT committish: 70f5f30161f7b804a681cd080274bfcdc9f4fe8c
texidoces = "
Aquí se muestran muchos de (¿o quizá todos?) los símbolos que
"
doctitlefr = "Gravure de musique ancienne"
+ lsrtags = "ancient-notation"
+
texidoc = "
Shown here are many (all?) of the symbols that are included in
LilyPond's support for ancient notation.
-
-
-
"
doctitle = "Ancient fonts"
} % begin verbatim
s32*1
% \break % 12 (32*1)
- }
+ } % begin verbatim
+
>>
>>
\MensuralVoice
\override NoteHead #'style = #'neomensural
\override Rest #'style = #'neomensural
- \override Stem #'flag-style = #'mensural
+ \override Flag #'style = #'mensural
\override Stem #'thickness = #1.0
}
\context {
Dentro de un acorde (entre ángulos simples @code{< >}), antes de la
nota que queremos alterar, situamos la instrucción @code{\\tweak}
-seguida por @code{'font-size} y definimos el tamaño adecuado como
-@w{@code{-2}} (una cabeza pequeña).
+seguida por @code{#'font-size} y definimos el tamaño adecuado como
+@code{#-2} (una cabeza pequeña).
"
doctitlees = "Modificar el tamaño de una nota suelta de un acorde"
partitura completa.
Este archivo tiene que procesarse de forma separada con la opción
-@option{-dclip-systems}; la página de fragmentos de código podría no
+@code{-dclip-systems}; la página de fragmentos de código podría no
mostrar el resultado adecuadamente.
La salida consiste en archivos con los nombres
una barra de la misma longitud que el grupo especial. Para controlar
la visibilidad de los corchetes de grupo, establezca la propiedad
@code{'bracket-visibility} a @code{#t} (imprimir el corchete siempre),
-@code{#f} (no imprimirlo nunca) o @code{'if-no-beam} (imprimir el
+@code{#f} (no imprimirlo nunca) o @code{#'if-no-beam} (imprimir el
corchete solamente si no hay barra).
"
@code{'bracket-visibility}, de contôler précisément leur
affichage@tie{}: déterminée à @code{#t}, ils seront toujours
imprimés@tie{}; @code{#f} permet de ne jamais les imprimer, et
-@code{'if-no-beam} les imprimera en l'absence de ligature.
+@code{#'if-no-beam} les imprimera en l'absence de ligature.
"
doctitlefr = "Contrôle de l'impression des crochets de nolet"
\once \override NoteHead #'X-offset = #1.7
\once \override Stem #'rotation = #'(45 0 0)
\once \override Stem #'extra-offset = #'(-0.2 . -0.2)
- \once \override Stem #'flag-style = #'no-flag
+ \once \override Flag #'style = #'no-flag
\once \override Accidental #'extra-offset = #'(4 . 0)
}
texidocfr = "
Il s'agit de fonctions postfix pour personnaliser l'extension des
crescendos textuels. L'extension devrait débuter sur la première notte
-de la mesure. Il faut utiliser @w{@code{-\mycresc}} -- comme une
+de la mesure. Il faut utiliser @code{-\mycresc} -- comme une
articulation -- sous peine que le départ de l'extension n'apparaisse
qu'à la note suivante.
"
\once \override TabNoteHead #'transparent = ##t
\once \override NoteHead #'transparent = ##t
\once \override Stem #'transparent = ##t
+ \once \override Flag #'transparent = ##t
\once \override NoteHead #'no-ledgers = ##t
\once \override Glissando #'(bound-details left padding) = #0.3
}
texidoces = "
La alineación horizontal de la letra se puede ajustar sobreescribiendo
la propiedad @code{self-alignment-X} del objeto @code{LyricText}.
-@w{@code{-1}} es izquierda, @code{0} es centrado y @code{1} es derecha;
-sin embargo, puede usar también @code{LEFT}, @code{CENTER} y
-@code{RIGHT}.
+@code{#-1} es izquierda, @code{#0} es centrado y @code{#1} es derecha;
+sin embargo, puede usar también @code{#LEFT}, @code{#CENTER} y
+@code{#RIGHT}.
"
doctitlees = "Alineación de la letra"
texidocde = "
Die horizontale Ausrichtung von Gesangstext kann eingestellt werden, indem
man die @code{self-alignment-X}-Eigenschaft des @code{LyricText}-Objekts
-verändert. @w{@code{-1}} bedeutet links, @code{0} bedeutet mittig und @code{1}
-bedeutet rechts, man kann aber genauso gut auch @code{LEFT}, @code{CENTER}
-und @code{RIGHT} benutzen.
+verändert. @code{#-1} bedeutet links, @code{#0} bedeutet mittig und @code{#1}
+bedeutet rechts, man kann aber genauso gut auch @code{#LEFT}, @code{#CENTER}
+und @code{#RIGHT} benutzen.
"
doctitlede = "Ausrichtung von Gesangstext"
texidocfr = "
L'alignement horizontal des paroles peut se gérer à l'aide de la
propriété @code{self-alignment-X} de l'objet @code{LyricText}.
-Les valeurs @w{@code{-1}} ou @code{LEFT} produiront un alignement par la
-gauche, les valeurs @code{0} ou @code{CENTER} un alignement centré, et
-les valeurs @code{1} ou @code{RIGHT} un alignement par la droite.
+Les valeurs @code{#-1} ou @code{#LEFT} produiront un alignement par la
+gauche, les valeurs @code{#0} ou @code{#CENTER} un alignement centré, et
+les valeurs @code{#1} ou @code{#RIGHT} un alignement par la droite.
"
doctitlefr = "Alignement des syllabes"
@code{dashLarger}, @code{dashDot} y @code{dashUnderscore} reciben
valores predeterminados. Se pueden modificar estos valores
predeterminados para las abreviaturas. Por ejemplo, para asociar
-la abreviatura @w{@code{-+}} (@code{dashPlus}) con el símbolo del
+la abreviatura @code{-+} (@code{dashPlus}) con el símbolo del
semitrino en lugar del símbolo predeterminado +, asigne el valor
@code{trill} a la variable @code{dashPlus}:
@code{dashBar}, @code{dashLarger}, @code{dashDot} und
@code{dashUnderscore} Standardwerte zugewiesen werden. Diese Standardwerte
können verändert werden. Um zum Beispiel die Abkürzung
-@w{@code{-+}} (@code{dashPlus}) mit dem Triller anstatt mit dem +-Symbol zu
+@code{-+} (@code{dashPlus}) mit dem Triller anstatt mit dem +-Symbol zu
assoziieren, muss der Wert @code{trill} der Variable
@code{dashPlus} zugewiesen werden:
@code{dashHat}, @code{dashPlus}, @code{dashDash}, @code{dashBar},
@code{dashLarger}, @code{dashDot}, et @code{dashUnderscore} ainsi que
leur valeur par défaut. Ces valeurs peuvent être modifiées selon vos
-besoins. Il suffit par exemple, pour affecter au raccourci @w{@code{-+}}
+besoins. Il suffit par exemple, pour affecter au raccourci @code{-+}
(@code{dashPlus}) le symbole du trille en lieu et place du @code{+}
(caractère plus), d'assigner la valeur @code{trill} à la variable
@code{dashPlus} :
--- /dev/null
+%% This file is in the public domain.
+\version "2.15.9"
+
+\header {
+ lsrtags = "ancient-notation"
+
+ texidoc = "
+Shown here are many (all?) of the symbols that are included in
+LilyPond's support for ancient notation.
+"
+ doctitle = "Ancient fonts"
+} % begin verbatim
+
+upperStaff = \new VaticanaStaff = "upperStaff" <<
+ \context VaticanaVoice <<
+ \transpose c c {
+
+ \override NoteHead #'style = #'vaticana.punctum
+ \key es \major
+ \clef "vaticana-fa2"
+ c1 des e f ges
+
+ \override NoteHead #'style = #'vaticana.inclinatum
+ a! b ces'
+ \bar "|"
+ % \break % 1 (8*1)
+
+ \override NoteHead #'style = #'vaticana.quilisma
+ b! des'! ges! fes!
+ \breathe
+ \clef "vaticana-fa1"
+ \override NoteHead #'style = #'vaticana.plica
+ es d
+ \override NoteHead #'style = #'vaticana.reverse.plica
+ c d
+ \bar "|"
+ % \break %2 (8*1)
+
+ \override NoteHead #'style = #'vaticana.punctum.cavum
+ es f
+ \override NoteHead #'style = #'vaticana.lpes
+ g as
+ \override NoteHead #'style = #'vaticana.upes
+ bes as
+ \override NoteHead #'style = #'vaticana.vupes
+ g f
+ \override NoteHead #'style = #'vaticana.linea.punctum
+ \once \override Staff.BarLine #'bar-extent = #'(-1 . 1) \bar "|"
+ % \break % 3 (8*1)
+
+ es d
+ \override NoteHead #'style = #'vaticana.epiphonus
+ c d
+ \override NoteHead #'style = #'vaticana.cephalicus
+ es f
+
+ \override Staff.KeySignature #'glyph-name-alist = #alteration-medicaea-glyph-name-alist
+ \override Staff.Accidental #'glyph-name-alist = #alteration-medicaea-glyph-name-alist
+ \override Staff.Custos #'style = #'medicaea
+ \override NoteHead #'style = #'medicaea.punctum
+ \clef "medicaea-fa2"
+ ces des
+ \bar "|"
+ % \break % 4 (8*1)
+
+ e! f! ges
+ \clef "medicaea-do2"
+ \override NoteHead #'style = #'medicaea.inclinatum
+ a! b! ces'
+ \override NoteHead #'style = #'medicaea.virga
+ b! a!
+ \bar "|"
+ % \break % 5 (8*1)
+
+ ges fes
+ \clef "medicaea-fa1"
+ \override NoteHead #'style = #'medicaea.rvirga
+ e des ces
+
+ \override Staff.KeySignature #'glyph-name-alist = #alteration-hufnagel-glyph-name-alist
+ \override Staff.Accidental #'glyph-name-alist = #alteration-hufnagel-glyph-name-alist
+ \override Staff.Custos #'style = #'hufnagel
+ \override NoteHead #'style = #'hufnagel.punctum
+ \clef "hufnagel-fa2"
+ ces des es
+ \bar "|"
+ % \break % 6 (8*1)
+
+ fes ges
+ \clef "hufnagel-do2"
+ \override NoteHead #'style = #'hufnagel.lpes
+ as! bes! ces'
+ \override NoteHead #'style = #'hufnagel.virga
+ bes! as!
+ \bar "|"
+ % \break % 7 (8*1)
+
+ ges! fes!
+ \clef "hufnagel-do-fa"
+ \override NoteHead #'style = #'hufnagel.punctum
+ es! des ces des! es! fes!
+ \bar "||"
+ % \break % 8 (8*1)
+
+ s32*1
+ % \break % 12 (32*1)
+ }
+ >>
+>>
+
+lowerStaff = \new MensuralStaff = "lowerStaff" <<
+ \context MensuralVoice <<
+ \transpose c c {
+
+ \key a \major
+ cis'1 d'\breve gis'\breve e'\breve \[ e'\longa fis'\longa \]
+ \set Staff.forceClef = ##t
+ \clef "neomensural-c2"
+ cis1
+ \bar "|"
+ % \break % 2 (16*1)
+
+ \[ g\breve dis''\longa \]
+ b\breve \[ a\longa d\longa \]
+ \clef "petrucci-c2"
+ % \break % 4 (16*1)
+
+ fis1 ces1
+ \clef "petrucci-c2"
+ r\longa
+ \set Staff.forceClef = ##t
+ \clef "mensural-c2"
+ r\breve
+ \bar "|"
+ % \break % 5 (8*1)
+
+ r2
+ \clef "mensural-g"
+ r4 r8 r16 r16
+ \override NoteHead #'style = #'mensural
+ \override Rest #'style = #'mensural
+ \clef "petrucci-f"
+ c8 b, c16 b, c32 b, c64 b, c64 b,
+ d8 e d16 e d32 e d64 e d64 e
+ r\longa
+ \set Staff.forceClef = ##t
+ \clef "petrucci-f"
+ r\breve
+ \bar "|"
+ % \break % 6 (8*1)
+
+ r\breve
+ \clef "mensural-f"
+ r2 r4 r8 r16 r16
+
+ \set Staff.forceClef = ##t
+ \clef "mensural-f"
+ e\breve f g a1
+ \clef "mensural-g"
+ % \break % 7 (8*1)
+
+ \[ bes'!\longa a'!\longa c''!\longa \]
+ e'1 d' c' d' \bar "|"
+ \bar "|"
+ % \break % 9 (16*1)
+
+ bes'!\longa fis'!1 as'!1 ges'!\longa % lig
+ \set Staff.forceClef = ##t
+ \clef "mensural-g"
+ e'2 d' c' \bar "|"
+ % \break % 11 (16*1)
+
+ \set Staff.forceClef = ##t
+ \clef "petrucci-g"
+ c'2 d' e' f'
+ \clef "petrucci-g"
+ g' as'! bes'! cis''!
+ bes'! as'! gis'! fis'!
+ \set Staff.forceClef = ##t
+ \clef "mensural-g"
+ es'! des'! cis'!1 \bar "||"
+ % \break % 12 (8*1)
+ }
+ >>
+>>
+
+\paper {
+ line-thickness = #(/ staff-space 5.0)
+}
+
+\score {
+ <<
+ \upperStaff
+ \lowerStaff
+ >>
+ \layout {
+ indent = 0.0
+ line-width = 17.25\cm
+ \context {
+ \Score
+ timing = ##f
+ }
+ \context {
+ \MensuralVoice
+ \override NoteHead #'style = #'neomensural
+ \override Rest #'style = #'neomensural
+ \override Flag #'style = #'mensural
+ \override Stem #'thickness = #1.0
+ }
+ \context {
+ \MensuralStaff
+ \revert BarLine #'transparent
+ \override KeySignature #'glyph-name-alist = #alteration-mensural-glyph-name-alist
+ clefGlyph = #"clefs.petrucci.c2"
+ }
+ \context {
+ \VaticanaStaff
+ \revert BarLine #'transparent
+ \override StaffSymbol #'thickness = #2.0
+ \override KeySignature #'glyph-name-alist = #alteration-vaticana-glyph-name-alist
+ \override Custos #'neutral-position = #4
+ }
+ }
+}
+
\once \override NoteHead #'X-offset = #1.7
\once \override Stem #'rotation = #'(45 0 0)
\once \override Stem #'extra-offset = #'(-0.2 . -0.2)
- \once \override Stem #'flag-style = #'no-flag
+ \once \override Flag #'style = #'no-flag
\once \override Accidental #'extra-offset = #'(4 . 0)
}
\once \override TabNoteHead #'transparent = ##t
\once \override NoteHead #'transparent = ##t
\once \override Stem #'transparent = ##t
+ \once \override Flag #'transparent = ##t
\once \override NoteHead #'no-ledgers = ##t
\once \override Glissando #'(bound-details left padding) = #0.3
}
%% Flag [Note Head - Stem]
%%
-noflag = \once \override Stem #'flag-style = #'no-flag
+noflag = \once \override Flag #'style = #'no-flag
%%%
%%% Functions
tipográfica, se imprime un becuadro antes de un sostenido o un
bemol cuando se tiene que cancelar una alteración anterior en la
misma nota. Para modificar este comportamiento, establezca el
-valor de la propiedad @code{extraNatural} a @code{#f} (falso)
+valor de la propiedad @code{extraNatural} a @code{##f} (falso)
dentro del contexto de @code{Staff}.
"
En accord avec les règles standards de l'écriture musicale, on grave
un bécarre avant un dièse ou un bémol si on a besoin d'annuler une
altération précédente. Pour modifier ce comportement, assignez la propriété
-@code{extraNatural} du contexte @code{Staff} à la valeur @code{#f} (faux).
+@code{extraNatural} du contexte @code{Staff} à la valeur @code{##f} (faux).
"
doctitlefr = "Suppression des bécarres superflus"
%% Flag [Note Head - Stem]
%%
-noflag = \once \override Stem #'flag-style = #'no-flag
+noflag = \once \override Flag #'style = #'no-flag
%%%
%%% Functions
s32 s32_\appassmolto s8. \voiceOne r8 <bes'' es bes'>-> s4
\override Stem #'cross-staff = ##t
\override Stem #'length = #28
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
s8 \voiceTwo g,8 aes4 s4
}
middleVoiceOne = \relative c' {
\override Stem #'cross-staff = ##t
\override Stem #'length = #32
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
d!8\noBeam s8 s8 s8_\crmolto s4 % 1
s4 <g bes\arpeggio>8[ <es' g>] \voiceOne e,8( dis16 e) | % 2
\revert Stem #'length
s2. | % 1
\override Stem #'cross-staff = ##t
\override Stem #'length = #24
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
s2 \voiceTwo e!4 | % 2
s4 \voiceTwo <bes c es f>8 <f' aes es'>16 d' <bes, f' aes c>8 <bes' fis'> | % 3
}
b
\override NoteHead #'color = #green
\override Stem #'color = #blue
+ \override Flag #'color = #magenta
e8 es d dis e4 r
}
\header {
texidoc = "Default flag styles: '(), 'mensural and 'no-flag.
- Compare all three methods to print them: (1) C++ default implementation,
- (2) Scheme implementation using the 'flag-style grob property and
+ Compare all three methods to print them: (1) C++ default implementation,
+ (2) Scheme implementation using the 'style grob property and
(3) setting the 'flag property explicitly to the desired Scheme function.
All three systems should be absolutely identical."
}
c''8 d''16 c''32 d''64 \acciaccatura {c''8} d''64
}
-% Old settings: flag-style set to default, 'mensural, 'no-flag; using the
+% Old settings: style set to default, 'mensural, 'no-flag; using the
% default C++ function ly:stem::calc-stem
{
\override Score.RehearsalMark #'self-alignment-X = #LEFT
\testnotes
\mark "Symbol: 'mensural (C++)"
- \override Stem #'flag-style = #'mensural
+ \override Flag #'style = #'mensural
\testnotes
\mark "Symbol: 'no-flag (C++)"
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
\testnotes
}
\override Score.RehearsalMark #'self-alignment-X = #LEFT
\time 2/4
- \override Stem #'flag = #default-flag
- \revert Stem #'flag-style
+ \override Flag #'stencil = #default-flag
+ \revert Flag #'style
\mark "Default flags (Scheme)"
\testnotes
\mark "Symbol: 'mensural (Scheme)"
- \override Stem #'flag-style = #'mensural
+ \override Flag #'style = #'mensural
\testnotes
\mark "Symbol: 'no-flag (Scheme)"
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
\testnotes
}
\time 2/4
\mark "Function: normal-flag"
- \override Stem #'flag = #normal-flag
+ \override Flag #'stencil = #normal-flag
\testnotes
\mark "Function: mensural-flag"
- \override Stem #'flag = #mensural-flag
+ \override Flag #'stencil = #mensural-flag
\testnotes
\mark "Function: no-flag"
- \override Stem #'flag = #no-flag
+ \override Flag #'stencil = #no-flag
\testnotes
}
\version "2.14.0"
\header {
- texidoc = "The 'flag property of the Stem grob can be set to a custom
+ texidoc = "The 'stencil property of the Flag grob can be set to a custom
scheme function to generate the glyph for the flag."
}
% test notes, which will be shown in different style:
testnotes = { \autoBeamOff c'8 d'16 c'32 d'64 \acciaccatura {c'8} d'64 c''8 d''16 c''32 d''64 \acciaccatura {c''8} d''64 }
-#(define-public (weight-flag stem-grob)
- (let* ((log (- (ly:grob-property stem-grob 'duration-log) 2))
+#(define-public (weight-flag grob)
+ (let* ((stem-grob (ly:grob-parent grob X))
+ (log (- (ly:grob-property stem-grob 'duration-log) 2))
(is-up (eqv? (ly:grob-property stem-grob 'direction) UP))
(yext (if is-up (cons (* log -0.8) 0) (cons 0 (* log 0.8))))
(flag-stencil (make-filled-box-stencil '(-0.4 . 0.4) yext))
- (stroke-style (ly:grob-property stem-grob 'stroke-style))
+ (stroke-style (ly:grob-property grob 'stroke-style))
(stroke-stencil (if (equal? stroke-style "grace") (make-line-stencil 0.2 -0.9 -0.4 0.9 -0.4) empty-stencil)))
(ly:stencil-add flag-stencil stroke-stencil)))
% Create a flag stencil by looking up the glyph from the font
-#(define (inverted-flag stem-grob)
- (let* ((dir (if (eqv? (ly:grob-property stem-grob 'direction) UP) "d" "u"))
- (flag (retrieve-glyph-flag "" dir "" stem-grob))
- (line-thickness (ly:staff-symbol-line-thickness stem-grob))
+#(define (inverted-flag grob)
+ (let* ((stem-grob (ly:grob-parent grob X))
+ (dir (if (eqv? (ly:grob-property stem-grob 'direction) UP) "d" "u"))
+ (flag (retrieve-glyph-flag "" dir "" grob))
+ (line-thickness (ly:staff-symbol-line-thickness grob))
(stem-thickness (ly:grob-property stem-grob 'thickness))
(stem-width (* line-thickness stem-thickness))
- (stroke-style (ly:grob-property stem-grob 'stroke-style))
+ (stroke-style (ly:grob-property grob 'stroke-style))
(stencil (if (null? stroke-style) flag
- (add-stroke-glyph flag stem-grob dir stroke-style "")))
+ (add-stroke-glyph flag grob dir stroke-style "")))
(rotated-flag (ly:stencil-rotate-absolute stencil 180 0 0)))
(ly:stencil-translate rotated-flag (cons (- (/ stem-width 2)) 0))))
\override Score.RehearsalMark #'self-alignment-X = #LEFT
\time 2/4
\mark "Function: weight-flag (custom)"
- \override Stem #'flag = #weight-flag
+ \override Flag #'stencil = #weight-flag
\testnotes
\mark "Function: inverted-flag (custom)"
- \override Stem #'flag = #inverted-flag
+ \override Flag #'stencil = #inverted-flag
\testnotes
}
{
\autoBeamOff
\time 3/8
- \override Stem #'flag = #modern-straight-flag
+ \override Flag #'stencil = #modern-straight-flag
\override Stem #'length-fraction = #'1.5
r8
\acciaccatura {
\override Score.RehearsalMark #'self-alignment-X = #LEFT
\time 2/4
\mark "modern straight"
- \override Stem #'flag = #modern-straight-flag
+ \override Flag #'stencil = #modern-straight-flag
\testnotes
\mark "old straight (large angles)"
- \override Stem #'flag = #old-straight-flag
+ \override Flag #'stencil = #old-straight-flag
\testnotes
%
% \mark "custom slant"
% % flag thickness and spacing
% % up-flag angle and length
% % down-flag angle and length
-% \override Stem #'flag = #(straight-flag 0.35 0.8 -5 0.5 60 2.0)
+% \override Flag #'stencil = #(straight-flag 0.35 0.8 -5 0.5 60 2.0)
% \testnotes
}
#(whitelist-grob 'NoteHead)
#(whitelist-grob 'Stem)
+#(whitelist-grob 'Flag)
#(whitelist-grob "NoteHead")
#(whitelist-grob "Stem")
+#(whitelist-grob "Flag")
#(map whitelist-symbol '(stencil style duration-log
stem-attachment end-position staff-position
\override NoteHead #'transparent = ##t
\override NoteHead #'no-ledgers = ##t
\override Stem #'transparent = ##t
+ \override Flag #'transparent = ##t
\override Beam #'transparent = ##t
<< \skips
>>
\grace {
- \override Stem #'stroke-style = #"grace"
+ \override Flag #'stroke-style = #"grace"
s8
s16 s s
\clef bass
<e,,, e,>32(\sustainOff\sustainOn
- \revert Stem #'stroke-style
+ \revert Flag #'stroke-style
}
<gis' e>2)
%
-longgrace = \override Stem #'stroke-style = #'()
-endlonggrace = \revert Stem #'stroke-style
+longgrace = \override Flag #'stroke-style = #'()
+endlonggrace = \revert Flag #'stroke-style
ritenuto = \markup { \italic "rit." }
\version "2.14.0"
}
mus = \relative c' {
- % Acciaccaturas contain a slur and \override Stem #'stroke-style
+ % Acciaccaturas contain a slur and \override Flag #'stroke-style
% Thus, we're checking \override here
c4 \acciaccatura d8 c4
% Checking \set and \unset
% Checking \once \override
\once \override Stem #'thickness = #8.0 d8
% Checking two overrides
- \override Stem #'thickness = #8.0 \override Stem #'stroke-style = "grace"
+ \override Stem #'thickness = #8.0 \override Flag #'stroke-style = "grace"
d8
% reverting one of them
\revert Stem #'thickness d8
% and the other
- \revert Stem #'stroke-style c8
+ \revert Flag #'stroke-style c8
% checking tweaks
c2-\tweak #'color #red ->
\version "2.14.0"
\header {
- texidoc = "Stems with overridden 'length should not confuse height estimation.
-This example should fit snugly on one page.
+ texidoc = "Stems with overridden 'Y-extent should
+not confuse height estimation. This example should fit snugly
+on one page.
"
}
\score {
\new Voice {
\voiceTwo
- \override Stem #'length = #0
+ \override Stem #'Y-extent = #'(0.0 . 0.0)
\repeat unfold 144 a4
}
\layout {
--- /dev/null
+
+\version "2.15.9"
+
+\header {
+ texidoc = "Stem length can be overridden via the function
+stem::length
+"
+}
+
+\relative c' {
+ \override Stem #'Y-extent = #(stem::length 8)
+ e4 f'4
+}
--- /dev/null
+\version "2.15.9"
+
+\header {
+ texidoc = "Lilypond gets beamed stem pure heights correct
+to avoid outside staff collisions.
+"
+}
+
+{
+ \stemUp
+ gis''8 a bes'' a
+ bes''! a bes''! a
+}
- beam->relative_coordinate (common[Y_AXIS], Y_AXIS);
Real factor = parameters.STEM_COLLISION_FACTOR;
- if (!unsmob_grob (s->get_object ("beam"))
- && !Stem::flag (s).is_empty ())
+ if (!unsmob_grob (s->get_object ("beam")))
factor = 1.0;
add_collision (x, y, factor);
}
stem_y += thick * 0.5 * get_grob_direction (s);
/*
- Do set_stemend for invisible stems too, so tuplet brackets
+ Do set_stem_positions for invisible stems too, so tuplet brackets
have a reference point for sloping
*/
- Stem::set_stemend (s, 2 * stem_y / staff_space);
+ Stem::set_stem_positions (s, 2 * stem_y / staff_space);
}
return posns;
i != stems.end (); i++)
{
Grob *stem = (*i);
- Stencil flag = Stem::flag (stem);
- if (!flag.is_empty ())
+ Grob *flag = Stem::flag (stem);
+ if (flag)
{
- Interval y = flag.extent (Y_AXIS)
- * (2 / ss)
- + Stem::stem_end_position (stem);
-
- Interval x = stem->relative_coordinate (commonx, X_AXIS)
- + flag.extent (X_AXIS);
+ Grob *commony = stem->common_refpoint (flag, Y_AXIS);
+ Interval y = flag->extent (commony, Y_AXIS) * (2 / ss);
+ Interval x = flag->extent (commonx, X_AXIS);
boxes.push_back (Box (x, y));
}
--- /dev/null
+/*
+ This file is part of LilyPond, the GNU music typesetter.
+
+ Copyright (C) 1996--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Jan Nieuwenhuizen <janneke@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/>.
+*/
+
+#include "stem.hh"
+
+#include "directional-element-interface.hh"
+#include "font-interface.hh"
+#include "grob.hh"
+#include "international.hh"
+#include "output-def.hh"
+#include "staff-symbol-referencer.hh"
+#include "stencil.hh"
+#include "warn.hh"
+
+class Flag
+{
+public:
+ DECLARE_SCHEME_CALLBACK (print, (SCM));
+ DECLARE_SCHEME_CALLBACK (width, (SCM));
+ DECLARE_SCHEME_CALLBACK (calc_y_offset, (SCM));
+ DECLARE_SCHEME_CALLBACK (calc_x_offset, (SCM));
+ DECLARE_GROB_INTERFACE ();
+};
+
+
+
+MAKE_SCHEME_CALLBACK (Flag, width, 1);
+SCM
+Flag::width (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ Stencil *sten = unsmob_stencil (me->get_property ("stencil"));
+ if (!sten)
+ return ly_interval2scm (Interval (0.0, 0.0));
+
+ Grob *stem = me->get_parent (X_AXIS);
+
+ /*
+ TODO:
+ This reproduces a bad hard-coding that has been in the code for quite some time:
+ the bounding boxes for the flags are slightly off and need to be fixed.
+ */
+
+ return ly_interval2scm (sten->extent (X_AXIS) - stem->extent (stem, X_AXIS)[RIGHT]);
+}
+MAKE_SCHEME_CALLBACK (Flag, print, 1);
+SCM
+Flag::print (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ Grob *stem = me->get_parent (X_AXIS);
+
+ Direction d = get_grob_direction (stem);
+ int log = Stem::duration_log (stem);
+ string flag_style;
+
+ SCM flag_style_scm = me->get_property ("style");
+ if (scm_is_symbol (flag_style_scm))
+ flag_style = ly_symbol2string (flag_style_scm);
+
+ if (flag_style == "no-flag")
+ return Stencil ().smobbed_copy ();
+
+ bool adjust = true;
+
+ string staffline_offs;
+ if (flag_style == "mensural")
+ /* Mensural notation: For notes on staff lines, use different
+ flags than for notes between staff lines. The idea is that
+ flags are always vertically aligned with the staff lines,
+ regardless if the note head is on a staff line or between two
+ staff lines. In other words, the inner end of a flag always
+ touches a staff line.
+ */
+ {
+ if (adjust)
+ {
+ Real ss = Staff_symbol_referencer::staff_space (me);
+ int p = (int) (rint (stem->extent (stem, Y_AXIS)[d] * 2 / ss));
+ staffline_offs
+ = Staff_symbol_referencer::on_line (stem, p) ? "0" : "1";
+ }
+ else
+ staffline_offs = "2";
+ }
+ else
+ staffline_offs = "";
+
+ char dir = (d == UP) ? 'u' : 'd';
+ string font_char = flag_style
+ + to_string (dir) + staffline_offs + to_string (log);
+ Font_metric *fm = Font_interface::get_default_font (me);
+ Stencil flag = fm->find_by_name ("flags." + font_char);
+ if (flag.is_empty ())
+ me->warning (_f ("flag `%s' not found", font_char));
+
+ /*
+ TODO: maybe property stroke-style should take different values,
+ e.g. "" (i.e. no stroke), "single" and "double" (currently, it's
+ '() or "grace"). */
+ SCM stroke_style_scm = me->get_property ("stroke-style");
+ if (scm_is_string (stroke_style_scm))
+ {
+ string stroke_style = ly_scm2string (stroke_style_scm);
+ if (!stroke_style.empty ())
+ {
+ string font_char = flag_style + to_string (dir) + stroke_style;
+ Stencil stroke = fm->find_by_name ("flags." + font_char);
+ if (stroke.is_empty ())
+ {
+ font_char = to_string (dir) + stroke_style;
+ stroke = fm->find_by_name ("flags." + font_char);
+ }
+ if (stroke.is_empty ())
+ me->warning (_f ("flag stroke `%s' not found", font_char));
+ else
+ flag.add_stencil (stroke);
+ }
+ }
+
+ return flag.smobbed_copy ();
+}
+
+MAKE_SCHEME_CALLBACK (Flag, calc_y_offset, 1);
+SCM
+Flag::calc_y_offset (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ Grob *stem = me->get_parent (X_AXIS);
+ Direction d = get_grob_direction (stem);
+
+ Real blot
+ = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
+
+ Real y2 = stem->extent (stem, Y_AXIS)[d];
+
+ return scm_from_double (y2 - d * blot / 2);
+}
+
+MAKE_SCHEME_CALLBACK (Flag, calc_x_offset, 1);
+SCM
+Flag::calc_x_offset (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ Grob *stem = me->get_parent (X_AXIS);
+ return scm_from_double (stem->extent (stem, X_AXIS)[RIGHT]);
+}
+
+ADD_INTERFACE (Flag,
+ "A flag that gets attached to a stem."
+ "The style property is symbol determining"
+ " what style of flag glyph is typeset on a"
+ " @code{Stem}. Valid options include @code{'()}"
+ " for standard flags, @code{'mensural} and"
+ " @code{'no-flag}, which switches off the flag.",
+
+ /* properties */
+ "style "
+ "stroke-style "
+ );
\ No newline at end of file
virtual void handle_prebroken_dependencies ();
virtual Interval_t<int> spanned_rank_interval () const;
virtual Interval pure_height (Grob *ref, int start, int end);
+ virtual void cache_pure_height (Interval height);
DECLARE_GROB_INTERFACE ();
protected:
virtual void discretionary_processing ();
static void add_head (Grob *me, Grob *n);
static Stem_info get_stem_info (Grob *);
static Real chord_start_y (Grob *);
- static void set_stemend (Grob *, Real);
+ static void set_stem_positions (Grob *, Real);
+ static void cache_pure_height (Grob *, Interval, Interval);
static Slice beam_multiplicity (Grob *);
static Direction get_default_dir (Grob *);
static Real thickness (Grob *);
+ static Real beam_end_corrective (Grob *);
static int head_count (Grob *);
static bool is_invisible (Grob *);
static bool is_normal_stem (Grob *);
static bool is_cross_staff (Grob *);
static Interval head_positions (Grob *);
- static Real stem_end_position (Grob *);
- static Stencil flag (Grob *);
- static Stencil get_translated_flag (Grob *);
+ static Interval internal_pure_height (Grob *, bool);
+ static Interval internal_height (Grob *, bool);
+ static bool is_valid_stem (Grob *);
+ static Grob *get_reference_head (Grob *);
+ static Real internal_calc_stem_end_position (Grob *, bool);
+ static Real internal_calc_stem_begin_position (Grob *, bool);
+
DECLARE_GROB_INTERFACE ();
static void set_spacing_hints (Grob *);
+ static Grob *flag (Grob *);
DECLARE_SCHEME_CALLBACK (print, (SCM));
DECLARE_SCHEME_CALLBACK (calc_default_direction, (SCM));
DECLARE_SCHEME_CALLBACK (offset_callback, (SCM element));
DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
DECLARE_SCHEME_CALLBACK (calc_beaming, (SCM));
- DECLARE_SCHEME_CALLBACK (calc_length, (SCM));
DECLARE_SCHEME_CALLBACK (calc_stem_begin_position, (SCM));
+ DECLARE_SCHEME_CALLBACK (pure_calc_stem_begin_position, (SCM, SCM, SCM));
DECLARE_SCHEME_CALLBACK (calc_stem_end_position, (SCM));
+ DECLARE_SCHEME_CALLBACK (pure_calc_stem_end_position, (SCM, SCM, SCM));
DECLARE_SCHEME_CALLBACK (calc_stem_info, (SCM));
DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM));
DECLARE_SCHEME_CALLBACK (width, (SCM smob));
DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM));
DECLARE_SCHEME_CALLBACK (height, (SCM));
DECLARE_SCHEME_CALLBACK (calc_cross_staff, (SCM));
- DECLARE_SCHEME_CALLBACK (calc_flag, (SCM));
};
#endif
if (cached_pure_height_valid_)
return cached_pure_height_ + pure_relative_y_coordinate (g, start, end);
- cached_pure_height_ = Grob::pure_height (this, start, end);
- cached_pure_height_valid_ = true;
+ cache_pure_height (Grob::pure_height (this, start, end));
return cached_pure_height_ + pure_relative_y_coordinate (g, start, end);
}
+void
+Item::cache_pure_height (Interval height)
+{
+ cached_pure_height_ = height;
+ cached_pure_height_valid_ = true;
+}
+
ADD_INTERFACE (Item,
"Grobs can be distinguished in their role in the horizontal"
" spacing. Many grobs define constraints on the spacing by"
#include "separation-item.hh"
#include "spacing-interface.hh"
#include "staff-spacing.hh"
+#include "staff-symbol-referencer.hh"
#include "stem.hh"
#include "warn.hh"
Interval hp = Stem::head_positions (stem);
if (!hp.is_empty ())
{
- Real chord_start = hp[stem_dir];
-
- /*
- can't look at stem-end-position, since that triggers
- beam slope computations.
- */
- Real stem_end = hp[stem_dir]
- + stem_dir * robust_scm2double (stem->get_property ("length"), 7);
-
- stem_posns[d] = Interval (min (chord_start, stem_end),
- max (chord_start, stem_end));
+ Real ss = Staff_symbol_referencer::staff_space (stem);
+ stem_posns[d] = stem->pure_height (stem, 0, INT_MAX) * (2 / ss);
head_posns[d].unite (hp);
}
}
{
vector<Grob *> rheads_;
Grob *stem_;
+ Grob *flag_;
Grob *note_column_;
Grob *arpeggio_;
protected:
DECLARE_ACKNOWLEDGER (stem);
+ DECLARE_ACKNOWLEDGER (flag);
DECLARE_ACKNOWLEDGER (rhythmic_head);
DECLARE_ACKNOWLEDGER (arpeggio);
void process_acknowledged ();
{
stem_ = 0;
+ flag_ = 0;
note_column_ = 0;
arpeggio_ = 0;
}
Pointer_group_interface::add_grob (note_column_, ly_symbol2scm ("elements"), arpeggio_);
note_column_->set_object ("arpeggio", arpeggio_->self_scm ());
}
+ if (flag_)
+ Pointer_group_interface::add_grob (note_column_, ly_symbol2scm ("elements"), flag_);
}
}
stem_ = i.grob ();
}
+void
+Rhythmic_column_engraver::acknowledge_flag (Grob_info i)
+{
+ flag_ = i.grob ();
+}
+
void
Rhythmic_column_engraver::acknowledge_rhythmic_head (Grob_info i)
{
note_column_ = 0;
stem_ = 0;
arpeggio_ = 0;
+ flag_ = 0;
}
ADD_ACKNOWLEDGER (Rhythmic_column_engraver, stem);
+ADD_ACKNOWLEDGER (Rhythmic_column_engraver, flag);
ADD_ACKNOWLEDGER (Rhythmic_column_engraver, rhythmic_head);
ADD_ACKNOWLEDGER (Rhythmic_column_engraver, arpeggio);
Direction d = get_grob_direction (stem);
if (Stem::is_normal_stem (stem) && d == DOWN)
{
-
- /*
- can't look at stem-end-position, since that triggers
- beam slope computations.
- */
- Real stem_start = Stem::head_positions (stem) [d];
- Real stem_end = stem_start
- + d * robust_scm2double (stem->get_property ("length"), 7);
-
- Interval stem_posns (min (stem_start, stem_end),
- max (stem_end, stem_start));
+ Interval stem_posns = stem->pure_height (stem, 0, INT_MAX);
stem_posns.intersect (bar_height);
{
Grob *stem_;
Grob *tremolo_;
+ vector <Grob *> maybe_flags_;
Stream_event *rhythmic_ev_;
Stream_event *tremolo_ev_;
DECLARE_TRANSLATOR_LISTENER (tremolo);
DECLARE_ACKNOWLEDGER (rhythmic_head);
void stop_translation_timestep ();
+ void finalize ();
+ void kill_unused_flags ();
};
Stem_engraver::Stem_engraver ()
/* Announce the cause of the head as cause of the stem. The
stem needs a rhythmic structure to fit it into a beam. */
stem_ = make_item ("Stem", gi.grob ()->self_scm ());
-
if (tremolo_ev_)
{
/* Stem tremolo is never applied to a note by default,
}
Stem::add_head (stem_, gi.grob ());
+
+ if (Stem::is_normal_stem (stem_)
+ && Stem::duration_log (stem_) > 2)
+ {
+ Item *flag = make_item ("Flag", stem_->self_scm ());
+ flag->set_parent (stem_, X_AXIS);
+ stem_->set_object ("flag", flag->self_scm ());
+ maybe_flags_.push_back (flag);
+ }
+}
+
+void
+Stem_engraver::kill_unused_flags ()
+{
+ for (vsize i = 0; i < maybe_flags_.size (); i++)
+ if (unsmob_grob (maybe_flags_[i]->get_parent (X_AXIS)->get_object ("beam")))
+ maybe_flags_[i]->suicide ();
+}
+
+void
+Stem_engraver::finalize ()
+{
+ kill_unused_flags ();
}
void
Stem_engraver::stop_translation_timestep ()
{
+ if (scm_is_string (get_property ("whichBar")))
+ kill_unused_flags ();
+
tremolo_ = 0;
if (stem_)
{
/* read */
"tremoloFlags "
"stemLeftBeamCount "
- "stemRightBeamCount ",
+ "stemRightBeamCount "
+ "whichBar ",
/* write */
""
Real beam_translation = get_beam_translation (me);
int beam_count = beam ? (Stem::beam_multiplicity (stem).length () + 1) : 0;
- Real ss = Staff_symbol_referencer::staff_space (me);
Real end_y
- = Stem::stem_end_position (stem) * ss / 2
+ = stem->extent (stem, Y_AXIS)[stemdir]
- stemdir * max (beam_count, 1) * beam_translation;
if (!beam && Stem::duration_log (stem) >= 3)
{
/* we shouldn't position relative to the end of the stem since the stem
is invisible */
+ Real ss = Staff_symbol_referencer::staff_space (me);
vector<int> nhp = Stem::note_head_positions (stem);
Real note_head = (stemdir == UP ? nhp.back () : nhp[0]) * ss / 2;
end_y = note_head + stemdir * 1.5;
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
+/*
+ Note that several internal functions have a calc_beam bool argument.
+ This argument means: "If set, acknowledge the fact that there is a beam
+ and deal with it. If not, give me the measurements as if there is no beam."
+ Most pure functions are called WITHOUT calc_beam, whereas non-pure functions
+ are called WITH calc_beam.
+
+ The only exception to this is ::pure_height, which calls internal_pure_height
+ with "true" for calc_beam in order to trigger the calculations of other
+ pure heights in case there is a beam. It passes false, however, to
+ internal_height and internal_pure_height for all subsequent iterations.
+*/
+
#include "stem.hh"
#include "spanner.hh"
}
void
-Stem::set_stemend (Grob *me, Real se)
+Stem::set_stem_positions (Grob *me, Real se)
{
// todo: margins
Direction d = get_grob_direction (me);
+ Grob *beam = unsmob_grob (me->get_object ("beam"));
if (d && d * head_positions (me)[get_grob_direction (me)] >= se * d)
me->warning (_ ("weird stem size, check for narrow beams"));
- me->set_property ("stem-end-position", scm_from_double (se));
+ Interval height = me->pure_height (me, 0, INT_MAX);
+ Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5;
+
+ height[d] = se * half_space + beam_end_corrective (me);
+
+ Real stemlet_length = robust_scm2double (me->get_property ("stemlet-length"),
+ 0.0);
+ bool stemlet = stemlet_length > 0.0;
+
+ Grob *lh = get_reference_head (me);
+
+ if (!lh)
+ {
+ if (stemlet && beam)
+ {
+ Real beam_translation = Beam::get_beam_translation (beam);
+ Real beam_thickness = Beam::get_beam_thickness (beam);
+ int beam_count = beam_multiplicity (me).length () + 1;
+
+ height[-d] = (height[d] - d
+ * (0.5 * beam_thickness
+ + beam_translation * max (0, (beam_count - 1))
+ + stemlet_length));
+ }
+ else if (!stemlet && beam)
+ height[-d] = height[d];
+ else if (stemlet && !beam)
+ me->programming_error ("Can't have a stemlet without a beam.");
+ }
+
+ me->set_property ("Y-extent", ly_interval2scm (height));
}
/* Note head that determines hshift for upstems
SCM /* end */)
{
Grob *me = unsmob_grob (smob);
- Interval iv;
+ return ly_interval2scm (internal_pure_height (me, true));
+}
+Interval
+Stem::internal_pure_height (Grob *me, bool calc_beam)
+{
if (!is_normal_stem (me))
- return ly_interval2scm (iv);
+ return Interval (0.0, 0.0);
- Real ss = Staff_symbol_referencer::staff_space (me);
- Real rad = Staff_symbol_referencer::staff_radius (me);
+ Grob *beam = unsmob_grob (me->get_object ("beam"));
+
+ Interval iv = internal_height (me, false);
- if (!to_boolean (me->get_property ("cross-staff")))
+ if (!beam)
+ return iv;
+ if (!to_boolean (me->get_property ("cross-staff")) && calc_beam)
{
- Real len_in_halfspaces;
- SCM user_set_len_scm = me->get_property_data ("length");
- if (scm_is_number (user_set_len_scm))
- len_in_halfspaces = scm_to_double (user_set_len_scm);
- else
- len_in_halfspaces = scm_to_double (calc_length (smob));
- Real len = len_in_halfspaces * ss / 2;
+ Interval overshoot;
Direction dir = get_grob_direction (me);
+ Direction d = DOWN;
+ do
+ overshoot[d] = d == dir ? dir * infinity_f : iv[d];
+ while (flip (&d) != DOWN);
- Interval hp = head_positions (me);
- if (dir == UP)
- iv = Interval (0, len);
- else
- iv = Interval (-len, 0);
+ vector<Interval> heights;
+ vector<Grob *> my_stems;
+ extract_grob_set (beam, "normal-stems", normal_stems);
+ for (vsize i = 0; i < normal_stems.size (); i++)
+ if (normal_stems[i] != me && get_grob_direction (normal_stems[i]) == dir)
+ {
+ heights.push_back (Stem::internal_pure_height (normal_stems[i], false));
+ my_stems.push_back (normal_stems[i]);
+ iv.unite (heights.back ());
+ }
+ for (vsize i = 0; i < my_stems.size (); i++)
+ cache_pure_height (my_stems[i], iv, heights[i]);
+ iv.intersect (overshoot);
+ }
- if (!hp.is_empty ())
- {
- iv.translate (hp[dir] * ss / 2);
- iv.add_point (hp[-dir] * ss / 2);
- }
+ return iv;
+}
- /* extend the stem (away from the head) to cover the staff */
- if (dir == UP)
- iv[UP] = max (iv[UP], rad * ss);
- else
- iv[DOWN] = min (iv[DOWN], -rad * ss);
- }
- else
- iv = Interval (-rad * ss, rad * ss);
+void
+Stem::cache_pure_height (Grob *me, Interval iv, Interval my_iv)
+{
+ Interval overshoot;
+ Direction dir = get_grob_direction (me);
+ Direction d = DOWN;
+ do
+ overshoot[d] = d == dir ? dir * infinity_f : my_iv[d];
+ while (flip (&d) != DOWN);
- return ly_interval2scm (iv);
+ iv.intersect (overshoot);
+ dynamic_cast<Item *> (me)->cache_pure_height (iv);
}
MAKE_SCHEME_CALLBACK (Stem, calc_stem_end_position, 1)
Stem::calc_stem_end_position (SCM smob)
{
Grob *me = unsmob_grob (smob);
+ return scm_from_double (internal_calc_stem_end_position (me, true));
+}
+MAKE_SCHEME_CALLBACK (Stem, pure_calc_stem_end_position, 3)
+SCM
+Stem::pure_calc_stem_end_position (SCM smob,
+ SCM, /* start */
+ SCM /* end */)
+{
+ Grob *me = unsmob_grob (smob);
+ return scm_from_double (internal_calc_stem_end_position (me, false));
+}
+
+Real
+Stem::internal_calc_stem_end_position (Grob *me, bool calc_beam)
+{
if (!head_count (me))
- return scm_from_double (0.0);
+ return 0.0;
- if (Grob *beam = get_beam (me))
+ Grob *beam = get_beam (me);
+ Real ss = Staff_symbol_referencer::staff_space (me);
+ if (beam && calc_beam)
{
(void) beam->get_property ("quantized-positions");
- return me->get_property ("stem-end-position");
+ return me->extent (me, Y_AXIS)[get_grob_direction (me)] * ss * 2;
}
vector<Real> a;
/* WARNING: IN HALF SPACES */
- Real length = robust_scm2double (me->get_property ("length"), 7);
-
- Direction dir = get_grob_direction (me);
- Interval hp = head_positions (me);
- Real stem_end = dir ? hp[dir] + dir * length : 0;
-
- /* TODO: change name to extend-stems to staff/center/'() */
- bool no_extend = to_boolean (me->get_property ("no-stem-extend"));
- if (!no_extend && dir * stem_end < 0)
- stem_end = 0.0;
-
- return scm_from_double (stem_end);
-}
-
-/* Length is in half-spaces (or: positions) here. */
-MAKE_SCHEME_CALLBACK (Stem, calc_length, 1)
-SCM
-Stem::calc_length (SCM smob)
-{
- Grob *me = unsmob_grob (smob);
-
SCM details = me->get_property ("details");
int durlog = duration_log (me);
- Real ss = Staff_symbol_referencer::staff_space (me);
Real staff_rad = Staff_symbol_referencer::staff_radius (me);
Real length = 7;
SCM s = ly_assoc_get (ly_symbol2scm ("lengths"), details, SCM_EOL);
/* Tremolo stuff. */
Grob *t_flag = unsmob_grob (me->get_object ("tremolo-flag"));
- if (t_flag && !unsmob_grob (me->get_object ("beam")))
+ if (t_flag && (!unsmob_grob (me->get_object ("beam")) || !calc_beam))
{
/* Crude hack: add extra space if tremolo flag is there.
length = max (length, minlen + 1.0);
}
- return scm_from_double (length);
+ Real stem_end = dir ? hp[dir] + dir * length : 0;
+
+ /* TODO: change name to extend-stems to staff/center/'() */
+ bool no_extend = to_boolean (me->get_property ("no-stem-extend"));
+ if (!no_extend && dir * stem_end < 0)
+ stem_end = 0.0;
+
+ return stem_end;
}
+
/* The log of the duration (Number of hooks on the flag minus two) */
int
Stem::duration_log (Grob *me)
return scm_from_int (dir);
}
+// note - height property necessary to trigger quantized beam positions
+// otherwise, we could just use Grob::stencil_height_proc
MAKE_SCHEME_CALLBACK (Stem, height, 1);
SCM
Stem::height (SCM smob)
{
Grob *me = unsmob_grob (smob);
- if (!is_normal_stem (me))
- return ly_interval2scm (Interval ());
-
- Direction dir = get_grob_direction (me);
+ return ly_interval2scm (internal_height (me, true));
+}
- Grob *beam = get_beam (me);
- if (beam)
- {
- /* trigger set-stem-lengths. */
- beam->get_property ("quantized-positions");
- }
+Grob*
+Stem::get_reference_head (Grob *me)
+{
+ return to_boolean (me->get_property ("avoid-note-head"))
+ ? last_head (me)
+ : first_head (me);
+}
- /*
- Can't get_stencil (), since that would cache stencils too early.
- This causes problems with beams.
- */
- Stencil *stencil = unsmob_stencil (print (smob));
- Interval iv = stencil ? stencil->extent (Y_AXIS) : Interval ();
+Real
+Stem::beam_end_corrective (Grob *me)
+{
+ Grob *beam = unsmob_grob (me->get_object ("beam"));
+ Direction dir = get_grob_direction (me);
if (beam)
{
if (dir == CENTER)
programming_error ("no stem direction");
dir = UP;
}
- iv[dir] += dir * Beam::get_beam_thickness (beam) * 0.5;
+ return dir * Beam::get_beam_thickness (beam) * 0.5;
}
-
- return ly_interval2scm (iv);
+ return 0.0;
}
-Real
-Stem::stem_end_position (Grob *me)
+Interval
+Stem::internal_height (Grob *me, bool calc_beam)
{
- return robust_scm2double (me->get_property ("stem-end-position"), 0);
-}
+ if (!is_valid_stem (me))
+ return Interval ();
-MAKE_SCHEME_CALLBACK (Stem, calc_flag, 1);
-SCM
-Stem::calc_flag (SCM smob)
-{
- Grob *me = unsmob_grob (smob);
+ Direction dir = get_grob_direction (me);
- int log = duration_log (me);
- /*
- TODO: maybe property stroke-style should take different values,
- e.g. "" (i.e. no stroke), "single" and "double" (currently, it's
- '() or "grace"). */
- string flag_style;
-
- SCM flag_style_scm = me->get_property ("flag-style");
- if (scm_is_symbol (flag_style_scm))
- flag_style = ly_symbol2string (flag_style_scm);
-
- if (flag_style == "no-flag")
- return Stencil ().smobbed_copy ();
-
- bool adjust = true;
-
- string staffline_offs;
- if (flag_style == "mensural")
- /* Mensural notation: For notes on staff lines, use different
- flags than for notes between staff lines. The idea is that
- flags are always vertically aligned with the staff lines,
- regardless if the note head is on a staff line or between two
- staff lines. In other words, the inner end of a flag always
- touches a staff line.
- */
- {
- if (adjust)
- {
- int p = (int) (rint (stem_end_position (me)));
- staffline_offs
- = Staff_symbol_referencer::on_line (me, p) ? "0" : "1";
- }
- else
- staffline_offs = "2";
- }
- else
- staffline_offs = "";
-
- char dir = (get_grob_direction (me) == UP) ? 'u' : 'd';
- string font_char = flag_style
- + to_string (dir) + staffline_offs + to_string (log);
- Font_metric *fm = Font_interface::get_default_font (me);
- Stencil flag = fm->find_by_name ("flags." + font_char);
- if (flag.is_empty ())
- me->warning (_f ("flag `%s' not found", font_char));
-
- SCM stroke_style_scm = me->get_property ("stroke-style");
- if (scm_is_string (stroke_style_scm))
+ Grob *beam = get_beam (me);
+ if (beam && calc_beam)
{
- string stroke_style = ly_scm2string (stroke_style_scm);
- if (!stroke_style.empty ())
- {
- string font_char = flag_style + to_string (dir) + stroke_style;
- Stencil stroke = fm->find_by_name ("flags." + font_char);
- if (stroke.is_empty ())
- {
- font_char = to_string (dir) + stroke_style;
- stroke = fm->find_by_name ("flags." + font_char);
- }
- if (stroke.is_empty ())
- me->warning (_f ("flag stroke `%s' not found", font_char));
- else
- flag.add_stencil (stroke);
- }
+ /* trigger set-stem-lengths. */
+ (void) beam->get_property ("quantized-positions");
+ return me->extent (me, Y_AXIS);
}
- return flag.smobbed_copy ();
-}
+ Real y2 = internal_calc_stem_end_position (me, calc_beam);
+ Real y1 = internal_calc_stem_begin_position (me, calc_beam);
-Stencil
-Stem::flag (Grob *me)
-{
- int log = duration_log (me);
- if (log < 3
- || unsmob_grob (me->get_object ("beam")))
- return Stencil ();
+ Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5;
- if (!is_normal_stem (me))
- return Stencil ();
+ Interval stem_y = Interval (min (y1, y2), max (y2, y1)) * half_space;
+ stem_y[dir] += beam_end_corrective (me);
- // This get_property call already evaluates the scheme function with
- // the grob passed as argument! Thus, we only have to check if a valid
- // stencil is returned.
- SCM flag_style_scm = me->get_property ("flag");
- if (Stencil *flag = unsmob_stencil (flag_style_scm))
- {
- return *flag;
- }
- else
- {
- return Stencil ();
- }
+ return stem_y;
}
MAKE_SCHEME_CALLBACK (Stem, width, 1);
if (is_invisible (me))
r.set_empty ();
- else if (unsmob_grob (me->get_object ("beam"))
- || abs (duration_log (me)) <= 2)
+ else
{
r = Interval (-1, 1);
r *= thickness (me) / 2;
}
- else
- {
- r = Interval (-1, 1) * thickness (me) * 0.5;
- r.unite (flag (me).extent (X_AXIS));
- }
+
return ly_interval2scm (r);
}
Stem::calc_stem_begin_position (SCM smob)
{
Grob *me = unsmob_grob (smob);
+ return scm_from_double (internal_calc_stem_begin_position (me, true));
+}
+
+MAKE_SCHEME_CALLBACK (Stem, pure_calc_stem_begin_position, 3);
+SCM
+Stem::pure_calc_stem_begin_position (SCM smob,
+ SCM, /* start */
+ SCM /* end */)
+{
+ Grob *me = unsmob_grob (smob);
+ return scm_from_double (internal_calc_stem_begin_position (me, false));
+}
+
+Real
+Stem::internal_calc_stem_begin_position (Grob *me, bool calc_beam)
+{
+ Grob *beam = get_beam (me);
+ Real ss = Staff_symbol_referencer::staff_space (me);
+ if (beam && calc_beam)
+ {
+ (void) beam->get_property ("quantized-positions");
+ return me->extent (me, Y_AXIS)[-get_grob_direction (me)] * ss * 2;
+ }
+
Direction d = get_grob_direction (me);
- Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5;
- Grob *lh
- = to_boolean (me->get_property ("avoid-note-head"))
- ? last_head (me)
- : first_head (me);
+ Grob *lh = get_reference_head (me);
Real pos = Staff_symbol_referencer::get_position (lh);
Real y_attach = Note_head::stem_attachment_coordinate (head, Y_AXIS);
y_attach = head_height.linear_combination (y_attach);
- pos += d * y_attach / half_space;
+ pos += d * y_attach * 2 / ss;
}
- return scm_from_double (pos);
+ return pos;
}
-MAKE_SCHEME_CALLBACK (Stem, print, 1);
-SCM
-Stem::print (SCM smob)
+bool
+Stem::is_valid_stem (Grob *me)
{
- Grob *me = unsmob_grob (smob);
- Grob *beam = get_beam (me);
-
- Stencil mol;
- Direction d = get_grob_direction (me);
-
+ /* TODO: make the stem start a direction ?
+ This is required to avoid stems passing in tablature chords. */
Real stemlet_length = robust_scm2double (me->get_property ("stemlet-length"),
0.0);
bool stemlet = stemlet_length > 0.0;
- /* TODO: make the stem start a direction ?
- This is required to avoid stems passing in tablature chords. */
- Grob *lh
- = to_boolean (me->get_property ("avoid-note-head"))
- ? last_head (me)
- : first_head (me);
+ Grob *lh = get_reference_head (me);
+ Grob *beam = unsmob_grob (me->get_object ("beam"));
if (!lh && !stemlet)
- return SCM_EOL;
+ return false;
if (!lh && stemlet && !beam)
- return SCM_EOL;
+ return false;
if (lh && robust_scm2int (lh->get_property ("duration-log"), 0) < 1)
- return SCM_EOL;
+ return false;
if (is_invisible (me))
- return SCM_EOL;
+ return false;
- Real y2 = robust_scm2double (me->get_property ("stem-end-position"), 0.0);
- Real y1 = y2;
- Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5;
+ return true;
+}
- if (lh)
- y2 = robust_scm2double (me->get_property ("stem-begin-position"), 0.0);
- else if (stemlet)
- {
- Real beam_translation = Beam::get_beam_translation (beam);
- Real beam_thickness = Beam::get_beam_thickness (beam);
- int beam_count = beam_multiplicity (me).length () + 1;
-
- y2 -= d
- * (0.5 * beam_thickness
- + beam_translation * max (0, (beam_count - 1))
- + stemlet_length) / half_space;
- }
+MAKE_SCHEME_CALLBACK (Stem, print, 1);
+SCM
+Stem::print (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ if (!is_valid_stem (me))
+ return SCM_EOL;
- Interval stem_y (min (y1, y2), max (y2, y1));
+ Interval stem_y = me->extent (me, Y_AXIS);
+ Direction dir = get_grob_direction (me);
+
+ stem_y[dir] -= beam_end_corrective (me);
// URG
Real stem_width = thickness (me);
= me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
Box b = Box (Interval (-stem_width / 2, stem_width / 2),
- Interval (stem_y[DOWN] * half_space, stem_y[UP] * half_space));
+ stem_y);
+ Stencil mol;
Stencil ss = Lookup::round_filled_box (b, blot);
mol.add_stencil (ss);
- mol.add_stencil (get_translated_flag (me));
-
return mol.smobbed_copy ();
}
-Stencil
-Stem::get_translated_flag (Grob *me)
-{
- Stencil fl = flag (me);
- if (!fl.is_empty ())
- {
- Direction d = get_grob_direction (me);
- Real blot
- = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
- Real stem_width = thickness (me);
- Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5;
- Real y2 = robust_scm2double (me->get_property ("stem-end-position"), 0.0);
- fl.translate_axis (y2 * half_space - d * blot / 2, Y_AXIS);
- fl.translate_axis (stem_width / 2, X_AXIS);
- }
- return fl;
-}
-
/*
move the stem to right of the notehead if it is up.
*/
return scm_from_bool (is_cross_staff (unsmob_grob (smob)));
}
+Grob*
+Stem::flag (Grob *me)
+{
+ return unsmob_grob (me->get_object ("flag"));
+}
+
/* FIXME: Too many properties */
ADD_INTERFACE (Stem,
"The stem represents the graphical stem. In addition, it"
"direction "
"duration-log "
"flag "
- "flag-style "
"french-beaming "
- "length "
"length-fraction "
"max-beam-connect "
"neutral-direction "
"note-heads "
"positioning-done "
"rests "
- "stem-begin-position "
- "stem-end-position "
"stem-info "
"stemlet-length "
- "stroke-style "
"thickness "
"tremolo-flag "
);
else
{
if (use_horizontal_spacing_ || !Stem::get_beam (stem))
- stem_end_position = Stem::stem_end_position (stem) * staff_space * .5;
+ stem_end_position = stem->extent (stem, Y_AXIS)[get_grob_direction (stem)];
else
+ // May want to change this to the stem's pure height...
stem_end_position = Stem::note_head_positions (stem)[get_grob_direction (stem)]
* staff_space * .5;
}
if (dir == LEFT)
{
- Box flag_box = Stem::get_translated_flag (stem).extent_box ();
- flag_box.translate ( Offset (x[RIGHT], X_AXIS));
- boxes.push_back (flag_box);
+ Grob *flag = Stem::flag (stem);
+ if (flag)
+ {
+ Grob* commony = stem->common_refpoint (flag, Y_AXIS);
+ boxes.push_back (Box (flag->extent (x_refpoint_, X_AXIS),
+ flag->extent (commony, Y_AXIS)));
+ }
}
}
else
&& Note_column::get_stem (columns[0])
&& Note_column::get_stem (columns.back ()))
{
- /*
- trigger set_stem_ends
- */
- (void) par_beam->get_property ("quantized-positions");
-
Drul_array<Grob *> stems (Note_column::get_stem (columns[0]),
Note_column::get_stem (columns.back ()));
- Real ss = 0.5 * Staff_symbol_referencer::staff_space (me);
- Real lp = ss * robust_scm2double (stems[LEFT]->get_property ("stem-end-position"), 0.0)
+ Real lp = stems[LEFT]->extent (stems[LEFT], Y_AXIS)[get_grob_direction (stems[LEFT])]
+ stems[LEFT]->get_parent (Y_AXIS)->relative_coordinate (commony, Y_AXIS);
- Real rp = ss * robust_scm2double (stems[RIGHT]->get_property ("stem-end-position"), 0.0)
+ Real rp = stems[RIGHT]->extent (stems[RIGHT], Y_AXIS)[get_grob_direction (stems[RIGHT])]
+ stems[RIGHT]->get_parent (Y_AXIS)->relative_coordinate (commony, Y_AXIS);
*dy = rp - lp;
graceSettings = #`(
(Voice Stem direction ,UP)
(Voice Stem font-size -3)
+ (Voice Flag font-size -3)
(Voice NoteHead font-size -3)
(Voice TabNoteHead font-size -4)
(Voice Dots font-size -3)
\remove "Accidental_engraver"
%% make the Stems as short as possible to minimize their influence
%% on the slur::calc-control-points routine
- \override Stem #'length = #0
\override Stem #'no-stem-extend = ##t
- \override Stem #'flag-style = #'no-flag
+ \override Flag #'style = #'no-flag
\override Stem #'details = #'((lengths 0 0 0 0 0 0)
(beamed-lengths 0 0 0)
(beamed-minimum-free-lengths 0 0 0)
startAcciaccaturaMusic = {
s1*0\startGraceSlur
- \override Stem #'stroke-style = #"grace"
+ \override Flag #'stroke-style = #"grace"
}
stopAcciaccaturaMusic = {
- \revert Stem #'stroke-style
+ \revert Flag #'stroke-style
s1*0\stopGraceSlur
}
startSlashedGraceMusic = {
- \override Stem #'stroke-style = #"grace"
+ \override Flag #'stroke-style = #"grace"
}
stopSlashedGraceMusic = {
- \revert Stem #'stroke-style
+ \revert Flag #'stroke-style
}
\consists Vaticana_ligature_engraver
\override NoteHead #'style = #'vaticana.punctum
\override Stem #'transparent = ##t
+ \override Flag #'transparent = ##t
}
}
\override NoteHead #'transparent = ##t
\override NoteHead #'no-ledgers = ##t
\override Stem #'transparent = ##t
+ \override Flag #'transparent = ##t
\override Beam #'transparent = ##t
\override Accidental #'transparent = ##t
}
\revert Accidental #'transparent
\revert Beam #'transparent
\revert Stem #'transparent
+ \revert Flag #'transparent
\revert NoteHead #'transparent
\revert NoteHead #'no-ledgers
\revert Dots #'transparent
% stems (the half note gets a double stem)
\revert TabVoice.Stem #'length
\revert TabVoice.Stem #'no-stem-extend
- \revert TabVoice.Stem #'flag-style
+ \revert TabVoice.Flag #'style
\revert TabVoice.Stem #'details
\revert TabVoice.Stem #'transparent
\override TabVoice.Stem #'stencil = #tabvoice::draw-double-stem-for-half-notes
\override NoteHead #'style = #'diamond
\override NoteHead #'color = #red
\override Stem #'color = #red
+ \override Flag #'color = #red
\override Beam #'color = #red
}
voiceTwoStyle = {
\override NoteHead #'style = #'triangle
\override NoteHead #'color = #blue
\override Stem #'color = #blue
+ \override Flag #'color = #blue
\override Beam #'color = #blue
}
voiceThreeStyle = {
\override NoteHead #'style = #'xcircle
\override NoteHead #'color = #green
\override Stem #'color = #green
+ \override Flag #'color = #green
\override Beam #'color = #green
}
voiceFourStyle = {
\override NoteHead #'style = #'cross
\override NoteHead #'color = #magenta
\override Stem #'color = #magenta
+ \override Flag #'color = #magenta
\override Beam #'color = #magenta
}
voiceNeutralStyle = {
\revert NoteHead #'style
\revert NoteHead #'color
\revert Stem #'color
+ \revert Flag #'color
\revert Beam #'color
}
;;
;; f
;;
- (flag ,ly:stencil? "A function returning the full flag stencil
-for the @code{Stem}, which is passed to the function as the only
-argument. The default ly:stem::calc-stencil function uses the
-@code{flag-style} property to determine the correct glyph for the
-flag. By providing your own function, you can create arbitrary
-flags.")
(flag-count ,number? "The number of tremolo beams.")
- (flag-style ,symbol? "A symbol determining what style of flag
-glyph is typeset on a @code{Stem}. Valid options include @code{'()}
-for standard flags, @code{'mensural} and @code{'no-flag}, which
-switches off the flag.")
(font-encoding ,symbol? "The font encoding is the broadest
category for selecting a font. Currently, only lilypond's system
fonts (Emmentaler) are using this property. Available
structure.")
(stem-attachment ,number-pair? "An @code{(@var{x} . @var{y})}
pair where the stem attaches to the notehead.")
- (stem-begin-position ,number? "Where does the stem begin (the
-position of the support-head)?")
- (stem-end-position ,number? "Where does the stem end (the end is
-opposite to the support-head)?")
;;[TODO: doco]
(stem-spacing-correction ,number? "Optical correction amount for
stems that are placed in tight configurations. For opposite
in addition to notes and stems.")
(figures ,ly:grob-array? "Figured bass objects for continuation line.")
+ (flag ,ly:grob? "A pointer to a @code{Flag} object.")
(glissando-index ,integer? "The index of a glissando in its note
column.")
(clip-edges . #t)
(collision-interfaces . (beam-interface
clef-interface
+ flag-interface
inline-accidental-interface
key-signature-interface
note-head-interface
text-interface
text-script-interface))))))
+ (Flag
+ . (
+ (stencil . ,ly:flag::print)
+ (X-extent . ,ly:flag::width)
+ (X-offset . ,ly:flag::calc-x-offset)
+ (Y-offset . ,ly:flag::calc-y-offset)
+ (meta . ((class . Item)
+ (interfaces . (flag-interface
+ font-interface))))))
+
(FootnoteItem
. (
(annotation-balloon . #f)
(direction . ,ly:stem::calc-direction)
(duration-log . ,stem::calc-duration-log)
- (flag . ,ly:stem::calc-flag)
- (length . ,ly:stem::calc-length)
(neutral-direction . ,DOWN)
(positioning-done . ,ly:stem::calc-positioning-done)
- (stem-begin-position . ,ly:stem::calc-stem-begin-position)
- (stem-end-position . ,ly:stem::calc-stem-end-position)
(stem-info . ,ly:stem::calc-stem-info)
(stencil . ,ly:stem::print)
(thickness . 1.3)
(Y-extent . ,ly:stem::height)
(Y-offset . ,ly:staff-symbol-referencer::callback)
(meta . ((class . Item)
- (interfaces . (font-interface
- stem-interface))))))
+ (interfaces . (stem-interface))))))
(StemTremolo
. (
ly:note-head::print
ly:dots::print
ly:clef::print
+ ly:flag::print
+ default-flag
+ normal-flag
+ mensural-flag
+ no-flag
+ modern-straight-flag
+ old-straight-flag
ly:key-signature-interface::print
ly:percent-repeat-item-interface::beat-slash
ly:text-interface::print
(,ly:side-position-interface::y-aligned-side . ,ly:side-position-interface::pure-y-aligned-side)
(,ly:slur::height . ,ly:slur::pure-height)
(,ly:slur::outside-slur-callback . ,ly:slur::pure-outside-slur-callback)
+ (,ly:stem::calc-stem-end-position . ,ly:stem::pure-calc-stem-end-position)
(,ly:stem::height . ,ly:stem::pure-height)
(,ly:system::height . ,ly:system::calc-pure-height)))
(list
parenthesize-elements
laissez-vibrer::print
+ ly:flag::calc-y-offset
ly:rest::y-offset-callback
ly:staff-symbol-referencer::callback
ly:staff-symbol::height))
;;;; notably the old-straight-flag and the modern-straight-flag styles.
-(define-public (no-flag stem-grob)
+(define-public (no-flag grob)
"No flag: Simply return empty stencil."
empty-stencil)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(define-public (add-stroke-straight stencil stem-grob dir log stroke-style
+(define-public (add-stroke-straight stencil grob dir log stroke-style
offset length thickness stroke-thickness)
"Add the stroke for acciaccatura to the given flag stencil.
The stroke starts for up-flags at `upper-end-of-flag + (0,length/2)'
the angle! Other combinations don't look as good.
For down-stems the y-coordinates are simply mirrored."
- (let* ((start (offset-add offset (cons 0 (* (/ length 2) dir))))
+ (let* ((stem-grob (ly:grob-parent grob X))
+ (start (offset-add offset (cons 0 (* (/ length 2) dir))))
(end (offset-add (cons 0 (cdr offset))
(cons (- (/ (car offset) 2)) (* (- (+ thickness (car offset))) dir))))
(stroke (make-line-stencil stroke-thickness (car start) (cdr start) (car end) (cdr end))))
All lengths are scaled according to the font size of the note."
- (lambda (stem-grob)
- (let* ((log (ly:grob-property stem-grob 'duration-log))
+ (lambda (grob)
+ (let* ((stem-grob (ly:grob-parent grob X))
+ (log (ly:grob-property stem-grob 'duration-log))
(dir (ly:grob-property stem-grob 'direction))
(stem-up (eqv? dir UP))
- (layout (ly:grob-layout stem-grob))
+ (layout (ly:grob-layout grob))
; scale with the note size (e.g. for grace notes)
- (factor (magstep (ly:grob-property stem-grob 'font-size 0)))
+ (factor (magstep (ly:grob-property grob 'font-size 0)))
(grob-stem-thickness (ly:grob-property stem-grob 'thickness))
(line-thickness (ly:output-def-lookup layout 'line-thickness))
(half-stem-thickness (/ (* grob-stem-thickness line-thickness) 2))
(stencil (ly:round-filled-polygon points half-stem-thickness))
; Log for 1/8 is 3, so we need to subtract 3
(flag-stencil (buildflag stencil (- log 3) stencil spacing))
- (stroke-style (ly:grob-property stem-grob 'stroke-style)))
+ (stroke-style (ly:grob-property grob 'stroke-style)))
(if (equal? stroke-style "grace")
- (add-stroke-straight flag-stencil stem-grob
+ (add-stroke-straight flag-stencil grob
dir log
stroke-style
flag-end flag-length
(* half-stem-thickness 2))
flag-stencil))))
-(define-public (modern-straight-flag stem-grob)
+(define-public (modern-straight-flag grob)
"Modern straight flag style (for composers like Stockhausen, Boulez, etc.).
The angles are 18 and 22 degrees and thus smaller than for the ancient style
of Bach, etc."
- ((straight-flag 0.55 1 -18 1.1 22 1.2) stem-grob))
+ ((straight-flag 0.55 1 -18 1.1 22 1.2) grob))
-(define-public (old-straight-flag stem-grob)
+(define-public (old-straight-flag grob)
"Old straight flag style (for composers like Bach). The angles of the
flags are both 45 degrees."
- ((straight-flag 0.55 1 -45 1.2 45 1.4) stem-grob))
+ ((straight-flag 0.55 1 -45 1.2 45 1.4) grob))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; NOTE: By default, lilypond uses the C++ method Stem::calc-flag
-; (ly:stem::calc-flag is the corresponding Scheme interface) to generate the
+; NOTE: By default, lilypond uses the C++ method Flag::stencil
+; (ly:flag::stencil is the corresponding Scheme interface) to generate the
; flag stencil. The following functions are simply a reimplementation in
; Scheme, so that one has that functionality available in Scheme, if one
; wants to write a flag style, which modifies one of the standard flags
; by some stencil operations.
-(define-public (add-stroke-glyph stencil stem-grob dir stroke-style flag-style)
+(define-public (add-stroke-glyph stencil grob dir stroke-style flag-style)
"Load and add a stroke (represented by a glyph in the font) to the given
flag stencil."
(if (not (string? stroke-style))
stencil
; Otherwise: look up the stroke glyph and combine it with the flag
- (let* ((font-char (string-append "flags." flag-style dir stroke-style))
+ (let* ((stem-grob (ly:grob-parent grob X))
+ (font-char (string-append "flags." flag-style dir stroke-style))
(alt-font-char (string-append "flags." dir stroke-style))
- (font (ly:grob-default-font stem-grob))
+ (font (ly:grob-default-font grob))
(tmpstencil (ly:font-get-glyph font font-char))
(stroke-stencil (if (ly:stencil-empty? tmpstencil)
(ly:font-get-glyph font alt-font-char)
(ly:stencil-add stencil stroke-stencil)))))
-(define-public (retrieve-glyph-flag flag-style dir dir-modifier stem-grob)
+(define-public (retrieve-glyph-flag flag-style dir dir-modifier grob)
"Load the correct flag glyph from the font."
- (let* ((log (ly:grob-property stem-grob 'duration-log))
- (font (ly:grob-default-font stem-grob))
+ (let* ((stem-grob (ly:grob-parent grob X))
+ (log (ly:grob-property stem-grob 'duration-log))
+ (font (ly:grob-default-font grob))
(font-char (string-append "flags." flag-style dir dir-modifier (number->string log)))
(flag (ly:font-get-glyph font font-char)))
(if (ly:stencil-empty? flag)
flag))
-(define-public (create-glyph-flag flag-style dir-modifier stem-grob)
+(define-public (create-glyph-flag flag-style dir-modifier grob)
"Create a flag stencil by looking up the glyph from the font."
- (let* ((dir (if (eqv? (ly:grob-property stem-grob 'direction) UP) "u" "d"))
- (flag (retrieve-glyph-flag flag-style dir dir-modifier stem-grob))
- (stroke-style (ly:grob-property stem-grob 'stroke-style)))
+ (let* ((stem-grob (ly:grob-parent grob X))
+ (dir (if (eqv? (ly:grob-property stem-grob 'direction) UP) "u" "d"))
+ (flag (retrieve-glyph-flag flag-style dir dir-modifier grob))
+ (stroke-style (ly:grob-property grob 'stroke-style)))
(if (null? stroke-style)
flag
- (add-stroke-glyph flag stem-grob dir stroke-style flag-style))))
+ (add-stroke-glyph flag grob dir stroke-style flag-style))))
-(define-public (mensural-flag stem-grob)
+(define-public (mensural-flag grob)
"Mensural flags: Create the flag stencil by loading the glyph from the font.
Flags are always aligned with staff lines, so we need to check the end point
of the stem: For stems ending on staff lines, use different flags than for
staff line or between two staff lines. In other words, the inner end of
a flag always touches a staff line."
- (let* ((adjust #t)
- (stem-end (inexact->exact (round (ly:grob-property stem-grob 'stem-end-position))))
+ (let* ((stem-grob (ly:grob-parent grob X))
+ (adjust #t)
+ (d (ly:grob-property stem-grob 'direction))
+ (ss (ly:staff-symbol-staff-space stem-grob))
+ (stem-end (inexact->exact (round (* (index-cell
+ (ly:grob-extent stem-grob
+ stem-grob
+ Y)
+ d)
+ (/ 2 ss)))))
; For some reason the stem-end is a real instead of an integer...
(dir-modifier (if (ly:position-on-line? stem-grob stem-end) "1" "0"))
(modifier (if adjust dir-modifier "2")))
- (create-glyph-flag "mensural" modifier stem-grob)))
+ (create-glyph-flag "mensural" modifier grob)))
-(define-public ((glyph-flag flag-style) stem-grob)
+(define-public ((glyph-flag flag-style) grob)
"Simulatesthe default way of generating flags: Look up glyphs
@code{flags.style[ud][1234]} from the feta font and use it for the flag
stencil."
- (create-glyph-flag flag-style "" stem-grob))
+ (create-glyph-flag flag-style "" grob))
-(define-public (normal-flag stem-grob)
+(define-public (normal-flag grob)
"Create a default flag."
- (create-glyph-flag "" "" stem-grob))
+ (create-glyph-flag "" "" grob))
-(define-public (default-flag stem-grob)
+(define-public (default-flag grob)
"Create a flag stencil for the stem. Its style will be derived from the
-@code{'flag-style} Stem property. By default, @code{lilypond} uses a
+@code{'style} Flag property. By default, @code{lilypond} uses a
C++ Function (which is slightly faster) to do exactly the same as this
function. However, if one wants to modify the default flags, this function
can be used to obtain the default flag stencil, which can then be modified
at will. The correct way to do this is:
@example
-\\override Stem #'flag = #default-flag
-\\override Stem #'flag-style = #'mensural
+\\override Flag #'stencil = #default-flag
+\\override Flag #'style = #'mensural
@end example
"
- (let* ((flag-style-symbol (ly:grob-property stem-grob 'flag-style))
+ (let* ((stem-grob (ly:grob-parent grob X))
+ (flag-style-symbol (ly:grob-property grob 'style))
(flag-style (if (symbol? flag-style-symbol)
(symbol->string flag-style-symbol)
"")))
(cond
- ((equal? flag-style "") (normal-flag stem-grob))
- ((equal? flag-style "mensural") (mensural-flag stem-grob))
- ((equal? flag-style "no-flag") (no-flag stem-grob))
- (else ((glyph-flag flag-style) stem-grob)))))
+ ((equal? flag-style "") (normal-flag grob))
+ ((equal? flag-style "mensural") (mensural-flag grob))
+ ((equal? flag-style "no-flag") (no-flag grob))
+ (else ((glyph-flag flag-style) grob)))))
(make-property-set 'graceSettings
;; TODO: take this from voicedGraceSettings or similar.
'((Voice Stem font-size -3)
+ (Voice Flag font-size -3)
(Voice NoteHead font-size -3)
(Voice TabNoteHead font-size -4)
(Voice Dots font-size -3)
(ly:duration-log
(ly:event-property (event-cause grob) 'duration)))
+(define-public (stem::length val)
+ (lambda (grob)
+ (let* ((d (ly:grob-property grob 'direction))
+ (ss (ly:staff-symbol-staff-space grob))
+ (beg (ly:stem::calc-stem-begin-position grob))
+ (y1 (* beg (* 0.5 ss)))
+ (y2 (* ((if (eqv? d DOWN) - +) beg val) (* 0.5 ss))))
+ (if (eqv? d DOWN)
+ (cons y2 y1)
+ (cons y1 y2)))))
+
(define-public (note-head::calc-duration-log grob)
(min 2
(ly:duration-log