now positioned automatically to avoid collisions.
@lilypond[fragment,ragged-right,relative=1]
- \override TextScript #'outside-staff-priority = #1
c''
\once \override TextScript #'self-alignment-X = #CENTER
a,^"this doesn't collide with the c"
}
@end lilypond
-Text can also be placed on its own, away from any @code{\score}
-block. This is primarily used in a @code{\book} (see
-@ref{Multiple scores in a book}).
+A @code{\markup} command can also be placed on its own, away from any
+@code{\score} block, see @ref{Multiple scores in a book}.
@lilypond[quote,ragged-right,verbatim]
\markup{ Here is some text. }
}
@end lilypond
-The @code{set-octavation} function also takes -1 (for 8va bassa) and 2
-(for 15ma) as arguments. Internally the function sets the properties
-@code{ottavation} (e.g., to @code{"8va"}) and
+The @code{set-octavation} function also takes -1 (for 8va bassa), 2@tie{}(for 15ma),
+and -2 (for 15ma bassa) as arguments. Internally the function sets the properties
+@code{ottavation} (e.g., to @code{"8va"} or @code{"8vb"}) and
@code{centralCPosition}. For overriding the text of the bracket, set
@code{ottavation} after invoking @code{set-octavation}, i.e.,
The command @code{\setEasyHeads} overrides settings for the
@internalsref{NoteHead} object. To make the letters readable, it has
to be printed in a large font size. To print with a larger font, see
-@ref{Setting global staff size}.
+@ref{Setting the staff size}.
@refcommands
and the @context{Voice} is inserted afterwards
@example
-\new Staff = down
+\context Staff = down
\new Voice @{ @dots{} \change Staff = up @dots{} @}
@end example
@end lilypond
+@refbugs
+
+When using figured bass above the staff with extender lines and
+@code{implicitBassFigures} the lines may become swapped around.
+Maintaining order consistently will be impossible when multiple figures
+have overlapping extender lines. To avoid this problem, plese
+use @code{stacking-dir} on @code{BassFigureAlignment}.
+
+
@seealso
Program reference: @internalsref{NewBassFigure},
@top GNU LilyPond --- The music typesetter
@c HJJ: Info needs `@top', which is a synonym for `@unnumbered' in TeX.
-This is the user manual for GNU LilyPond 2.8.x series.
+This is the user manual for GNU LilyPond 2.10.x series.
@ifhtml
(See the bottom of this page for the exact version number).
@end ifhtml
@funindex \book
-The movements and texts are combined together in a @code{\book} block,
-like
+All the movements and texts which appear in the same @code{.ly} file
+will normally be typeset in the form of a single output file.
@example
-\book @{
- \score @{
- @var{..}
- @}
- \markup @{
- @var{..}
- @}
- \score @{
- @var{..}
- @}
+\score @{
+ @var{..}
+@}
+\markup @{
+ @var{..}
+@}
+\score @{
+ @var{..}
@}
@end example
+However, if you want multiple output files from the same @code{.ly}
+file, then you can add multiple @code{\book} blocks, where each such
+@code{\book} block will result in a separate output. If you do not
+specify any @code{\book} block in the file, LilyPond will implicitly
+treat the full file as a single @code{\book} block, see @ref{File
+structure}. One important exception is within lilypond-book documents,
+where you explicitly have to add a @code{\book} block, otherwise only
+the first @code{\score} or @code{\markup} will appear in the output.
The header for each piece of music can be put inside the @code{\score}
block. The @code{piece} name from the header will be printed before
the top of the file is inserted.
@example
-\book @{
- \header @{
- title = "Eight miniatures"
- composer = "Igor Stravinsky"
- @}
- \score @{
- @dots{}
- \header @{ piece = "Romanze" @}
- @}
- \markup @{
- ..text of second verse..
- @}
- \markup @{
- ..text of third verse..
- @}
- \score @{
- @dots{}
- \header @{ piece = "Menuetto" @}
- @}
+\header @{
+ title = "Eight miniatures"
+ composer = "Igor Stravinsky"
+@}
+\score @{
+ @dots{}
+ \header @{ piece = "Romanze" @}
+@}
+\markup @{
+ ..text of second verse..
+@}
+\markup @{
+ ..text of third verse..
+@}
+\score @{
+ @dots{}
+ \header @{ piece = "Menuetto" @}
@}
@end example
@item
A @code{\book} block logically combines multiple movements
(i.e., multiple @code{\score} blocks) in one document. If there are
-a number of @code{\scores}, a single output file will be created
-in which all movements are concatenated.
+a number of @code{\scores}, one output file will be created for
+each @code{\book} block, in which all corresponding movements are
+concatenated. The only reason to explicitly specify @code{\book} blocks
+in a @code{.ly} file is if you wish multiple output files from a single
+input file. One exception is within lilypond-book documents, where you
+explicitly have to add a @code{\book} block if you want more than a
+single @code{\score} or @code{\markup} in the same example.
This behavior can be changed by setting the variable
@code{toplevel-book-handler} at toplevel. The default handler is
@node Creating titles
@subsection Creating titles
-Titles are created for each @code{\score} block, and over a
-@code{\book}.
+Titles are created for each @code{\score} block, and for the full input
+file (or @code{\book} block).
The contents of the titles are taken from the @code{\header} blocks.
The header block for a book supports the following
@table @code
@funindex bookTitleMarkup
@item bookTitleMarkup
- This is the title put over an entire @code{\book} block. Typically,
- it has the composer and the title of the piece
+ This is the title added at the top of the entire output document.
+Typically, it has the composer and the title of the piece
@funindex scoreTitleMarkup
@item scoreTitleMarkup
- This is the title put over a @code{\score} block within a
-@code{\book}. Typically, it has the name of the movement (@code{piece}
-field).
+ This is the title put over a @code{\score} block. Typically, it has
+the name of the movement (@code{piece} field).
@funindex oddHeaderMarkup
@item oddHeaderMarkup
@funindex printallheaders
@item printallheaders
-Setting this to #t will print all headers for each \score in a
-\book. Normally only the piece and opus \headers are printed.
+Setting this to #t will print all headers for each \score in the
+output. Normally only the piece and opus \headers are printed.
@funindex systemSeparatorMarkup
@item systemSeparatorMarkup
@section Music layout
@menu
-* Setting global staff size::
+* Setting the staff size::
* Score layout::
@end menu
-@node Setting global staff size
-@subsection Setting global staff size
+@node Setting the staff size
+@subsection Setting the staff size
@cindex font size, setting
@cindex staff size, setting
@funindex layout file
-To set the global staff size, use @code{set-global-staff-size}.
+To set the staff size globally for all scores in a file (or
+in a @code{book} block, to be precise), use @code{set-global-staff-size}.
@example
#(set-global-staff-size 14)
This sets the global default size to 14pt staff height and scales all
fonts accordingly.
+To set the staff size individually for each score, use
+@example
+\score@{
+ ...
+ \layout@{
+ #(layout-set-staff-size 15)
+ @}
+@}
+@end example
+
The Feta font provides musical symbols at eight different
sizes. Each font is tuned for a different staff size: at a smaller size
the font becomes heavier, to match the relatively heavier staff lines.
\combine "X" "+"
\combine "o" "/"
\box \column { \line { "string 1" } \line { "string 2" } }
+ " "
\italic Norsk
\super "2"
+ \circle \dynamic "p"
+ " "
\dynamic sfzp
\huge { "A" \smaller "A" \smaller \smaller "A"
\smaller \smaller \smaller "A" }
--- /dev/null
+
+\version "2.11.0"
+
+\header {
+
+ texidoc = " Broken ties honor @code{minimum-length} also. This tie
+has a @code{minimum-length} of 5."
+
+}
+
+\relative {
+ \override Tie #'minimum-length = #5
+ f2. f16 f f f ~ | \break
+ f1
+}
+
+\paper {
+ indent = 0.0\mm
+ line-width = 40.0\mm
+}
if (heads.is_empty () || heads.length () < 0.5)
{
- programming_error ("no heads for arpeggio found?");
- me->suicide ();
+ if (!to_boolean (me->get_property ("transparent")))
+ {
+ me->warning ("no heads for arpeggio found?");
+ me->suicide ();
+ }
return SCM_EOL;
}
DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM));
DECLARE_GROB_INTERFACE();
- static int get_rank (Grob *);
+ static int get_rank (Grob const *);
static bool is_musical (Grob *);
static Moment when_mom (Grob *);
static bool is_used (Grob *);
{
Music *me = unsmob_music (m);
Music *elt = unsmob_music (me->get_property ("element"));
- return elt->get_length ().smobbed_copy ();
+ if (elt)
+ return elt->get_length ().smobbed_copy ();
+ else
+ return Moment (0).smobbed_copy ();
}
}
int
-Paper_column::get_rank (Grob *me)
+Paper_column::get_rank (Grob const *me)
{
- return dynamic_cast<Paper_column *> (me)->rank_;
+ return dynamic_cast<Paper_column const *> (me)->rank_;
}
System *
for (vsize j = 0; j < arpeggios_.size (); j++)
{
extract_grob_set (arpeggios_[j], "stems", stems);
- for (vsize i = stems.size (); i--;)
+ for (vsize i = 0; i < stems.size (); i++)
Pointer_group_interface::add_grob (span_arpeggio_, ly_symbol2scm ("stems"),
stems[i]);
extract_grob_set (arpeggios_[j], "side-support-elements", sses);
- for (vsize i = sses.size (); i--;)
+ for (vsize i = 0; i < sses.size (); i++)
Pointer_group_interface::add_grob (span_arpeggio_, ly_symbol2scm ("side-support-elements"),
sses[i]);
Spanner::set_spacing_rods (SCM smob)
{
Grob *me = unsmob_grob (smob);
-
- Rod r;
- Spanner *sp = dynamic_cast<Spanner *> (me);
- r.item_drul_[LEFT] = sp->get_bound (LEFT);
- r.item_drul_[RIGHT] = sp->get_bound (RIGHT);
-
SCM num_length = me->get_property ("minimum-length");
if (scm_is_number (num_length))
{
+ Rod r;
+ Spanner *sp = dynamic_cast<Spanner *> (me);
+
+
+ System *root = get_root_system (me);
+ vector<Item*> cols (root->broken_col_range (sp->get_bound (LEFT)->get_column (),
+ sp->get_bound (RIGHT)->get_column ()));
+
+ if (cols.size ())
+ {
+ Rod r ;
+ r.item_drul_[LEFT] = sp->get_bound (LEFT);
+ r.item_drul_[RIGHT] = cols[0]->find_prebroken_piece (LEFT);
+ r.distance_ = robust_scm2double (num_length, 0);
+ r.add_to_cols ();
+
+ r.item_drul_[LEFT] = cols.back ()->find_prebroken_piece (RIGHT);
+ r.item_drul_[RIGHT] = sp->get_bound (RIGHT);
+ r.add_to_cols ();
+ }
+
r.distance_ = robust_scm2double (num_length, 0);
+ r.item_drul_[LEFT] = sp->get_bound (LEFT);
+ r.item_drul_[RIGHT] = sp->get_bound (RIGHT);
r.add_to_cols ();
}
LY_DEFINE (ly_event_property, "ly:event-property",
2, 0, 0, (SCM sev, SCM sym),
"Get the property @var{sym} of stream event @var{mus}.\n"
- "If @var{sym} is undefined, return @code{' ()}.\n")
+ "If @var{sym} is undefined, return @code{'()}.\n")
{
Stream_event *e = unsmob_stream_event (sev);
SCM_ASSERT_TYPE (e, sev, SCM_ARG1, __FUNCTION__, "stream event");
left = left->get_column ();
right = right->get_column ();
+
extract_grob_set (this, "columns", cols);
- vsize i = 0;
- while (i < cols.size ()
- && cols[i] != left)
- i++;
+ vsize i = binary_search (cols, (Grob *) left,
+ Paper_column::less_than);
+
+ int end_rank = Paper_column::get_rank (right);
if (i < cols.size ())
i++;
while (i < cols.size ()
- && cols[i] != right)
+ && Paper_column::get_rank (cols[i]) < end_rank)
{
Paper_column *c = dynamic_cast<Paper_column *> (cols[i]);
if (Paper_column::is_breakable (c) && !c->system_)
--- /dev/null
+/*
+ tab-harmonic-engraver.cc -- implement Tab_harmonic_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2005--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#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 */ "Parenthesize objects whose music cause has the @code{parenthesize} "
+ "property.",
+
+ /* create */
+ "HarmonicParenthesesItem ",
+ /* read */ "",
+ /* write */ "");
/*
tab-note-heads-engraver.cc -- part of GNU LilyPond
- based on note-heads-engraver.cc, by Jean-Baptiste Lamy <jiba@tuxfamily.org>,
-
- (c) 2002--2006
+ (c) 2002--2006 Han-Wen Nienhuys, Jean-Baptiste Lamy <jiba@tuxfamily.org>,
*/
#include <cctype>
#include "rhythmic-head.hh"
#include "stream-event.hh"
#include "warn.hh"
+#include "context.hh"
#include "translator.icc"
vsize j = 0;
for (vsize i = 0; i < note_events_.size (); i++)
{
- SCM stringTunings = get_property ("stringTunings");
- int number_of_strings = scm_ilength (stringTunings);
+ SCM string_tunings = get_property ("stringTunings");
+ int number_of_strings = scm_ilength (string_tunings);
bool high_string_one = to_boolean (get_property ("highStringOne"));
Stream_event *event = note_events_[i];
while (!string_found)
{
int fret = unsmob_pitch (scm_pitch)->semitone_pitch ()
- - scm_to_int (scm_list_ref (stringTunings, scm_from_int (tab_string - 1)));
+ - scm_to_int (scm_list_ref (string_tunings, scm_from_int (tab_string - 1)));
if (fret < min_fret)
tab_string += high_string_one ? 1 : -1;
else
string_found = true;
}
- SCM text = scm_call_3 (proc, scm_from_int (tab_string), stringTunings, scm_pitch);
+ SCM text = scm_call_3 (proc, scm_from_int (tab_string),
+ context ()->self_scm (),
+ event->self_scm ());
+ note->set_property ("text", text);
+
int pos = 2 * tab_string - number_of_strings - 1; // No tab-note between the string !!!
if (to_boolean (get_property ("stringOneTopmost")))
pos = -pos;
- note->set_property ("text", text);
-
note->set_property ("staff-position", scm_from_int (pos));
+
+
notes_.push_back (note);
}
}
straight_corners[d] += -d * shorten[d] / length * dz;
while (flip (&d) != LEFT);
- if (gap.is_empty ())
- gap = Interval (0, 0);
- do
- gap_corners[d] = (dz * 0.5) + gap[d] / length * dz;
- while (flip (&d) != LEFT)
- ;
+ if (!gap.is_empty ())
+ {
+ do
+ gap_corners[d] = (dz * 0.5) + gap[d] / length * dz;
+ while (flip (&d) != LEFT);
+ }
Drul_array<Offset> flare_corners = straight_corners;
do
Stencil m;
do
{
- m.add_stencil (Line_interface::line (me, straight_corners[d],
- gap_corners[d]));
+ if (!gap.is_empty ())
+ m.add_stencil (Line_interface::line (me, straight_corners[d],
+ gap_corners[d]));
m.add_stencil (Line_interface::line (me, straight_corners[d],
flare_corners[d]));
}
+
while (flip (&d) != LEFT);
+ if (gap.is_empty ())
+ m.add_stencil (Line_interface::line (me, straight_corners[LEFT],
+ straight_corners[RIGHT]));
+
return m;
}
\name "TabVoice"
\alias "Voice"
\consists "Tab_note_heads_engraver"
+ \consists "Tab_harmonic_engraver"
+
\remove "Note_heads_engraver"
\remove "Fingering_engraver"
\remove "New_fingering_engraver"
(ly:add-interface
'parentheses-interface
"Parentheses for other objects"
- '(padding))
+ '(padding stencils))
(ly:add-interface
'piano-pedal-interface
directions, this amount is the correction for two normal sized stems
that overlap completely.")
(stencil ,ly:stencil? "The symbol to print.")
+ (stencils ,list? "Multiple stencils, used as intermediate value.")
(strict-note-spacing ,boolean? "If set, unbroken columns
with non-musical material (clefs, barlines, etc.) are not spaced
separately, but put before musical columns.")
(ParenthesesItem
. ((stencil . ,parentheses-item::print)
+ (stencils . ,parentheses-item::calc-parenthesis-stencils)
(font-size . -6)
(padding . 0.2)
(meta . ((class . Item)
(interfaces . (parentheses-interface font-interface))))
))
+
+ (HarmonicParenthesesItem
+ . ((stencil . ,parentheses-item::print)
+ (padding . 0)
+ (stencils . ,parentheses-item::calc-angled-bracket-stencils)
+ (meta . ((class . Item)
+ (interfaces . (parentheses-interface font-interface))))
+ ))
(PhrasingSlur
. ((details . ,default-slur-details)
(interfaces . (side-position-interface
system-start-delimiter-interface))))))
-
(TabNoteHead
. (
(stencil . ,ly:text-interface::print)
(Y-offset . ,ly:staff-symbol-referencer::callback)
+ (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
+ (direction . 0)
(font-size . -2)
(stem-attachment . (0.0 . 1.35))
(font-series . bold)
(stencil . ,ly:tie::print)
(font-size . -6)
(details . (
- ;; for a full list, see tie-helper.cc
+ ;; for a full list, see tie-details.cc
(ratio . 0.333)
(center-staff-line-clearance . 0.6)
(tip-staff-line-clearance . 0.45)
(define-markup-command (whiteout layout props arg) (markup?)
"Provide a white underground for @var{arg}"
- (let* ((stil (interpret-markup layout props arg))
- (white
- (interpret-markup layout props
- (make-with-color-markup
- white
- (make-filled-box-markup
- (ly:stencil-extent stil X)
- (ly:stencil-extent stil Y)
- 0.0)))))
-
- (ly:stencil-add white stil)))
+ (stencil-whiteout (interpret-markup layout props arg)))
(define-markup-command (pad-markup layout props padding arg) (number? markup?)
"Add space around a markup object."
;;;;;;;;;;;;;;;;
;; list
+(define (functional-or . rest)
+ (if (pair? rest)
+ (or (car rest)
+ (apply functional-and (cdr rest)))
+ #f))
+
+(define (functional-and . rest)
+ (if (pair? rest)
+ (and (car rest)
+ (apply functional-and (cdr rest)))
+ #t))
+
(define (split-list lst n)
"Split LST in N equal sized parts"
(format "~a ~a ~a\n"
gc-protect-stat-count
sym
- (cdr (assoc sym stats)))
+ (let ((sym-stat (assoc sym stats)))
+ (if sym-stat
+ (cdr sym-stat)
+ "?")))
outfile))
'(protected-objects bytes-malloced cell-heap-size
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; markup definer utilities
+
+(defmacro-public in-module-define-variable (module-name symbol value)
+ "Define a variable in a module and export its name.
+ (in-module-define-variable (some module) symbol value)"
+ (let ((gmodule (gensym "module")))
+ `(let ((,gmodule (resolve-module ',module-name)))
+ (module-define! ,gmodule ',symbol ,value)
+ (module-export! ,gmodule '(,symbol)))))
+
+(defmacro-public in-module-define-function
+ (module-name function-name+arg-list . body)
+ "Define a public function in a module:
+ (in-module-define-function (some module) (function-name . args)
+ ..body..)"
+ `(in-module-define-variable
+ ,module-name
+ ,(car function-name+arg-list)
+ (let ((proc (lambda ,(cdr function-name+arg-list)
+ ,@body)))
+ (set-procedure-property! proc
+ 'name
+ ',(car function-name+arg-list))
+ proc)))
+
;;; `define-markup-command' can be used both for built-in markup
;;; definitions and user defined markups.
-
(defmacro-public define-markup-command (command-and-args signature . body)
"
(define-markup-command (COMMAND layout props arg1 arg2 ...) (arg1-type? arg2-type? ...)
\"documentation string\"
...command body...)
- or:
- (define-markup-command COMMAND (arg1-type? arg2-type? ...)
- function)
+or:
+ (define-markup-command COMMAND (arg1-type? arg2-type? ...) function)
"
- (let* ((command (if (pair? command-and-args) (car command-and-args) command-and-args))
- (args (if (pair? command-and-args) (cdr command-and-args) '()))
- (command-name (string->symbol (string-append (symbol->string command) "-markup")))
- (make-markup-name (string->symbol (string-append "make-" (symbol->string command-name)))))
- `(begin
- (define-public ,(if (pair? args)
- (cons command-name args)
- command-name)
- ,@body)
- (set! (markup-command-signature ,command-name) (list ,@signature))
- (if (not (member ,command-name markup-function-list))
- (set! markup-function-list (cons ,command-name markup-function-list)))
- (define-public (,make-markup-name . args)
- (let ((sig (list ,@signature)))
- (make-markup ,command-name ,(symbol->string make-markup-name) sig args))))))
+ (let* ((command (if (pair? command-and-args)
+ (car command-and-args)
+ command-and-args))
+ (command-name (string->symbol (format #f "~a-markup" command)))
+ (make-markup-name (string->symbol (format #f "make-~a-markup" command))))
+ `(let ((lily-module (resolve-module '(lily))))
+ ;; define the COMMAND-markup procedure in (lily) module
+ ,(if (pair? command-and-args)
+ ;; two cases:
+ ;; 1/ (define (COMMAND-markup layout props arg1 arg2 ...)
+ ;; ..command body))
+ `(in-module-define-function (lily) (,command-name ,@(cdr command-and-args))
+ ,@body)
+ ;; 2/ (define COMMAND-markup function)
+ `(in-module-define-variable (lily) ,command-name ,(car body)))
+ (let ((command-proc (module-ref lily-module ',command-name)))
+ ;; register its command signature
+ (set! (markup-command-signature command-proc)
+ (list ,@signature))
+ ;; add the COMMAND-markup procedure to the list of markup functions
+ (if (not (member command-proc markup-function-list))
+ (set! markup-function-list (cons command-proc markup-function-list)))
+ ;; define the make-COMMAND-markup procedure in (lily) module
+ (in-module-define-function (lily) (,make-markup-name . args)
+ (make-markup command-proc
+ ,(symbol->string make-markup-name)
+ (list ,@signature)
+ args))))))
(define-public (make-markup markup-function make-name signature args)
" Construct a markup object from MARKUP-FUNCTION and ARGS. Typecheck
(define (markup-symbol-to-proc markup-sym)
"Return the markup command procedure which name is `markup-sym', if any."
(hash-fold (lambda (key val prev)
- (or prev
- (if (eqv? (procedure-name key) markup-sym) key #f)))
+ (or prev
+ (if (eqv? (procedure-name key) markup-sym) key #f)))
#f
markup-command-signatures))
(car stencils))
(ly:make-stencil '() '(0 . 0) '(0 . 0))))
-
-
-
-
-
-
(string (cdr (assoc octavation '((2 . "15ma")
(1 . "8va")
(0 . #f)
- (-1 . "8va bassa")
- (-2 . "15ma bassa"))))))
+ (-1 . "8vb")
+ (-2 . "15mb"))))))
(ly:context-set-property! context 'middleCPosition new-c0)
(ly:context-set-property! context 'originalCentralCPosition c0)
(ly:context-set-property! context 'ottavation string)))))
;; The TabNoteHead tablatureFormat callback.
;; Compute the text grob-property
-(define-public (fret-number-tablature-format string tuning pitch)
- (make-whiteout-markup
- (make-vcenter-markup
- (number->string
- (- (ly:pitch-semitones pitch)
- (list-ref tuning
- ;; remove 1 because list index starts at 0 and guitar string at 1.
- (- string 1)))))))
+(define-public (fret-number-tablature-format string
+ context event)
+ (let*
+ ((tuning (ly:context-property context 'stringTunings))
+ (pitch (ly:event-property event 'pitch))
+ (is-harmonic (apply
+ functional-or
+ (map
+ (lambda (ev)
+ (eq? 'harmonic-event (ly:event-property ev 'class)))
+ (ly:event-property event 'articulations)))))
+
+
+ (make-whiteout-markup
+ (make-vcenter-markup
+ (format
+ "~a"
+ (- (ly:pitch-semitones pitch)
+ (list-ref tuning
+ ;; remove 1 because list index starts at 0 and guitar string at 1.
+ (- string 1))))))
+ ))
;; The 5-string banjo has got a extra string, the fifth (duh), wich
;; starts at the fifth fret on the neck. Frets on the fifth string
;; the "first fret" on the fifth string is really the sixth fret
;; on the banjo neck.
;; We solve this by defining a new fret-number-tablature function:
-(define-public (fret-number-tablature-format-banjo string tuning pitch)
+(define-public (fret-number-tablature-format-banjo string
+ context event)
+ (let*
+ ((tuning (ly:context-property context 'stringTuning))
+ (pitch (ly:event-property event 'pitch))
+ )
(make-whiteout-markup
(make-vcenter-markup
(let ((fret (- (ly:pitch-semitones pitch) (list-ref tuning (- string 1)))))
(number->string (cond
((and (> fret 0) (= string 5))
(+ fret 5))
- (else fret)))))))
+ (else fret))))))
+ ))
; default tunings for common string instruments
;; * Pitch Trill Heads
;; * Parentheses
+(define-public (parentheses-item::calc-parenthesis-stencils grob)
+ (let* (
+ (font (ly:grob-default-font grob))
+ (lp (ly:font-get-glyph font "accidentals.leftparen"))
+ (rp (ly:font-get-glyph font "accidentals.rightparen"))
+ )
+
+ (list lp rp)))
+
+
+(define (grob-text grob text)
+ (let*
+ ((layout (ly:grob-layout grob))
+ (defs (ly:output-def-lookup layout 'text-font-defaults))
+ (props (ly:grob-alist-chain grob defs)))
+
+ (ly:text-interface::interpret-markup
+ layout props text)))
+
+(define-public (parentheses-item::calc-angled-bracket-stencils grob)
+ (let* (
+ (font (ly:grob-default-font grob))
+ (lp (ly:stencil-aligned-to (ly:stencil-aligned-to (grob-text grob (ly:wide-char->utf-8 #x2329))
+ Y CENTER) X RIGHT))
+ (rp (ly:stencil-aligned-to (ly:stencil-aligned-to (grob-text grob (ly:wide-char->utf-8 #x232A))
+ Y CENTER) X LEFT))
+ )
+
+ (list (stencil-whiteout lp)
+ (stencil-whiteout rp))))
+
(define (parenthesize-elements grob . rest)
(let*
((refp (if (null? rest)
(car rest)))
(elts (ly:grob-object grob 'elements))
(x-ext (ly:relative-group-extent elts refp X))
-
- (font (ly:grob-default-font grob))
- (lp (ly:font-get-glyph font "accidentals.leftparen"))
- (rp (ly:font-get-glyph font "accidentals.rightparen"))
+ (stencils (ly:grob-property grob 'stencils))
+ (lp (car stencils))
+ (rp (cadr stencils))
(padding (ly:grob-property grob 'padding 0.1)))
(ly:stencil-add
))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
`(text ,font-metric ,text) (car b) (cdr b))))
(define-public (fontify-text-white scale font-metric text)
- "Set TEXT with scale factor s"
+ "Set TEXT with scale factor SCALE"
(let* ((b (ly:text-dimension font-metric text))
;;urg -- workaround for using ps font
(c `(white-text ,(* 2 scale) ,text)))
;;urg -- extent is not from ps font, but we hope it's close
(ly:make-stencil c (car b) (cdr b))))
+(define-public (stencil-with-color stencil color)
+ (ly:make-stencil
+ (list 'color color (ly:stencil-expr stencil))
+ (ly:stencil-extent stencil X)
+ (ly:stencil-extent stencil Y)))
+
+(define-public (stencil-whiteout stencil)
+ (let*
+ ((x-ext (ly:stencil-extent stencil X))
+ (y-ext (ly:stencil-extent stencil Y))
+
+ )
+
+ (ly:stencil-add
+ (stencil-with-color (ly:round-filled-box x-ext y-ext 0.0)
+ white)
+ stencil)
+ ))
+
(define-public (dimension-arrows destination)
"Draw twosided arrow from here to @var{destination}"