The Bug Meister is omitted from the daily schedule.
@example
-Sunday: Valentin
+Sunday: Colin
Monday: Dmytro
Tuesday: James Bailey
Wednesday: Ralph
@end example
@item
-If the issue requires multi-page output, then generate a
-@file{bug.pdf} file with the normal:
+If the issue requires one or two pages of output, then generate a
+@file{bug.png} file with the normal:
@example
lilypond --png bug.ly
@end example
+@item
+If the issue cannot be shown with less than three pages, then
+generate a @file{bug.pdf} file with:
+
+@example
+lilypond --pdf bug.ly
+@end example
+
+Note that this is likely to be extremely rare; most bugs should fit
+into the first two categories above.
+
+
@end itemize
@item
output data. Delete everything from the beginning of the file
up to but not including the first occurrence of @code{digraph}.
+Also, delete the final liypond message about successs from the end
+of the file.
+
@item Process the logfile with @code{dot}
The directed graph is created from the log file with the program
@details{Aprendizaje}
@item
-@ifWebLinks{@manualStableGlossarySplitNoName-es,@rglosnamed{Top,Glosario}}
+@ifWebLinks{@manualStableGlossarySplitNoName,@rglosnamed{Top,Glosario}}
@emph{(lectura opcional)} términos musicales y traducciones.
@details{Glosario}
@details{Utilización}
@item
-@ifWebLinks{@manualStableSnippetsSplitNoName-es,@rlsrnamed{Top,Fragmentos}}
+@ifWebLinks{@manualStableSnippetsSplitNoName,@rlsrnamed{Top,Fragmentos}}
trucos y consejos cortos.
@details{Fragmentos}
@details{Extender}
@item
-@ifWebLinks{@manualStableInternalsSplitNoName-es,@rinternalsnamed{Top,Funcionamiento interno}}
+@ifWebLinks{@manualStableInternalsSplitNoName,@rinternalsnamed{Top,Funcionamiento interno}}
referencia sobre el trucaje.
@details{Funcionamiento interno}
@c used for news about the upcoming release; see CG 10.2
+@newsItem
+@subsubheading ¡Lanzado LilyPond 2.13.40! @emph{21 de noviembre de 2010}
+
+Nos complace anunciar el lanzamiento de LilyPond 2.13.40. Esta
+versión contiene el conjunto habitual de correcciones de fallos. Sin
+embargo, aún quedan algunos problemas críticos, por lo que esta
+versión está orientada solamente a los desarrolladores.
+
+Tenga en cuenta que ésta @strong{no} es la segunda versión de pruebas
+beta. A causa de la aparición de algunos cambios en nuestro proceso
+de construcción del programa que no se han probado, no podemos estar
+completamente seguros de la calidad de esta versión.
+
+@newsEnd
+
+
@newsItem
@subsubheading Primera versión de pruebas Beta de 2.14: ¡Lanzado LilyPond 2.13.39! @emph{15 de noviembre de 2010}
Learning Manual:
@rlearning{Contexts and engravers}.
-Installed files:
+Installed Files:
@file{ly/engraver-init.ly},
@file{ly/performer-init.ly}.
The automatic beaming settings for a time signature can be changed
as described in @ref{Time signature}.
+Most automatic beaming settings for a time signature contain an
+entry for @code{beamExceptions}. For example, 4/4 time tries to
+beam the measure in two if there are only eighth notes. The
+@code{beamExceptions} rule can override the @code{beatStructure} setting
+if @code{beamExceptions} is not reset.
+
+@lilypond[quote,verbatim,relative=2]
+\time 4/4
+\set Timing.baseMoment = #(ly:make-moment 1 8)
+\set Timing.beatStructure = #'(3 3 2)
+% This won't beam (3 3 2) because of beamExceptions
+\repeat unfold 8 {c8} |
+% This will beam (3 3 2) because we clear beamExceptions
+\set Timing.beamExceptions = #'()
+\repeat unfold 8 {c8}
+@end lilypond
+
+In a similar fashion, eighth notes in 3/4 time are beamed as a full
+measure by default. To beam eighth notes in 3/4 time on the beat,
+reset @code{beamExceptions}.
+
+@lilypond[quote,verbatim,relative=2]
+\time 3/4
+% by default we beam in (3) due to beamExceptions
+\repeat unfold 6 {a8} |
+% This will beam (1 1 1) due to beatLength
+\set Timing.beamExceptions = #'()
+\repeat unfold 6 {a8}
+@end lilypond
+
@i{@strong{How automatic beaming works}}
When automatic beaming is enabled, the placement of automatic beams
@seealso
-Installed files:
+Installed Files:
@file{scm/beam-settings.scm}.
Snippets:
@end example
The available unit suffixes are @code{\mm}, @code{\cm},
-@code{\in}, and @code{\pt}. For the sake of clarity, when using
-millimeters, the @code{\mm} is typically included in the code,
-even though it is not technically necessary.
+@code{\in}, and @code{\pt}. These units are simple values for
+converting from millimeters; they are defined in
+@file{ly/paper-defaults-init.ly}. For the sake of clarity, when
+using millimeters, the @code{\mm} is typically included in the
+code, even though it is not technically necessary.
It is also possible to define @code{\paper} values using Scheme.
The Scheme equivalent of the above example is:
@seealso
Notation Reference:
-@ref{Custom headers footers and titles}.
+@ref{Paper size and automatic scaling},
+@ref{Custom headers footers and titles},
+@ref{The \layout block}.
+
+Installed Files:
+@file{ly/paper-defaults-init.ly}.
@node Paper size and automatic scaling
@end example
@seealso
+Notation Reference:
+@ref{Automatic scaling to paper size}.
+
Installed Files:
@file{scm/paper.scm}.
values of several @code{\paper} variables are automatically scaled
to the new size. To bypass the automatic scaling for a particular
variable, set the variable after setting the paper size. Note
-that the automatic scaling is not triggered by setting
-@code{paper-height} or @code{paper-width}, even though
+that the automatic scaling is not triggered by setting the
+@code{paper-height} or @code{paper-width} variables, even though
@code{paper-width} can influence other values (this is separate
from scaling and is discussed below). The
@code{set-default-paper-size} and @code{set-paper-size} functions
are described in @ref{Setting paper size}.
The vertical dimensions affected by automatic scaling are
-@code{top-margin} and @code{bottom-margin}. The horizontal
+@code{top-margin} and @code{bottom-margin} (see
+@ref{Fixed vertical spacing \paper variables}. The horizontal
dimensions affected by automatic scaling are @code{left-margin},
@code{right-margin}, @code{inner-margin}, @code{outer-margin},
-@code{binding-offset}, @code{indent}, and @code{short-indent}.
+@code{binding-offset}, @code{indent}, and @code{short-indent} (see
+@ref{Horizontal spacing \paper variables}.
The default values for these dimensions are set in
@file{ly/paper-defaults-init.ly}, using internal variables named
@code{210\mm}.
@seealso
+Notation Reference:
+@ref{Fixed vertical spacing \paper variables},
+@ref{Horizontal spacing \paper variables}.
+
Installed Files:
@file{ly/paper-defaults-init.ly},
@file{scm/paper.scm}.
@end table
@seealso
+Notation Reference:
+@ref{Automatic scaling to paper size}.
+
Installed Files:
@file{ly/paper-defaults-init.ly}.
when unset. If @code{line-width} is set, and both
@code{left-margin} and @code{right-margin} are unset, then the
margins will be updated to center the systems on the page
-automatically. Also see @code{check-consistency}.
+automatically. Also see @code{check-consistency}. This variable
+can also be set in a @code{\layout} block.
@item left-margin
@funindex left-margin
@end table
@seealso
+Notation Reference:
+@ref{Automatic scaling to paper size}.
+
Installed Files:
@file{ly/paper-defaults-init.ly}.
@end table
@seealso
+Notation Reference:
+@ref{Automatic scaling to paper size}.
+
Installed Files:
@file{ly/paper-defaults-init.ly}.
@end table
@seealso
+Notation Reference:
+@ref{Automatic scaling to paper size}.
+
Installed Files:
@file{ly/paper-defaults-init.ly}.
@ref{Optimal page turning},
@ref{Minimal page breaking}.
-Installed files:
+Installed Files:
@file{ly/paper-defaults-init.ly}.
@seealso
-Installed files:
+Installed Files:
@file{ly/titling-init.ly}.
Snippets:
variables that can appear in a @code{\layout} block are:
@itemize
-@item @code{ragged-right}
-@item @code{ragged-last}
-@item @code{indent}
-@item @code{short-indent}
-@item @code{system-count}
+
+@item
+@code{line-width}, @code{ragged-right} and @code{ragged-last}
+(see @ref{\paper variables for widths and margins})
+
+@item
+@code{indent} and @code{short-indent}
+(see @ref{\paper variables for shifts and indents})
+
+@item
+@code{system-count}
+(see @ref{\paper variables for line breaking})
+
@end itemize
Here is an example @code{\layout} block:
@example
\layout @{
- indent = 2.0\cm
+ indent = 2\cm
\context @{
\StaffGroup
\override StaffGrouper #'staff-staff-spacing #space = #8
@}
\context @{
\Voice
- \override TextScript #'padding = #1.0
+ \override TextScript #'padding = #1
\override Glissando #'thickness = #3
@}
@}
To set the staff size individually for each score, use
@example
\score@{
- ...
- \layout@{
- #(layout-set-staff-size 15)
+ @dots{}
+ \layout @{
+ #(layout-set-staff-size 15)
@}
@}
@end example
Line breaks are normally determined automatically. They are chosen
so that lines look neither cramped nor loose, and consecutive
-lines have similar density. Occasionally you might want to
-override the automatic breaks; you can do this by specifying
-@code{\break}. This will force a line break at this point. However,
-line breaks can only occur at the end of @q{complete} bars, i.e.,
-where there are no notes or tuplets left @q{hanging} over the bar
-line. If you want to have a line break where there is no bar line,
-you can force an invisible bar line by entering @code{\bar ""},
-although again there must be no notes left hanging over in any of
-the staves at this point, or it will be ignored.
-
-The opposite command, @code{\noBreak}, forbids a line break at the
-bar line where it is inserted.
+lines have similar density.
+
+To manually force a line break at a bar line, use the
+@code{\break} command:
+
+@lilypond[quote,ragged-right,relative=2,verbatim]
+c4 c c c | \break
+c4 c c c |
+@end lilypond
+
+By default, a @code{\break} in the middle of a measure is ignored,
+and a warning is printed. To force a line break in the middle of
+a measure, add an invisible bar line with @w{@samp{\bar ""}}:
+
+@lilypond[quote,ragged-right,relative=2,verbatim]
+c4 c c
+\bar "" \break
+c |
+c4 c c c |
+@end lilypond
+
+A @code{\break} occuring at a bar line is also ignored if the
+previous measure ends in the middle of a note, such as when a
+tuplet begins and ends in different measures. To allow
+@code{\break} commands to work in these situations, remove the
+@code{Forbid_line_break_engraver} from the @code{Voice} context.
+Note that manually forced line breaks have to be added in parallel
+with the music:
+
+@lilypond[quote,ragged-right,verbatim]
+\new Voice \with {
+ \remove Forbid_line_break_engraver
+} \relative c'' {
+ <<
+ { c2. \times 2/3 { c4 c c } c2. | }
+ { s1 | \break s1 | }
+ >>
+}
+@end lilypond
+
+Similarly, line breaks are normally forbidden when beams cross bar
+lines. This behavior can be changed by setting
+@code{\override Beam #'breakable = ##t}:
+
+@lilypond[quote,ragged-right,relative=2,verbatim]
+\override Beam #'breakable = ##t
+c2. c8[ c | \break
+c8 c] c2. |
+@end lilypond
+
+The @code{\noBreak} command forbids a line break at the bar line
+where it is inserted.
The most basic settings influencing line spacing are @code{indent}
and @code{line-width}. They are set in the @code{\layout} block.
@example
\layout @{
-indent = #0
-line-width = #150
-ragged-last = ##t
+ indent = 0\mm
+ line-width = 150\mm
+ ragged-last = ##t
@}
@end example
every 4 measures, and only there:
@example
-<< \repeat unfold 7 @{
- s1 \noBreak s1 \noBreak
- s1 \noBreak s1 \break @}
- @emph{the real music}
+<<
+ \repeat unfold 7 @{
+ s1 \noBreak s1 \noBreak
+ s1 \noBreak s1 \break
+ @}
+ @{ @var{the actual music@dots{}} @}
>>
@end example
@seealso
+Notation Reference:
+@ref{\paper variables for line breaking}.
+
Snippets:
@rlsr{Spacing}.
@rinternals{LineBreakEvent}.
-@knownissues
-
-Line breaks can only occur if there is a @q{proper} bar line. A note
-which is hanging over a bar line is not proper, such as
-
-@lilypond[quote,ragged-right,relative=2,verbatim]
-c4 c2 << c2 {s4 \break } >> % this does nothing
-c2 c4 | % a break here would work
-c4 c2 c4 ~ \break % as does this break
-c4 c2 c4
-@end lilypond
-
-This can be avoided by removing the @code{Forbid_line_break_engraver}.
-Note that manually forced line breaks have to be added in parallel
-with the music.
-
-@lilypond[quote,ragged-right,verbatim]
-\new Voice \with {
- \remove Forbid_line_break_engraver
-} {
- c4 c2 << c2 {s4 \break } >> % now the break is allowed
- c2 c4
-}
-@end lilypond
-
-Similarly, line breaks are normally forbidden when beams cross bar
-lines. This behavior can be changed by setting
-@code{\override Beam #'breakable = ##t}.
-
-
@node Page breaking
@subsection Page breaking
@code{ragged-last} which have the same effect on vertical spacing:
@code{ragged-bottom} and @code{ragged-last-bottom}. If set to
@code{##t} the systems on all pages or just the last page
-respectively will not be justified vertically.
-
-For more details see @ref{Vertical spacing}.
+respectively will not be justified vertically. See
+@ref{Fixed vertical spacing \paper variables}.
Page breaks are computed by the @code{page-breaking} function. LilyPond
provides three algorithms for computing page breaks,
but the value can be changed in the @code{\paper} block:
@example
-\paper@{
- #(define page-breaking ly:page-turn-breaking)
+\paper @{
+ page-breaking = #ly:page-turn-breaking
@}
@end example
\paper @{
%% In a part consisting mostly of text,
%% ly:minimal-breaking may be preferred
- #(define page-breaking ly:minimal-breaking)
+ page-breaking = #ly:minimal-breaking
@}
\markup @{ @dots{} @}
@dots{}
@seealso
+Notation Reference:
+@ref{\paper variables for page breaking}.
+
Snippets:
@rlsr{Spacing}.
@example
\paper @{
- #(define page-breaking ly:minimal-breaking)
+ page-breaking = #ly:minimal-breaking
@}
@end example
ragged-bottom = ##t
}
+music = \relative c'' { c8 c c c }
+
\score {
\new Staff {
- \repeat unfold 2 { c'8 c'8 c'8 c'8 } \break
- \repeat unfold 4 { c'8 c'8 c'8 c'8 } \break
- \repeat unfold 6 { c'8 c'8 c'8 c'8 } \break
- \repeat unfold 8 { c'8 c'8 c'8 c'8 } \pageBreak
- \repeat unfold 8 { c'8 c'8 c'8 c'8 } \break
- \repeat unfold 6 { c'8 c'8 c'8 c'8 } \break
- \repeat unfold 4 { c'8 c'8 c'8 c'8 } \break
- \repeat unfold 2 { c'8 c'8 c'8 c'8 }
- }
+ \repeat unfold 2 { \music } \break
+ \repeat unfold 4 { \music } \break
+ \repeat unfold 6 { \music } \break
+ \repeat unfold 8 { \music } \pageBreak
+ \repeat unfold 8 { \music } \break
+ \repeat unfold 6 { \music } \break
+ \repeat unfold 4 { \music } \break
+ \repeat unfold 2 { \music }
+ }
\layout {
\context {
\Score
Line- and page-breaking information usually appears within note entry directly.
@example
+music = \relative c'' @{ c4 c c c @}
+
\score @{
\new Staff @{
- \repeat unfold 2 @{ c'4 c'4 c'4 c'4 @}
- \break
- \repeat unfold 3 @{ c'4 c'4 c'4 c'4 @}
+ \repeat unfold 2 @{ \music @} \break
+ \repeat unfold 3 @{ \music @}
@}
@}
@end example
breaking layout information.
@lilypond[quote,verbatim]
+music = \relative c'' { c4 c c c }
+
\score {
\new Staff <<
\new Voice {
s1 * 5 \break
}
\new Voice {
- \repeat unfold 2 { c'4 c'4 c'4 c'4 }
- \repeat unfold 3 { c'4 c'4 c'4 c'4 }
- \repeat unfold 6 { c'4 c'4 c'4 c'4 }
- \repeat unfold 5 { c'4 c'4 c'4 c'4 }
+ \repeat unfold 2 { \music }
+ \repeat unfold 3 { \music }
+ \repeat unfold 6 { \music }
+ \repeat unfold 5 { \music }
}
>>
}
@code{NonMusicalPaperColumnGrob}, as explained in @ref{Vertical spacing}.
@lilypond[quote,verbatim]
+music = \relative c'' { c4 c c c }
+
\score {
\new Staff <<
\new Voice {
s1 * 5 \break
}
\new Voice {
- \repeat unfold 2 { c'4 c'4 c'4 c'4 }
- \repeat unfold 3 { c'4 c'4 c'4 c'4 }
- \repeat unfold 6 { c'4 c'4 c'4 c'4 }
- \repeat unfold 5 { c'4 c'4 c'4 c'4 }
+ \repeat unfold 2 { \music }
+ \repeat unfold 3 { \music }
+ \repeat unfold 6 { \music }
+ \repeat unfold 5 { \music }
}
>>
}
@end table
@seealso
-Installed files:
+Installed Files:
@file{ly/engraver-init.ly},
@file{scm/define-grobs.scm}.
@node Explicit staff and system positioning
@subsection Explicit staff and system positioning
-One way to understand the @code{VerticalAxisGroup} and @code{\paper}
-settings explained in the previous two sections is as a collection of
-different settings that primarily concern the amount of vertical padding
-different staves and systems running down the page.
+One way to understand the flexible vertical spacing mechanisms
+explained above is as a collection of settings that control the
+amount of vertical padding between staves and systems.
-It is possible to approach vertical spacing in a different way using
-@code{NonMusicalPaperColumn #'line-break-system-details}. Where
-@code{VerticalAxisGroup} and @code{\paper} settings specify vertical padding,
-@code{NonMusicalPaperColumn #'line-break-system-details} specifies exact
-vertical positions on the page.
+It is possible to approach vertical spacing in a different way
+using @code{NonMusicalPaperColumn #'line-break-system-details}.
+While the flexible vertical spacing mechanisms specify vertical
+padding, @code{NonMusicalPaperColumn #'line-break-system-details}
+can specify exact vertical positions on the page.
-@code{NonMusicalPaperColumn #'line-break-system-details} accepts an associative
-list of three different settings:
+@code{NonMusicalPaperColumn #'line-break-system-details} accepts
+an associative list of three different settings:
@itemize
@item @code{X-offset}
#'line-break-system-details #'((Y-offset . 40))
\overrideProperty NonMusicalPaperColumn
- #'line-break-system-details #'((X-offset . 20) (Y-offset . 40))
+ #'line-break-system-details #'((X-offset . 20)
+ (Y-offset . 40))
\overrideProperty NonMusicalPaperColumn
#'line-break-system-details #'((alignment-distances . (15)))
\overrideProperty NonMusicalPaperColumn
- #'line-break-system-details #'((X-offset . 20) (Y-offset . 40)
+ #'line-break-system-details #'((X-offset . 20)
+ (Y-offset . 40)
(alignment-distances . (15)))
@end example
@c \book { } is required in these examples to ensure the spacing
@c overrides can be seen between systems. -np
-@lilypond[quote]
+@lilypond[verbatim,quote,staffsize=16]
\header { tagline = ##f }
\paper { left-margin = 0\mm }
\book {
the @code{Y-offset} pair in the @code{line-break-system-details}
attribute of the @code{NonMusicalPaperColumn} grob:
-@lilypond[quote]
+@lilypond[verbatim,quote,staffsize=16]
\header { tagline = ##f }
\paper { left-margin = 0\mm }
\book {
within each system manually. We do this using the @code{alignment-distances}
subproperty of @code{line-break-system-details}.
-@lilypond[quote]
+@lilypond[verbatim,quote,staffsize=16]
\header { tagline = ##f }
\paper { left-margin = 0\mm }
\book {
every system and every staff. Finally, note that @code{alignment-distances}
specifies the vertical positioning of staves but not of staff groups.
-@lilypond[quote]
+@lilypond[verbatim,quote,staffsize=16]
\header { tagline = ##f }
\paper { left-margin = 0\mm }
\book {
Snippets:
@rlsr{Text}.
-Installed files:
+Installed Files:
@file{scm/markup.scm}.
Internals Reference:
@rinternals{TextScript}.
-Installed files:
+Installed Files:
@file{scm/define-markup-commands.scm}.
Internals Reference:
@rinternals{TextScript}.
-Installed files:
+Installed Files:
@file{scm/define-markup-commands.scm}.
Internals Reference:
@rinternals{TextScript}.
-Installed files:
+Installed Files:
@file{scm/define-markup-commands.scm},
@file{scm/stencil.scm}.
Internals Reference:
@rinternals{TextScript}.
-Installed files:
+Installed Files:
@file{scm/define-markup-commands.scm},
@file{scm/fret-diagrams.scm},
@file{scm/harp-pedals.scm}.
Internals Reference:
@rinternals{TextScript}.
-Installed files:
+Installed Files:
@file{scm/define-markup-commands.scm}.
@rlsr{Text}.
@c A source file gets never installed...
-@c Installed files:
+@c Installed Files:
@c @file{lily/font-config-scheme.cc}.
@c used for news about the upcoming release; see CG 10.2
+@newsItem
+@subsubheading LilyPond 2.13.41 released! @emph{Dec 4, 2010}
+
+We are happy to announce the release of LilyPond 2.13.41. This
+release contains the usual number of bugfixes. However, a number
+of critical issues still remain, so this release is intended for
+developers only.
+
+Please note that this is @strong{not} the second beta test. Due
+to a number of untested changes to our build process, we cannot be
+at all confident about the quality of this release.
+
+@newsEnd
+
+
@newsItem
@subsubheading LilyPond 2.13.40 released! @emph{Nov 21, 2010}
PACKAGE_NAME=LilyPond
MAJOR_VERSION=2
MINOR_VERSION=13
-PATCH_LEVEL=41
+PATCH_LEVEL=42
MY_PATCH_LEVEL=
VERSION_STABLE=2.12.3
-VERSION_DEVEL=2.13.40
+VERSION_DEVEL=2.13.41
;; Use Command on Region even for inactive mark (region).
(if (string-match "XEmacs\\|Lucid" emacs-version)
- (setq zmacs-regions nil)
+ (progn
+ (setq zmacs-regions nil)
+ (make-local-hook 'post-command-hook)) ; XEmacs requires
(setq mark-even-if-inactive t))
;; Context dependent syntax tables in LilyPond-mode
- (make-local-hook 'post-command-hook) ; XEmacs requires
(add-hook 'post-command-hook 'LilyPond-mode-context-set-syntax-table nil t)
;; Turn on paren-mode buffer-locally, i.e., in LilyPond-mode
--- /dev/null
+\version "2.13.42"
+
+
+\header {
+ texidoc = "
+A @code{\bookpart} variable can be inserted in a @code{\book}.
+No segfault should occur in this case.
+"
+}
+
+mypart = \bookpart {
+ \relative c' {
+ c1
+ }
+}
+
+\book {
+ \mypart
+}
-\version "2.13.1"
+\version "2.13.42"
#(set-default-paper-size "a6")
\header {
- texidoc = "The min-systems-per-page variable takes precedence over
-the desire not to overfill a page."
+ texidoc = "
+The min-systems-per-page variable takes precedence over
+the desire not to overfill a page. In this case, systems will
+overlap because they are forced to be on the page.
+"
}
\book {
}
\repeat unfold 21 { c'1 }
-}
\ No newline at end of file
+}
--- /dev/null
+\version "2.13.41"
+
+\header {
+ texidoc = "
+Layouts that overflow a page will be compressed in order to fit on
+the page, even if it causes collisions. In this example, the
+tagline should not collide with the bottom staff.
+"
+}
+
+\paper {
+ paper-height= 8\cm
+}
+
+\book {
+ \repeat unfold 3 { g'''1\mark \markup "Long Text" g'''1\break}
+}
"
}
+#(define (assert-single-page layout props arg)
+ (if (and (= (chain-assoc-get 'page:page-number props -1)
+ (ly:output-def-lookup layout 'first-page-number))
+ (chain-assoc-get 'page:last? props -1))
+ (interpret-markup layout props arg)
+ (ly:error "failed to fit test on single page")))
+
\paper {
#(set-paper-size "a6")
tagline = ##f
- system-system-spacing #'padding = #1.20
+ system-system-spacing = #'((padding . 1.2))
+ oddHeaderMarkup = \markup \on-the-fly #assert-single-page \null
}
-\new Voice {
- \voiceTwo
- \override Staff.Stem #'length = #0
- \repeat unfold 144 a
+\book {
+ \score {
+ \new Voice {
+ \voiceTwo
+ \override Stem #'length = #0
+ \repeat unfold 144 a4
+ }
+ \layout {
+ \context {
+ \Score
+ \remove "Bar_number_engraver"
+ }
+ }
+ }
}
c4. d-_( |
e\varcoda-> )
\override TextSpanner #'(bound-details left text) = "rit." f\startTextSpan |
- g ~ a\prall |
+ g ~ g\prall |
g\thumb e-.\stopTextSpan
\bar "|."
}
--- /dev/null
+\version "2.13.42"
+
+\header {
+ texidoc = "
+Harmonics can be specified either by ratio or by fret number.
+"
+}
+
+test = {
+ e,4
+ \harmonicByRatio #1/2 e,\6
+ \harmonicByRatio #1/3 a,\5
+ \harmonicByRatio #2/3 d,\4 |
+ \harmonicByRatio #1/4 { g8\3 b\2 e'\1 b\2 < g b e >2 } |
+ e,1 | % check whether tab note head is restored
+ \harmonicByFret #12 e'4\1 ~
+ \harmonicByFret #12 e'4\1 (
+ \ottava #1
+ \harmonicByFret #7 e'4\1)
+ \harmonicByFret #5 e'8\1
+ \ottava #2
+ \harmonicByFret #4 < b\2 e'\1 >8 |
+ \harmonicByFret #3 < g\3 b\2 e'\1 >4
+ \harmonicByFret #2.7 < g\3 b\2 e'\1 >4
+ \harmonicByFret #2.3 < g\3 b\2 e'\1 >4
+ \harmonicByFret #2 < g\3 b\2 e'\1 >4 |
+ \ottava #0
+ e,1 | % check whether tab note head is restored
+}
+
+\paper {
+ ragged-right = ##f
+}
+
+\score {
+ <<
+ \new Staff {
+ \new Voice {
+ \clef "treble_8"
+ \override Voice.StringNumber #'transparent = ##t
+ \test
+ }
+ }
+ \new TabStaff {
+ \new TabVoice {
+ \test
+ }
+ }
+ >>
+}
--- /dev/null
+\version "2.13.42"
+
+\header {
+ texidoc = "
+If a slur or a glissando follows a tie, the
+corresponding fret number is displayed in parentheses.
+"
+}
+
+music = {
+ c'4 ~ c'4 ( d'2 ) |
+ c'4 ~ c'4 \glissando d'2 |
+ c'4 ~ c'4 d'2 |
+ c'4 \glissando d'2. |
+}
+
+\score {
+ <<
+ \new Staff {
+ \new Voice {
+ \clef "G_8"
+ \music
+ }
+ }
+ \new TabStaff {
+ \new TabVoice {
+ \music
+ }
+ }
+ >>
+}
void
pop_paper (Lily_parser *parser)
{
- if (! scm_is_null (parser->lexer_->lookup_identifier ("$papers")))
+ if (scm_is_pair (parser->lexer_->lookup_identifier ("$papers")))
parser->lexer_->set_identifier (ly_symbol2scm ("$papers"),
scm_cdr (parser->lexer_->lookup_identifier ("$papers")));
}
solution_ = spacer.spring_positions ();
if (!spacer.fits ())
- warning (_f ("couldn't fit music on page: overflow is %f",
- spacer.configuration_length(spacer.force()) - page_height_));
+ {
+ Real overflow = spacer.configuration_length (spacer.force ())
+ - page_height_;
+ warning (_f ("couldn't fit music on page: overflow is %f",
+ overflow));
+ warning (_ ("compressing music to fit"));
+ vsize space_count = solution_.size ();
+ Real spacing_increment = overflow / (space_count - 2);
+ for (vsize i = 2; i < space_count; i++)
+ solution_[i] -= (i-1) * spacing_increment;
+ }
}
// The solution_ vector stores the position of every live VerticalAxisGroup
+++ /dev/null
-/*
- This file is part of LilyPond, the GNU music typesetter.
-
- Copyright (C) 2005--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
-
-
- 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 "engraver.hh"
-
-#include "item.hh"
-#include "pointer-group-interface.hh"
-#include "simple-closure.hh"
-#include "stream-event.hh"
-#include "warn.hh"
-
-#include "translator.icc"
-
-class Tab_harmonic_engraver : public Engraver
-{
- TRANSLATOR_DECLARATIONS (Tab_harmonic_engraver);
-
-protected:
- DECLARE_ACKNOWLEDGER (note_head);
-};
-
-Tab_harmonic_engraver::Tab_harmonic_engraver ()
-{
-}
-
-void
-Tab_harmonic_engraver::acknowledge_note_head (Grob_info info)
-{
- if (Stream_event *note = info.event_cause ())
- {
- for (SCM s = note->get_property ("articulations");
- scm_is_pair (s); s = scm_cdr (s))
- {
- Stream_event *ev = unsmob_stream_event (scm_car (s));
-
- if (!ev)
- continue;
-
-
- if (ev->in_event_class ("harmonic-event"))
- {
- if (Item *victim = info.item ())
- {
- Engraver *eng = dynamic_cast<Engraver*> (info.origin_translator ());
- Item *paren = eng->make_item ("HarmonicParenthesesItem", victim->self_scm ());
- Pointer_group_interface::add_grob (paren, ly_symbol2scm ("elements"), victim);
-
- paren->set_parent (victim, Y_AXIS);
-
- Real size = robust_scm2double (paren->get_property ("font-size"), 0.0)
- + robust_scm2double (victim->get_property ("font-size"), 0.0);
- paren->set_property ("font-size", scm_from_double (size));
- }
- }
- }
- }
-}
-
-ADD_ACKNOWLEDGER (Tab_harmonic_engraver, note_head);
-ADD_TRANSLATOR (Tab_harmonic_engraver,
- /* doc */
- "In a tablature, parenthesize objects whose music cause has"
- " the @code{parenthesize} property.",
-
- /* create */
- "HarmonicParenthesesItem ",
-
- /* read */
- "",
-
- /* write */
- ""
- );
--- /dev/null
+/*
+ This file is part of LilyPond, the GNU music typesetter.
+
+ Copyright (C) 2010 Carl D. Sorensen
+
+ 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 <cctype>
+#include <cstdio>
+
+#include "engraver.hh"
+
+using namespace std;
+
+#include "context.hh"
+#include "item.hh"
+#include "spanner.hh"
+
+#include "translator.icc"
+
+/*
+ Change tab-note-head properties when a tie is followed by a
+ slurs or glissando.
+*/
+class Tab_tie_follow_engraver : public Engraver
+{
+ vector<Spanner *> slurs_;
+ vector<Spanner *> glissandi_;
+ vector<Item *> note_heads_;
+
+public:
+ TRANSLATOR_DECLARATIONS (Tab_tie_follow_engraver);
+
+protected:
+ DECLARE_ACKNOWLEDGER (glissando);
+ DECLARE_ACKNOWLEDGER (slur);
+ DECLARE_ACKNOWLEDGER (tab_note_head);
+
+ void stop_translation_timestep ();
+};
+
+Tab_tie_follow_engraver::Tab_tie_follow_engraver ()
+{
+}
+
+void
+Tab_tie_follow_engraver::acknowledge_glissando (Grob_info info)
+{
+ glissandi_.push_back (info.spanner ());
+}
+
+void
+Tab_tie_follow_engraver::acknowledge_tab_note_head (Grob_info info)
+{
+ note_heads_.push_back (info.item ());
+}
+
+void
+Tab_tie_follow_engraver::acknowledge_slur (Grob_info info)
+{
+ slurs_.push_back (info.spanner ());
+}
+
+void
+Tab_tie_follow_engraver::stop_translation_timestep ()
+{
+ for (vsize k = 0; k < note_heads_.size (); k++)
+ {
+ bool spanner_start = false;
+ for (vsize j = 0; j < slurs_.size (); j++)
+ {
+ Item* left_item = slurs_[j]->get_bound (LEFT);
+ if (left_item)
+ {
+ SCM left_cause = left_item->get_property ("cause");
+ Item *slur_cause = unsmob_item (left_cause);
+ if (slur_cause == note_heads_[k])
+ {
+ note_heads_[k]->set_property ("span-start", SCM_BOOL_T);
+ spanner_start = true;
+ break;
+ }
+ }
+ }
+ if (!spanner_start)
+ for (vsize j = 0; j < glissandi_.size (); j++)
+ {
+ Item *left_bound = glissandi_[j]->get_bound (LEFT);
+ if (left_bound == note_heads_[k])
+ {
+ note_heads_[k]->set_property ("span-start", SCM_BOOL_T);
+ break;
+ }
+ }
+ }
+ slurs_.clear ();
+ glissandi_.clear ();
+ note_heads_.clear();
+}
+
+ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, slur);
+ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, glissando);
+ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, tab_note_head);
+
+
+ADD_TRANSLATOR (Tab_tie_follow_engraver,
+ /* doc */
+ "Adjust TabNoteHead properties when a tie is followed"
+ " by a slur or glissando.",
+
+ /* create */
+ " ",
+
+ /* read */
+ " ",
+
+ /* write */
+ " "
+ );
#include "translator.icc"
/**
- Manufacture ties. Acknowledge noteheads, and put them into a
+ Manufacture ties. Acknowledge note heads, and put them into a
priority queue. If we have a TieEvent, connect the notes that finish
just at this time, and note that start at this time.
// Prevent all other tied notes ending at the same moment (assume
// implicitly the notes have also started at the same moment!)
- // from triggering an "unterminated tie" warning. Neede e.g. for
+ // from triggering an "unterminated tie" warning. Needed e.g. for
// <c e g>~ g
for (vsize j = heads_to_tie_.size (); j--;)
{
if (heads_to_tie_[j].end_moment_ == end)
- heads_to_tie_[i].tie_from_chord_created = true;
+ heads_to_tie_[j].tie_from_chord_created = true;
}
}
}
if (!left_ev)
{
- // may happen for ambituses
+ // may happen for ambitus
continue;
}
\name "TabVoice"
\alias "Voice"
\consists "Tab_note_heads_engraver"
- \consists "Tab_harmonic_engraver"
+ \consists "Tab_tie_follow_engraver"
\remove "Note_heads_engraver"
\remove "Fingering_engraver"
\override Hairpin #'transparent = ##t
\override Script #'stencil = ##f
\override TextScript #'stencil = ##f
+ \override Glissando #'stencil = #glissando::draw-tab-glissando
%% the direction for glissando lines will be automatically corrected
\override Glissando #'extra-dy = #glissando::calc-tab-extra-dy
\override Glissando #'bound-details #'right = #`((attach-dir . ,LEFT)
\override Clef #'stencil = #clef::print-modern-tab-if-set
%% no time signature
\override TimeSignature #'stencil = ##f
- %% better parentheses in a TabStaff
- \override ParenthesesItem #'stencils = #parentheses-item::calc-tabstaff-parenthesis-stencils
%% no arpeggios
\override Arpeggio #'stencil = ##f
%% we ignore collision warnings that may occur due to
#(def-grace-function startGraceMusic stopGraceMusic
(_i "Insert @var{music} as grace notes."))
-
+harmonicByFret = #(define-music-function (parser location fret music) (number? ly:music?)
+ (let* ((fret (number->string fret))
+ (pitch (fret->pitch fret)))
+ (make-sequential-music
+ (list
+ #{
+ \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label $fret)
+ #}
+ (make-harmonic
+ (calc-harmonic-pitch pitch music))
+ #{
+ \revert TabNoteHead #'stencil
+ #}))))
+
+harmonicByRatio = #(define-music-function (parser location ratio music) (number? ly:music?)
+ (let ((pitch (ratio->pitch ratio))
+ (fret (ratio->fret ratio)))
+ (make-sequential-music
+ (list
+ #{
+ \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label $fret)
+ #}
+ (make-harmonic
+ (calc-harmonic-pitch pitch music))
+ #{
+ \revert TabNoteHead #'stencil
+ #}))))
instrumentSwitch =
#(define-music-function
\revert TabVoice.MultiMeasureRestNumber #'transparent
\revert TabVoice.MultiMeasureRestText #'transparent
% markups etc.
+ \revert TabVoice.Glissando #'stencil
\revert TabVoice.Script #'stencil
\revert TabVoice.TextScript #'stencil
\revert TabVoice.TextSpanner #'stencil
'(align-dir fret-diagram-details size dot-placement-list
thickness))
+(ly:add-interface
+ 'glissando-interface
+ "A glissando."
+ '())
+
(ly:add-interface
'grace-spacing-interface
"Keep track of durations in a run of grace notes."
(ly:add-interface
'tab-note-head-interface
"A note head in tablature."
- '(details))
+ '(details display-cautionary span-start))
(ly:add-interface
'trill-spanner-interface
(direction-source ,ly:grob? "In case @code{side-relative-direction} is
set, which grob to get the direction from.")
+ (display-cautionary ,boolean? "Should the grob be displayed as a cautionary grob?")
(dot ,ly:grob? "A reference to a @code{Dots} object.")
(dots ,ly:grob-array? "Multiple @code{Dots} objects.")
(spacing ,ly:grob? "The spacing spanner governing this section.")
(spacing-wishes ,ly:grob-array? "An array of note spacing or staff spacing
objects.")
+ (span-start ,boolean? "Is the note head at the start of a spanner?")
(staff-grouper ,ly:grob? "The staff grouper we belong to.")
(staff-symbol ,ly:grob? "The staff symbol grob that we are in.")
(stem ,ly:grob? "A pointer to a @code{Stem} object.")
(Y-extent . #f)
(zigzag-width . 0.75)
(meta . ((class . Spanner)
- (interfaces . (line-interface
+ (interfaces . (glissando-interface
+ line-interface
line-spanner-interface
unbreakable-spanner-interface))))))
self-alignment-interface
spanner-interface))))))
- (HarmonicParenthesesItem
- . (
- (padding . 0)
- (stencil . ,parentheses-item::print)
- (stencils . ,parentheses-item::calc-angled-bracket-stencils)
- (meta . ((class . Item)
- (interfaces . (font-interface
- parentheses-interface))))))
-
(HorizontalBracket
. (
(bracket-flare . (0.5 . 0.5))
(details . ((tied-properties . ((break-visibility . ,begin-of-line-visible)
(parenthesize . #t)))
(repeat-tied-properties . ((note-head-visible . #t)
- (parenthesize . #t)))))
+ (parenthesize . #t)))
+ (harmonic-properties . ((angularity . 2)
+ (half-thickness . 0.075)
+ (padding . 0)
+ (procedure . ,parenthesize-stencil)
+ (width . 0.25)))
+ (cautionary-properties . ((angularity . 0.4)
+ (half-thickness . 0.075)
+ (padding . 0)
+ (procedure . ,parenthesize-stencil)
+ (width . 0.25)))))
+
(direction . ,CENTER)
(duration-log . ,note-head::calc-duration-log)
(font-series . bold)
(font-size . -2)
(stem-attachment . (0.0 . 1.35))
- (stencil . ,ly:text-interface::print)
+ (stencil . ,tab-note-head::print)
(whiteout . #t)
(X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
(Y-offset . ,ly:staff-symbol-referencer::callback)
"flag-styles.scm"
"fret-diagrams.scm"
+ "tablature.scm"
"harp-pedals.scm"
"define-woodwind-diagrams.scm"
"display-woodwind-diagrams.scm"
"paper.scm"
"backend-library.scm"
"x11-color.scm"
- "tablature.scm"
;; must be after everything has been defined
"safe-lily.scm"))
(if (and (symbol? style)
(eq? style 'cross))
(stencil-whiteout (ly:note-head::print grob))
- (ly:text-interface::print grob))))
+ (tab-note-head::print grob))))
;; definitions for the "moderntab" clef:
;; the "moderntab" clef will be added to the list of known clefs,
-0.75
0.75)))
-;; for ties in tablature, fret numbers that are tied to should be invisible,
-;; except for 'tied to' numbers after a line break;; these will be
-;; parenthesized (thanks to Neil for his solution):
-(define-public (parenthesize-tab-note-head grob)
- ;; Helper function to parenthesize tab noteheads,
- ;; since we can't use ParenthesesItem at this stage
- ;; This is basically the same as the C++ function
- ;; in accidental.cc, converted to Scheme
- (let* ((font (ly:grob-default-font grob))
- (open (stencil-whiteout
- (ly:font-get-glyph font "accidentals.leftparen")))
- (close (stencil-whiteout
- (ly:font-get-glyph font "accidentals.rightparen")))
- (me (ly:text-interface::print grob)))
-
- (ly:stencil-combine-at-edge
- (ly:stencil-combine-at-edge me X LEFT open) X RIGHT close)))
-
-;; ParenthesesItem doesn't work very well for TabNoteHead, since
-;; the parentheses are too small and clash with the staff-lines
-;; Define a callback for the 'stencils property which will tweak
-;; the parentheses' appearance for TabNoteHead
-(define-public (parentheses-item::calc-tabstaff-parenthesis-stencils grob)
- ;; the grob we want to parenthesize
- (let ((victim (ly:grob-array-ref (ly:grob-object grob 'elements) 0)))
-
- ;; check whether it's a note head
- (if (grob::has-interface victim 'note-head-interface)
- (begin
- ;; tweak appearance before retrieving
- ;; list of stencils '(left-paren right-paren)
- ;; get the font-size from victim (=TabNoteHead) to handle
- ;; grace notes properly
- (ly:grob-set-property! grob 'font-size
- (ly:grob-property victim 'font-size))
- (ly:grob-set-property! grob 'padding 0)
- ;; apply whiteout to each element of the list
- (map stencil-whiteout
- (parentheses-item::calc-parenthesis-stencils grob)))
- (parentheses-item::calc-parenthesis-stencils grob))))
-
;; the handler for ties in tablature; according to TabNoteHead #'details,
;; the 'tied to' note is handled differently after a line break
(define-public (tie::handle-tab-note-head grob)
(let* ((original (ly:grob-original grob))
(tied-tab-note-head (ly:spanner-bound grob RIGHT))
+ (spanner-start (ly:grob-property tied-tab-note-head 'span-start #f))
(siblings (if (ly:grob? original)
(ly:spanner-broken-into original) '())))
- (if (and (>= (length siblings) 2)
- (eq? (car (last-pair siblings)) grob))
- ;; tie is split -> get TabNoteHead #'details
- (let* ((details (ly:grob-property tied-tab-note-head 'details))
- (tied-properties (assoc-get 'tied-properties details '()))
- (tab-note-head-parenthesized (assoc-get 'parenthesize tied-properties #t))
- ;; we need the begin-of-line entry in the 'break-visibility vector
- (tab-note-head-visible
- (vector-ref (assoc-get 'break-visibility
- tied-properties #(#f #f #t)) 2)))
-
- (if tab-note-head-visible
- ;; tab note head is visible
- (if tab-note-head-parenthesized
- (ly:grob-set-property! tied-tab-note-head 'stencil
- (lambda (grob)
- (parenthesize-tab-note-head grob))))
- ;; tab note head is invisible
- (begin
- (ly:grob-set-property! tied-tab-note-head 'transparent #t)
- (ly:grob-set-property! tied-tab-note-head 'whiteout #f))))
-
- ;; tie is not split -> make fret number invisible
+ (if spanner-start
+ ;; tab note head is right bound of a tie and left of spanner,
+ ;; -> parenthesize it at all events
(begin
- (ly:grob-set-property! tied-tab-note-head 'transparent #t)
- (ly:grob-set-property! tied-tab-note-head 'whiteout #f)))))
+ (ly:grob-set-property! tied-tab-note-head 'display-cautionary #t)
+ (ly:grob-set-property! tied-tab-note-head 'stencil tab-note-head::print))
+ ;; otherwise, check whether tie is split:
+ (if (and (>= (length siblings) 2)
+ (eq? (car (last-pair siblings)) grob))
+ ;; tie is split -> get TabNoteHead #'details
+ (let* ((details (ly:grob-property tied-tab-note-head 'details))
+ (tied-properties (assoc-get 'tied-properties details '()))
+ (tab-note-head-parenthesized (assoc-get 'parenthesize tied-properties #t))
+ ;; we need the begin-of-line entry in the 'break-visibility vector
+ (tab-note-head-visible
+ (vector-ref (assoc-get 'break-visibility
+ tied-properties #(#f #f #t)) 2)))
+
+ (if tab-note-head-visible
+ ;; tab note head is visible
+ (if tab-note-head-parenthesized
+ (begin
+ (ly:grob-set-property! tied-tab-note-head 'display-cautionary #t)
+ (ly:grob-set-property! tied-tab-note-head 'stencil tab-note-head::print)))
+ ;; tab note head is invisible
+ (ly:grob-set-property! tied-tab-note-head 'transparent #t)))
+
+ ;; tie is not split
+ (ly:grob-set-property! tied-tab-note-head 'transparent #t)))))
+
+
;; repeat ties occur within alternatives in a repeat construct;
;; TabNoteHead #'details handles the appearance in this case
(define-public (repeat-tie::handle-tab-note-head grob)
(let* ((tied-tab-note-head (ly:grob-object grob 'note-head))
- (details (ly:grob-property tied-tab-note-head 'details))
- (repeat-tied-properties (assoc-get 'repeat-tied-properties details '()))
- (tab-note-head-visible (assoc-get 'note-head-visible repeat-tied-properties #t))
- (tab-note-head-parenthesized (assoc-get 'parenthesize repeat-tied-properties #t)))
-
- (if tab-note-head-visible
- ;; tab note head is visible
- (if tab-note-head-parenthesized
- (ly:grob-set-property! tied-tab-note-head 'stencil
- (lambda (grob)
- (parenthesize-tab-note-head grob))))
- ;; tab note head is invisible
- (begin
- (ly:grob-set-property! tied-tab-note-head 'transparent #t)
- (ly:grob-set-property! tied-tab-note-head 'whiteout #f)))))
+ (spanner-start (ly:grob-property tied-tab-note-head 'span-start #f)))
+ (if spanner-start
+ ;; tab note head is between a tie and a slur/glissando
+ ;; -> parenthesize it at all events
+ (begin
+ (ly:grob-set-property! tied-tab-note-head 'display-cautionary #t)
+ (ly:grob-set-property! tied-tab-note-head 'stencil tab-note-head::print))
+ ;; otherwise check 'details
+ (let* ((details (ly:grob-property tied-tab-note-head 'details))
+ (repeat-tied-properties (assoc-get 'repeat-tied-properties details '()))
+ (tab-note-head-visible (assoc-get 'note-head-visible repeat-tied-properties #t))
+ (tab-note-head-parenthesized (assoc-get 'parenthesize repeat-tied-properties #t)))
+
+ (if tab-note-head-visible
+ ;; tab note head is visible
+ (if tab-note-head-parenthesized
+ (begin
+ (ly:grob-set-property! tied-tab-note-head 'display-cautionary #t)
+ (ly:grob-set-property! tied-tab-note-head 'stencil tab-note-head::print)))
+ ;; tab note head is invisible
+ (ly:grob-set-property! tied-tab-note-head 'transparent #t))))))
;; the slurs should not be too far apart from the corresponding fret number, so
-;; we move the slur towards the TabNoteHeads:
+;; we move the slur towards the TabNoteHeads; moreover, if the left fret number is
+;; the right-bound of a tie, we'll set it in parentheses:
(define-public (slur::draw-tab-slur grob)
;; TODO: use a less "brute-force" method to decrease
;; the distance between the slur ends and the fret numbers
- (let* ((staff-space (ly:staff-symbol-staff-space grob))
+ (let* ((original (ly:grob-original grob))
+ (left-bound (ly:spanner-bound original LEFT))
+ (left-tab-note-head (ly:grob-property left-bound 'cause))
+ (staff-space (ly:staff-symbol-staff-space grob))
(control-points (ly:grob-property grob 'control-points))
(new-control-points (map
- (lambda (p)
- (cons (car p)
- (- (cdr p)
- (* staff-space
- (ly:grob-property grob 'direction)
- 0.35))))
- control-points)))
+ (lambda (p)
+ (cons (car p)
+ (- (cdr p)
+ (* staff-space
+ (ly:grob-property grob 'direction)
+ 0.35))))
+ control-points)))
(ly:grob-set-property! grob 'control-points new-control-points)
(ly:slur::print grob)))
+;; The glissando routine works similarly to the slur routine; if the
+;; fret number is "tied to", it should become parenthesized.
+(define-public (glissando::draw-tab-glissando grob)
+ (let* ((original (ly:grob-original grob))
+ (left-tab-note-head (ly:spanner-bound original LEFT))
+ (cautionary (ly:grob-property left-tab-note-head 'display-cautionary #f)))
+
+ (and cautionary
+ ;; increase left padding to avoid collision between
+ ;; closing parenthesis and glissando line
+ (ly:grob-set-nested-property! grob '(bound-details left padding) 0.5))
+ (ly:line-spanner::print grob)))
+
;; for \tabFullNotation, the stem tremolo beams are too big in comparison to
;; normal staves; this wrapper function scales accordingly:
(define-public (stem-tremolo::calc-tab-width grob)
(let ((width (ly:stem-tremolo::calc-width grob))
- (staff-space (ly:staff-symbol-staff-space grob)))
+ (staff-space (ly:staff-symbol-staff-space grob)))
(/ width staff-space)))
;; a callback for custom fret labels
(define-public ((tab-note-head::print-custom-fret-label fret) grob)
- (grob-interpret-markup grob (markup #:vcenter fret)))
+ (ly:grob-set-property! grob 'text fret)
+ (tab-note-head::print grob))
+
+(define-public (tab-note-head::print grob)
+ (define (is-harmonic? grob)
+ (let ((arts (ly:event-property (event-cause grob) 'articulations)))
+ (not (null? (filter (lambda (a)
+ (ly:in-event-class? a 'harmonic-event))
+ arts)))))
+
+ (let* ((cautionary (ly:grob-property grob 'display-cautionary #f))
+ (details (ly:grob-property grob 'details '()))
+ (harmonic-props (assoc-get 'harmonic-properties details '()))
+ (harmonic-angularity (assoc-get 'angularity harmonic-props 2))
+ (harmonic-half-thick (assoc-get 'half-thickness harmonic-props 0.075))
+ (harmonic-padding (assoc-get 'padding harmonic-props 0))
+ (harmonic-proc (assoc-get 'procedure harmonic-props parenthesize-stencil))
+ (harmonic-width (assoc-get 'width harmonic-props 0.25))
+ (cautionary-props (assoc-get 'cautionary-properties details '()))
+ (cautionary-angularity (assoc-get 'angularity cautionary-props 2))
+ (cautionary-half-thick (assoc-get 'half-thickness cautionary-props 0.075))
+ (cautionary-padding (assoc-get 'padding cautionary-props 0))
+ (cautionary-proc (assoc-get 'procedure cautionary-props parenthesize-stencil))
+ (cautionary-width (assoc-get 'width cautionary-props 0.25))
+ (output-grob (ly:text-interface::print grob))
+ (ref-grob (grob-interpret-markup grob "8"))
+ (column-offset (interval-length
+ (ly:stencil-extent
+ (grob-interpret-markup grob "8")
+ X))))
+
+ (if (is-harmonic? grob)
+ (set! output-grob (harmonic-proc output-grob
+ harmonic-half-thick
+ harmonic-width
+ harmonic-angularity
+ harmonic-padding)))
+ (if cautionary
+ (set! output-grob (cautionary-proc output-grob
+ cautionary-half-thick
+ cautionary-width
+ cautionary-angularity
+ cautionary-padding)))
+ (ly:stencil-translate-axis (centered-stencil output-grob)
+ column-offset
+ X)))
+
+;; Harmonic definitions
+
+(define node-positions
+ ;; for the node on m/n-th of the string length, we get the corresponding
+ ;; (exact) fret position by calculating p=(-12/log 2)*log(1-(m/n));
+ ;; since guitarists normally use the forth fret and not the 3.8th, here
+ ;; are rounded values, ordered by
+ ;; 1/2
+ ;; 1/3 2/3
+ ;; 1/4 2/4 3/4 etc.
+ ;; The value for 2/4 is irrelevant in practical, bacause the string sounds
+ ;; only one octave higher, not two, but since scheme normalizes the fractions
+ ;; anyway, these values are simply placeholders for easier indexing.
+ ;; According to the arithmetic sum, the position of m/n is at 1/2*(n-2)(n-1)+(m-1)
+ ;; if we start counting from zero
+ (vector 12
+ 7 19
+ 5 12 24
+ 4 9 16 28
+ 3 7 12 19 31
+ 2.7 5.8 9.7 14.7 21.7 33.7
+ 2.3 5 8 12 17 24 36
+ 2 4.4 7 10 14 19 26 38 ))
+
+(define partial-pitch
+ (vector '(0 0 0)
+ '(1 0 0)
+ '(1 4 0)
+ '(2 0 0)
+ '(2 2 0)
+ '(2 4 0)
+ '(2 6 -1/2)
+ '(3 0 0)
+ '(3 1 0)))
+
+(define fret-partials
+ '(("0" . 0)
+ ("12" . 1)
+ ("7" . 2)
+ ("19" . 2)
+ ("5" . 3)
+ ("24" . 3)
+ ("4" . 4)
+ ("9" . 4)
+ ("16" . 4)
+ ("3" . 5)
+ ("2.7" . 6)
+ ("2.3" . 7)
+ ("2" . 8)))
+
+(define-public (ratio->fret ratio)
+ "Calculate a fret number given @var{ratio} for the harmonic."
+ (let* ((nom (numerator ratio))
+ (den (denominator ratio))
+ (index (+ (* (- den 2)
+ (- den 1)
+ 1/2)
+ nom -1)))
+ (number->string (vector-ref node-positions index))))
+
+(define-public (ratio->pitch ratio)
+ "Calculate a pitch given @var{ratio} for the harmonic."
+ (let* ((partial (1- (denominator ratio)))
+ (pitch (vector-ref partial-pitch partial)))
+
+ (ly:make-pitch (first pitch)
+ (second pitch)
+ (third pitch))))
+
+(define-public (fret->pitch fret)
+ "Calculate a pitch given @var{fret} for the harmonic."
+ (let* ((partial (assoc-get fret fret-partials 0))
+ (pitch (vector-ref partial-pitch partial)))
+
+ (ly:make-pitch (first pitch)
+ (second pitch)
+ (third pitch))))
+
+(define-public (calc-harmonic-pitch pitch music)
+ "Calculate the harmonic pitches in @var{music} given
+@var{pitch} as the non-harmonic pitch."
+ (let ((es (ly:music-property music 'elements))
+ (e (ly:music-property music 'element))
+ (p (ly:music-property music 'pitch)))
+ (cond
+ ((pair? es)
+ (ly:music-set-property! music 'elements
+ (map (lambda (x) (calc-harmonic-pitch pitch x)) es)))
+ ((ly:music? e)
+ (ly:music-set-property! music 'element (calc-harmonic-pitch pitch e)))
+ ((ly:pitch? p)
+ (begin
+ (set! p (ly:pitch-transpose p pitch))
+ (ly:music-set-property! music 'pitch p))))
+ music))
+
+(define-public (make-harmonic mus)
+ "Convert music variable @var{mus} to harmonics."
+ (let ((elts (ly:music-property mus 'elements))
+ (elt (ly:music-property mus 'element)))
+ (cond
+ ((pair? elts)
+ (map make-harmonic elts))
+ ((ly:music? elt)
+ (make-harmonic elt))
+ ((music-is-of-type? mus 'note-event)
+ (set! (ly:music-property mus 'articulations)
+ (append
+ (ly:music-property mus 'articulations)
+ (list (make-music 'HarmonicEvent))))))
+ mus))
else:
return ''
+def addLang(url, lang):
+ if lang:
+ base, ext = os.path.splitext(url)
+ return base + '.' + lang + ext
+ else:
+ return url
def make_manual_links(name, version, lang):
"""Here is where all the macros manualStableLearningSplit,
# until 2.14 is out. -gp
if (url.endswith('.html')):
make_ver_link(macroLang("manual"+name+mshort+'Pdf',lang),
- url,
+ addLang(url, lang),
getTrans(manual.capitalize(),lang) + '.pdf')
make_ver_link(macroLang("manual"+name+mshort+'Split',lang),
- url,
+ addLang(url, lang),
getTrans(manual.capitalize(),lang) +
getTrans(' (split HTML)',lang))
make_ver_link(macroLang("manual"+name+mshort+'Big',lang),
- url,
+ addLang(url, lang),
getTrans(manual.capitalize(),lang) +
getTrans(' (big HTML)',lang))
newurl = url
else:
make_ver_link(macroLang("manual"+name+mshort+'Pdf',lang),
- url + '.pdf',
+ # TODO: this is an even stupider way of doing it
+ addLang(url+'.pdf', lang),
getTrans(manual.capitalize(),lang) + '.pdf')
make_ver_link(macroLang("manual"+name+mshort+'Split',lang),
- url + '/index.html',
+ addLang(url + '/index.html', lang),
getTrans(manual.capitalize(),lang) +
getTrans(' (split HTML)',lang))
make_ver_link(macroLang("manual"+name+mshort+'Big',lang),
- url + '-big-page.html',
+ addLang(url + '-big-page.html', lang),
getTrans(manual.capitalize(),lang) +
getTrans(' (big HTML)',lang))
newurl = url + '/index.html'
make_ver_link(macroLang("manual"+name+mshort+'SplitNoName',lang),
- newurl,
+ addLang(newurl, lang),
getTrans(manual.capitalize(),lang))
def make_regtest_links(name, version, lang):
### alter links as appropriate
link = getLocalHref(line)
if (link != ""):
- # quesitonable
- if (link.endswith(".html")):
- langlink = addLangExt(link[:-5], lang, "html")
- line = line.replace(link, langlink)
- if (link.endswith(".pdf")):
- langlink = addLangExt(link[:-4], lang, "pdf")
- line = line.replace(link, langlink)
+ # questionable
+ if (not link.startswith("../doc/")):
+ if (link.endswith(".html")):
+ langlink = addLangExt(link[:-5], lang, "html")
+ line = line.replace(link, langlink)
+ if (link.endswith(".pdf")):
+ langlink = addLangExt(link[:-4], lang, "pdf")
+ line = line.replace(link, langlink)
### add google tracker header
if (line.find("</head>") >= 0):
outfile.write("""<!-- Google tracking !-->
s = ''
- s = tag + '\n\\version "2.7.18"\n\n'
+ s = tag + '\n\\version "2.7.38"\n\n'
for i in range (len (tracks)):
s = s + dump_track (tracks[i], i)