#include "text-interface.hh"
#include "grob.hh"
+#include "item.hh"
#include "line-interface.hh"
#include "lookup.hh"
#include "font-interface.hh"
#include "lily-guile.hh"
#include "output-def.hh"
#include "misc.hh"
+#include "spanner.hh"
+#include "international.hh"
class Balloon_interface
{
public:
DECLARE_SCHEME_CALLBACK (print, (SCM));
+ DECLARE_SCHEME_CALLBACK (print_spanner, (SCM));
DECLARE_GROB_INTERFACE ();
};
b.widen (padding, padding);
// FIXME
- Stencil fr = Lookup::frame (b, 0.1, 0.05);
+ Stencil fr;
+ if (to_boolean (me->get_property ("annotation-balloon")))
+ fr = Lookup::frame (b, 0.1, 0.05);
SCM bt = me->get_property ("text");
SCM chain = Font_interface::text_font_alist_chain (me);
Offset z2 = z1 + off;
- fr.add_stencil (Line_interface::line (me, z1, z2));
+ if (to_boolean (me->get_property ("annotation-line")))
+ fr.add_stencil (Line_interface::line (me, z1, z2));
+
+ text_stil->translate (z2);
+ fr.add_stencil (*text_stil);
+
+ fr.translate (-off);
+ return fr.smobbed_copy ();
+}
+
+// ugh...code dup...hopefully can be consolidated w/ above one day
+MAKE_SCHEME_CALLBACK (Balloon_interface, print_spanner, 1);
+SCM
+Balloon_interface::print_spanner (SCM smob)
+{
+ Spanner *me = unsmob_spanner (smob);
+ Spanner *parent = unsmob_spanner (me->get_property ("parent-spanner"));
+ Spanner *p;
+ message (_f ("foo %d", robust_scm2int (me->get_property ("spanner-to-annotate"), 0)));
+ message (_f ("bar %d", robust_scm2int (me->broken_intos_[0]->get_property ("spanner-to-annotate"), 0)));
+ if (parent->broken_intos_.size () == 0)
+ p = parent;
+ else
+ p = parent->broken_intos_[robust_scm2int (me->get_property ("spanner-to-annotate"), 0) % parent->broken_intos_.size ()];
+
+
+ Drul_array<Item *> bounds;
+ Direction d = LEFT;
+
+ do
+ {
+ bounds[d] = me->get_bound (d);
+ }
+ while (flip (&d) != LEFT);
+
+ Grob *commonx = bounds[LEFT]->common_refpoint (bounds[RIGHT], X_AXIS);
+
+ Offset off (me->relative_coordinate (commonx, X_AXIS),
+ me->relative_coordinate (p, Y_AXIS));
+
+ Box b (p->extent (p, X_AXIS),
+ p->extent (p, Y_AXIS));
+
+ Real padding = robust_scm2double (me->get_property ("padding"), .1);
+ b.widen (padding, padding);
+
+ // FIXME
+ Stencil fr;
+ if (to_boolean (me->get_property ("annotation-balloon")))
+ fr = Lookup::frame (b, 0.1, 0.05);
+
+ SCM bt = me->get_property ("text");
+ SCM chain = Font_interface::text_font_alist_chain (me);
+
+ SCM stencil = Text_interface::interpret_markup (me->layout ()->self_scm (),
+ chain, bt);
+
+ Stencil *text_stil = unsmob_stencil (stencil);
+
+ Offset z1;
+ for (int i = X_AXIS; i < NO_AXES; i++)
+ {
+ Axis a ((Axis)i);
+ z1[a] = b[a].linear_combination (sign (off[a]));
+ text_stil->align_to (a, -sign (off[a]));
+ }
+
+ Offset z2 = z1 + off;
+
+ if (to_boolean (me->get_property ("annotation-line")))
+ fr.add_stencil (Line_interface::line (me, z1, z2));
text_stil->translate (z2);
fr.add_stencil (*text_stil);
" object.",
/* properties */
+ "annotation-balloon "
+ "annotation-line "
"padding "
+ "spanner-to-annotate "
"text "
);
out->title_space_ = system_markup_space_;
out->inverse_hooke_ = out->full_height () + system_system_space_;
+ out->footnotes_ = sys->get_footnotes_in_range (start_rank, end_rank);
+
out->refpoint_extent_ = sys->pure_refpoint_extent (start_rank, end_rank);
if (out->refpoint_extent_.is_empty ())
out->refpoint_extent_ = Interval (0, 0);
Page_layout_problem::read_spacing_spec (spec, &min_distance_, ly_symbol2scm ("minimum-distance"));
Page_layout_problem::read_spacing_spec (title_spec, &title_min_distance_, ly_symbol2scm ("minimum-distance"));
+ SCM footnotes = pb->get_property ("footnotes");
+ if (scm_is_pair (footnotes))
+ for (SCM s = footnotes; scm_is_pair (s); s = scm_cdr (s))
+ footnotes_.push_back (unsmob_stencil (scm_car (s)));
+
last_column_ = 0;
force_ = 0;
Interval stencil_extent = unsmob_stencil (pb->get_property ("stencil"))->extent (Y_AXIS);
DECLARE_TRANSLATOR_LISTENER (break_span);
DECLARE_ACKNOWLEDGER (note_column);
DECLARE_ACKNOWLEDGER (dynamic);
+ DECLARE_ACKNOWLEDGER (footnote_spanner);
DECLARE_END_ACKNOWLEDGER (dynamic);
protected:
ADD_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
ADD_ACKNOWLEDGER (Dynamic_align_engraver, note_column);
+ADD_ACKNOWLEDGER (Dynamic_align_engraver, footnote_spanner);
ADD_END_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
void
ended_.push_back (info.spanner ());
}
+void
+Dynamic_align_engraver::acknowledge_footnote_spanner (Grob_info info)
+{
+ Grob *parent = unsmob_grob (info.grob ()->get_property ("parent-spanner"));
+ if (line_ && parent
+ && parent->internal_has_interface (ly_symbol2scm ("dynamic-interface"))
+ && (scm_to_int (line_->get_property ("direction"))
+ * robust_scm2double (info.grob ()->get_property ("Y-offset"), 0.0) > 0.0)) {
+ Axis_group_interface::add_element (line_, info.grob ());message ("ADD"); }
+}
+
void
Dynamic_align_engraver::acknowledge_note_column (Grob_info info)
{
Grob *last_column_;
Real force_;
Line_shape shape_;
+ vector<Stencil *> footnotes_;
Interval refpoint_extent_; /* The refpoints of the first and last
spaceable staff in this line. min-distance
should be measured from the bottom
Real page_height (int page_number, bool last) const;
Real paper_height () const;
vsize system_count () const;
+ Real footnote_separator_stencil_height () const;
+ Real footnote_padding () const;
Real line_count_penalty (int line_count) const;
int line_count_status (int line_count) const;
bool too_many_lines (int line_count) const;
void break_into_pieces (vsize start, vsize end, Line_division const &div);
SCM systems ();
+ SCM footnotes ();
void set_current_breakpoints (vsize start,
vsize end,
int max_systems_per_page_;
int min_systems_per_page_;
vsize system_count_;
+ Real footnote_separator_stencil_height_;
+ Real footnote_padding_;
int orphan_penalty_;
vector<Line_division> current_configurations_;
static bool read_spacing_spec (SCM spec, Real* dest, SCM sym);
static bool is_spaceable (Grob *g);
static SCM get_details (Grob *g);
+ static SCM get_footnotes_from_lines (SCM lines, Real padding);
+ static Stencil* get_footnote_separator_stencil (Output_def *paper);
static SCM get_spacing_spec (Grob *before, Grob *after, bool pure, int start, int end);
static Real get_fixed_spacing (Grob *before, Grob *after, int spaceable_index, bool pure, int start, int end);
+ static void add_footnotes_to_footer (SCM footnotes, Stencil *foot, Paper_book *pb);
protected:
void append_system (System*, Spring const&, Real indent, Real padding);
Real rod_height_;
Real spring_len_;
Real inverse_spring_k_;
+ bool has_footnotes_;
Line_details last_line_;
Line_details first_line_;
{
page_height_ = page_height;
breaker_ = breaker;
+ has_footnotes_ = false;
clear ();
}
void calc_force ();
void resize (Real new_height);
+ Real account_for_footnotes (Line_details const &line);
void append_system (const Line_details &line);
void prepend_system (const Line_details &line);
void clear ();
*/
Prob *make_paper_system (SCM immutable_init);
void paper_system_set_stencil (Prob *prob, Stencil s);
+SCM get_footnotes (SCM expr);
#endif /* PAPER_SYSTEM_HH */
void init_elements ();
friend class Paper_score; // ugh.
Paper_score *pscore_; // ugh.
-
+ vector<Grob *> footnote_grobs_;
+
public:
Paper_score *paper_score () const;
+ vector<Stencil *> footnotes_;
Grob *get_vertical_alignment ();
Grob *get_extremal_staff (Direction dir, Interval const&);
Grob *get_pure_bound (Direction dir, int start, int end);
Grob *get_maybe_pure_bound (Direction dir, bool pure, int start, int end);
int get_rank () const;
+ vector<Stencil *> get_footnotes_in_range (vsize st, vsize end);
+ Stencil make_footnote_stencil (Real padding);
void do_break_substitution_and_fixup_refpoints ();
void post_processing ();
+ void populate_footnote_grob_vector ();
SCM get_paper_system ();
SCM get_paper_systems ();
SCM get_broken_system_grobs ();
+ SCM get_broken_footnote_stencils ();
DECLARE_SCHEME_CALLBACK (calc_pure_relevant_grobs, (SCM));
DECLARE_SCHEME_CALLBACK (height, (SCM));
#include "international.hh"
#include "item.hh"
+#include "line-interface.hh"
#include "output-def.hh"
#include "page-layout-problem.hh"
#include "page-spacing.hh"
#include "paper-book.hh"
#include "paper-score.hh"
#include "paper-system.hh"
+#include "text-interface.hh"
#include "system.hh"
#include "warn.hh"
// compressed.title_ is true if and only if the first of its
// compressed lines was a title.
- compressed.title_ = old.title_;
+ compressed.title_ = old.title_;
+
+ // take care of footnotes
+ compressed.footnotes_.insert (compressed.footnotes_.begin (),
+ old.footnotes_.begin (), old.footnotes_.end ());
+
ret.back () = compressed;
}
else
min_systems_per_page_ = max (0, robust_scm2int (pb->paper_->c_variable ("min-systems-per-page"), 0));
orphan_penalty_ = robust_scm2int (pb->paper_->c_variable ("orphan-penalty"), 100000);
+ Stencil *footnote_separator = Page_layout_problem::get_footnote_separator_stencil (pb->paper_);
+
+ if (footnote_separator)
+ {
+ Interval separator_extent = footnote_separator->extent (Y_AXIS);
+ Real separator_span = max (separator_extent[UP] - separator_extent[DOWN], 0.0);
+
+ footnote_separator_stencil_height_ = separator_span;
+ }
+ else
+ footnote_separator_stencil_height_ = 0.0;
+
+ footnote_padding_ = robust_scm2double (pb->paper_->c_variable ("footnote-padding"), 0.0);
+
if (systems_per_page_ && (max_systems_per_page_ || min_systems_per_page_))
{
warning (_f ("ignoring min-systems-per-page and max-systems-per-page because systems-per-page was set"));
return system_count_;
}
+Real
+Page_breaking::footnote_separator_stencil_height () const
+{
+ return footnote_separator_stencil_height_;
+}
+
+Real
+Page_breaking::footnote_padding () const
+{
+ return footnote_padding_;
+}
+
bool
Page_breaking::too_many_lines (int line_count) const
{
Prob *p = unsmob_prob (page);
p->set_property ("lines", paper_systems);
p->set_property ("configuration", configuration);
+
+ Stencil *foot = unsmob_stencil (p->get_property ("foot-stencil"));
+ SCM footnotes = Page_layout_problem::get_footnotes_from_lines (systems, footnote_padding ());
+ Page_layout_problem::add_footnotes_to_footer (footnotes, foot, unsmob_paper_book (p->get_property ("paper-book")));
+
+ p->set_property ("foot-stencil", foot->smobbed_copy ());
scm_apply_1 (page_stencil, page, SCM_EOL);
return page;
{
SCM lines = scm_caar (s);
SCM config = scm_cdar (s);
+
bool bookpart_last_page = (s == systems_and_configs);
SCM page = draw_page (lines, config, page_num, bookpart_last_page);
#include "prob.hh"
#include "skyline-pair.hh"
#include "system.hh"
+#include "text-interface.hh"
+
+SCM
+Page_layout_problem::get_footnotes_from_lines (SCM lines, Real padding)
+{
+ SCM footnotes = SCM_EOL;
+ // ugh...code dup
+ for (SCM s = lines; scm_is_pair (s); s = scm_cdr (s))
+ {
+ if (Grob *g = unsmob_grob (scm_car (s)))
+ {
+ System *sys = dynamic_cast<System *> (g);
+ if (!sys)
+ {
+ programming_error ("got a grob for footnotes that wasn't a System");
+ continue;
+ }
+ footnotes = scm_cons (sys->make_footnote_stencil (padding).smobbed_copy (), footnotes);
+ }
+ else if (Prob *p = unsmob_prob (scm_car (s)))
+ {
+ SCM stencils = p->get_property ("footnotes");
+ if (stencils == SCM_EOL)
+ continue;
+ Stencil footnote_stencil;
+
+ for (SCM st = stencils; scm_is_pair (st); st = scm_cdr (st))
+ footnote_stencil.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (scm_car (st)), padding);
+ footnotes = scm_cons (footnote_stencil.smobbed_copy (), footnotes);
+ }
+ }
+
+ if (!scm_is_pair (footnotes))
+ return SCM_EOL;
+
+ return scm_reverse (footnotes);
+}
+
+Stencil*
+Page_layout_problem::get_footnote_separator_stencil (Output_def *paper)
+{
+ SCM props = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"),
+ paper->self_scm ());
+
+ SCM markup = paper->c_variable ("footnote-separator-markup");
+
+ if (!Text_interface::is_markup (markup))
+ return NULL;
+
+ SCM footnote_stencil = Text_interface::interpret_markup (paper->self_scm (),
+ props, markup);
+
+ Stencil *footnote_separator = unsmob_stencil (footnote_stencil);
+
+ return footnote_separator;
+}
+
+void
+Page_layout_problem::add_footnotes_to_footer (SCM footnotes, Stencil *foot, Paper_book *pb)
+{
+ bool are_footnotes = false;
+ Real footnote_padding = robust_scm2double (pb->paper_->c_variable ("footnote-padding"), 0.0);
+
+ footnotes = scm_reverse (footnotes);
+ for (SCM s = footnotes; scm_is_pair (s); s = scm_cdr (s))
+ {
+ if (scm_car (s) == SCM_EOL)
+ continue;
+ Stencil *stencil = unsmob_stencil (scm_car (s));
+ if (stencil->extent (Y_AXIS).length() > 0.0)
+ {
+ foot->add_at_edge (Y_AXIS, UP, *stencil, footnote_padding);
+ are_footnotes = true;
+ }
+ }
+
+ if (are_footnotes)
+ {
+ Stencil *separator = get_footnote_separator_stencil (pb->paper_);
+ if (separator)
+ foot->add_at_edge (Y_AXIS, UP, *separator, footnote_padding);
+ }
+}
Page_layout_problem::Page_layout_problem (Paper_book *pb, SCM page_scm, SCM systems)
: bottom_skyline_ (DOWN)
{
Stencil *head = unsmob_stencil (page->get_property ("head-stencil"));
Stencil *foot = unsmob_stencil (page->get_property ("foot-stencil"));
-
+
+ Real footnote_padding = 0.0;
+ if (pb && pb->paper_)
+ footnote_padding = robust_scm2double (pb->paper_->c_variable ("footnote-padding"), 0.0);
+ SCM footnotes = get_footnotes_from_lines (systems, footnote_padding);
+ add_footnotes_to_footer (footnotes, foot, pb);
+
header_height_ = head ? head->extent (Y_AXIS).length () : 0;
footer_height_ = foot ? foot->extent (Y_AXIS).length () : 0;
page_height_ = robust_scm2double (page->get_property ("paper-height"), 100);
#include "page-spacing.hh"
+#include "international.hh"
#include "matrix.hh"
#include "page-breaking.hh"
#include "warn.hh"
first_line_ = line;
}
+ rod_height_ += account_for_footnotes (line);
inverse_spring_k_ += line.inverse_hooke_;
last_line_ = line;
calc_force ();
}
+Real
+Page_spacing::account_for_footnotes (Line_details const &line)
+{
+ Real footnote_height = 0.0;
+ for (vsize i = 0; i < line.footnotes_.size (); i++)
+ {
+ footnote_height += (has_footnotes_
+ ? 0.0
+ : (breaker_->footnote_separator_stencil_height ()
+ + breaker_->footnote_padding ()));
+
+ has_footnotes_ = true;
+ Interval extent = line.footnotes_[i]->extent (Y_AXIS);
+ footnote_height += extent[UP] - extent[DOWN];
+ footnote_height += breaker_->footnote_padding ();
+ }
+ return footnote_height;
+}
+
void
Page_spacing::prepend_system (const Line_details &line)
{
rod_height_ -= first_line_.full_height ();
rod_height_ += first_line_.tallness_;
rod_height_ += line.full_height();
-
+ rod_height_ += account_for_footnotes (line);
inverse_spring_k_ += line.inverse_hooke_;
first_line_ = line;
{
force_ = rod_height_ = spring_len_ = 0;
inverse_spring_k_ = 0;
+ has_footnotes_ = false;
}
list == texts? SCM_BOOL_T : SCM_BOOL_F);
paper_system_set_stencil (ps, *unsmob_stencil (t));
+
+ SCM footnotes = get_footnotes (unsmob_stencil (t)->expr ());
+ ps->set_property ("footnotes", scm_reverse (footnotes));
ps->set_property ("is-title", SCM_BOOL_T);
if (list != texts)
/* For each markup other than the first, place it as closely as
return prob;
}
+SCM
+get_footnotes (SCM expr)
+{
+ if (!scm_is_pair (expr))
+ return SCM_EOL;
+
+ SCM head = scm_car (expr);
+
+ if (head == ly_symbol2scm ("delay-stencil-evaluation"))
+ {
+ // we likely need to do something here...just don't know what...
+ return SCM_EOL;
+ }
+
+ if (head == ly_symbol2scm ("combine-stencil"))
+ {
+ SCM out = SCM_EOL;
+ for (SCM x = scm_cdr (expr); scm_is_pair (x); x = scm_cdr (x))
+ {
+ SCM footnote = get_footnotes (scm_car (x));
+ if (scm_is_pair (footnote))
+ {
+ for (SCM y = scm_reverse (footnote); scm_is_pair (y); y = scm_cdr (y))
+ out = scm_cons (scm_car (y), out);
+ }
+ else if (SCM_EOL != footnote)
+ out = scm_cons (footnote, out);
+ }
+ return out;
+ }
+ if (head == ly_symbol2scm ("translate-stencil"))
+ return get_footnotes (scm_caddr (expr));
+
+ if (head == ly_symbol2scm ("footnote"))
+ return scm_cadr (expr);
+
+ return SCM_EOL;
+}
+
+
void
paper_system_set_stencil (Prob *prob, Stencil s)
{
interpret_stencil_expression (scm_force (scm_cadr (expr)), func, func_arg, o);
return;
}
+ if (head == ly_symbol2scm ("footnote"))
+ return;
if (head == ly_symbol2scm ("translate-stencil"))
{
o += ly_scm2offset (scm_cadr (expr));
#include "pointer-group-interface.hh"
#include "skyline-pair.hh"
#include "staff-symbol-referencer.hh"
+#include "text-interface.hh"
#include "warn.hh"
System::System (System const &src)
Grob *g = all_elts[j];
g->fixup_refpoint ();
}
-
+
count += all_elts.size ();
}
return lines;
}
+void
+System::populate_footnote_grob_vector ()
+{
+ extract_grob_set (this, "all-elements", all_elts);
+ for (vsize i = 0; i < all_elts.size (); i++)
+ {
+ if ((all_elts[i]->name () == "Footnote") || (all_elts[i]->name () == "FootnoteSpanner"))
+ footnote_grobs_.push_back (all_elts[i]);
+ }
+ sort (footnote_grobs_.begin (), footnote_grobs_.end (), Grob::less);
+
+}
+
+vector<Stencil *>
+System::get_footnotes_in_range (vsize st, vsize end)
+{
+ vector<Stencil *> out;
+ if (footnote_grobs_.size () == 0)
+ populate_footnote_grob_vector ();
+
+ for (vsize j = 0; j < footnote_grobs_.size (); j++)
+ {
+ if (footnote_grobs_[j]->spanned_rank_interval ()[LEFT] < (int)st)
+ continue;
+ if (footnote_grobs_[j]->spanned_rank_interval ()[LEFT] >= (int)end)
+ break;
+ SCM footnote_markup = footnote_grobs_[j]->get_property ("footnote-text");
+
+ if (!Text_interface::is_markup (footnote_markup))
+ continue;
+
+ SCM props = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"),
+ pscore_->layout ()->self_scm ());
+
+ SCM footnote_stl = Text_interface::interpret_markup (pscore_->layout ()->self_scm (),
+ props, footnote_markup);
+
+ Stencil *footnote_stencil = unsmob_stencil (footnote_stl);
+ out.push_back (footnote_stencil);
+ }
+
+ return out;
+}
+
+Stencil
+System::make_footnote_stencil (Real padding)
+{
+ Stencil mol;
+
+ for (vsize i = 0; i < footnotes_.size (); i++)
+ mol.add_at_edge (Y_AXIS, DOWN, *footnotes_[i], padding);
+
+ return mol;
+}
+
void
System::break_into_pieces (vector<Column_x_positions> const &breaking)
{
Interval iv (pure_height (this, st, end));
system->set_property ("pure-Y-extent", ly_interval2scm (iv));
+ system->footnotes_ = get_footnotes_in_range (st, end);
+
system->set_bound (LEFT, c[0]);
system->set_bound (RIGHT, c.back ());
SCM system_labels = SCM_EOL;
\consists "Stanza_number_align_engraver"
\consists "Bar_number_engraver"
\consists "Parenthesis_engraver"
+ \consists "Footnote_engraver"
\defaultchild "Staff"
argument))
-
+footnoteGrob =
+#(define-music-function (parser location grob-name offset text footnote)
+ (symbol? number-pair? markup? markup?)
+ (_i "Attach @var{text} to @var{grob-name} at offset @var{offset},
+ with @var{text} referring to @var{footnote} (use like @code{\\once})")
+ (make-music 'FootnoteEvent
+ 'symbol grob-name
+ 'X-offset (car offset)
+ 'Y-offset (cdr offset)
+ 'text text
+ 'footnote-text footnote))
+
+footnote =
+#(define-music-function (parser location offset text footnote)
+ (number-pair? markup? markup?)
+ (_i "Attach @var{text} at @var{offset} with @var{text} referring
+ to @var{footnote} (use like @code{\\tweak})")
+ (make-music 'FootnoteEvent
+ 'X-offset (car offset)
+ 'Y-offset (cdr offset)
+ 'text text
+ 'footnote-text footnote))
grace =
#(def-grace-function startGraceMusic stopGraceMusic
ragged-bottom = ##f
ragged-last-bottom = ##t % best for shorter scores
-
%%
%% Flexible vertical spacing
%%
page-breaking = #ly:optimal-breaking
+ %%
+ %% Footnotes
+ %%
+ footnote-separator-markup = \markup { \draw-hline }
+ footnote-padding = 0.5\mm
+
+
%%
%% Page numbering
%%
print-first-page-number = ##f
print-page-number = ##t
-
%%
%% Headers, footers, and titles
%%
(RemoveContext ChangeParent Override Revert UnsetProperty
SetProperty music-event OldMusicEvent CreateContext Prepare
OneTimeStep Finish))
- (music-event . (annotate-output-event
+ (music-event . (annotate-output-event footnote-event
arpeggio-event breathing-event extender-event span-event
rhythmic-event dynamic-event break-event label-event percent-event
key-change-event string-number-event stroke-finger-event tie-event
"A fingering instruction."
'())
+(ly:add-interface
+ 'footnote-interface
+ "Make a footnote."
+ '(footnote-text))
+
+(ly:add-interface
+ 'footnote-spanner-interface
+ "Make a footnote spanner."
+ '(footnote-text))
+
(ly:add-interface
'fret-diagram-interface
"A fret diagram"
(alteration-alist ,list? "List of @code{(@var{pitch}
. @var{accidental})} pairs for key signature.")
(annotation ,string? "Annotate a grob for debug purposes.")
+ (annotation-balloon ,boolean? "Draw a balloon around an annotation.")
+ (annotation-line ,boolean? "Draw a line from an annotation.")
(arpeggio-direction ,ly:dir? "If set, put an arrow on the
arpeggio squiggly line.")
(arrow-length ,number? "Arrow length.")
@code{-1} is smaller, @code{+1} is bigger. Each step of@tie{}1 is
approximately 12% larger; 6@tie{}steps are exactly a factor@tie{}2
larger. Fractional values are allowed.")
+ (footnote-text ,markup? "A footnote for the grob.")
(force-hshift ,number? "This specifies a manual shift for notes
in collisions. The unit is the note head width of the first voice
note. This is used by @rinternals{note-collision-interface}.")
elements closer together.")
(slope ,number? "The slope of this object.")
(slur-padding ,number? "Extra distance between slur and script.")
+ (spanner-to-annotate ,integer? "The number of a spanner in a
+spanner's broken spanner list to annotate. Values less than 0 or
+greater than the number of broken spanners will be wrapped modulo the
+number of spanners.")
(space-alist ,list? "A table that specifies distances between
prefatory items, like clef and time-signature. The format is an alist
of spacing tuples: @code{(@var{break-align-symbol} @var{type}
(BalloonTextItem
. (
+ (annotation-balloon . #t)
+ (annotation-line . #t)
(stencil . ,ly:balloon-interface::print)
(text . ,(grob::calc-property-by-copy 'text))
(X-offset . ,(grob::calc-property-by-copy 'X-offset))
text-interface
text-script-interface))))))
+ (Footnote
+ . (
+ (annotation-balloon . #f)
+ (annotation-line . #t)
+ (stencil . ,ly:balloon-interface::print)
+ (text . ,(grob::calc-property-by-copy 'text))
+ (X-offset . ,(grob::calc-property-by-copy 'X-offset))
+ (Y-offset . ,(grob::calc-property-by-copy 'Y-offset))
+ (meta . ((class . Item)
+ (interfaces . (balloon-interface
+ footnote-interface
+ font-interface
+ text-interface))))))
+
+ (FootnoteSpanner
+ . (
+ (annotation-balloon . #f)
+ (annotation-line . #t)
+ (footnote-text . #f)
+ (stencil . ,ly:balloon-interface::print-spanner)
+ (text . ,(grob::calc-property-by-copy 'text))
+ (X-offset . ,(grob::calc-property-by-copy 'X-offset))
+ (Y-offset . ,(grob::calc-property-by-copy 'Y-offset))
+ (meta . ((class . Spanner)
+ (interfaces . (balloon-interface
+ footnote-spanner-interface
+ font-interface
+ text-interface))))))
+
(FretBoard
. (
(after-line-breaking . ,ly:chord-name::after-line-breaking)
(y (cdr dest)))
(make-line-stencil th 0 0 x y)))
+(define-markup-command (draw-hline layout props)
+ ()
+ #:category graphic
+ #:properties ((thickness 1))
+ "
+@cindex drawing a line across a page
+
+Draws a line across a page.
+@lilypond[verbatim,quote]
+\\markup {
+ \\draw-hline
+}
+@end lilypond"
+ (let ((th (* (ly:output-def-lookup layout 'line-thickness)
+ thickness))
+ (x (ly:output-def-lookup layout 'line-width))
+ (y 0.0))
+ (make-line-stencil th 0 0 x y)))
+
(define-markup-command (draw-circle layout props radius thickness filled)
(number? number? boolean?)
#:category graphic
(list markup?))
(interpret-markup layout props (list anonymous-with-signature arg))))
+(define-markup-command (footnote layout props arg1 arg2)
+ (markup? markup?)
+ #:category other
+ "Apply the footnote @var{arg2} to @var{arg1}."
+ (ly:stencil-combine-at-edge
+ (interpret-markup layout props arg1)
+ X
+ RIGHT
+ (ly:make-stencil
+ `(footnote ,(interpret-markup layout props arg2))
+ '(0 . 0)
+ '(0 . 0))
+ 0.0))
+
(define-markup-command (override layout props new-prop arg)
(pair? markup?)
#:category other
(types . (general-music fingering-event event))
))
+ (FootnoteEvent
+ . ((description . "Footnote a grob.")
+ (types . (general-music event footnote-event))
+ ))
+
(GlissandoEvent
. ((description . "Start a glissando on this note.")
(types . (general-music glissando-event event))
ellipse
embedded-ps
embedded-svg
+ footnote
glyph-string
grob-cause
named-glyph