From: Mike Solomon Date: Wed, 2 Nov 2011 13:26:56 +0000 (+0100) Subject: Adds in-notes to LilyPond. X-Git-Tag: release/2.15.17-1~25 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=dcd022fe1212a4a439539c22c1a8f90788e5d050;hp=37bd2b54bdfaa3693f6aa3f43f9072cc9cfacc21;p=lilypond.git Adds in-notes to LilyPond. In notes function like footnotes in that they serve to annotate music, but are different in that they are typeset either above or below the system to which the grob being annotated belongs. Currently, in-notes are not implemented in top-level markups. This will hopefully be the subject of a future patch. This patch also does some clean up in page-breaking.cc and page-layout-problem.cc to speed up the performance of scores with in-notes and/or footnotes. --- diff --git a/input/regression/footnote-break-visibility.ly b/input/regression/footnote-break-visibility.ly index 23e9035a71..c23d5d6d2b 100644 --- a/input/regression/footnote-break-visibility.ly +++ b/input/regression/footnote-break-visibility.ly @@ -1,8 +1,9 @@ -\version "2.14.0" +\version "2.15.17" \header { texidoc = "With grobs that have break visibility, footnotes will -automatically print to the first line of the break. This behavior -can be overrided." +automatically take the break visibility of the grob being footnoted. +This behavior can be overridden. +" } #(set-default-paper-size "a6") diff --git a/input/regression/in-note.ly b/input/regression/in-note.ly new file mode 100644 index 0000000000..1d08d5c12c --- /dev/null +++ b/input/regression/in-note.ly @@ -0,0 +1,20 @@ +\version "2.15.17" + +\header { + texidoc = "LilyPond does in-notes. +" +} + +#(set-default-paper-size "a6") +\book { + \relative c' { + \repeat unfold 5 { + \once \override FootnoteItem #'footnote = ##f + \footnoteGrob #'NoteHead #'(0 . 0) + "" \markup { \box \fill-line { "this is a test" } } + \repeat unfold 5 { a\< b c d\! } + \autoFootnoteGrob #'NoteHead #'(-1 . 1) "foobar" + \repeat unfold 5 { a\< b c d\! } + } + } +} diff --git a/lily/align-interface.cc b/lily/align-interface.cc index 44c30e6013..00ea0029e3 100644 --- a/lily/align-interface.cc +++ b/lily/align-interface.cc @@ -290,7 +290,7 @@ Align_interface::align_elements_to_ideal_distances (Grob *me) System *sys = me->get_system (); if (sys) { - Page_layout_problem layout (NULL, SCM_EOL, scm_list_1 (sys->self_scm ()), 0); + Page_layout_problem layout (NULL, SCM_EOL, scm_list_1 (sys->self_scm ())); layout.solution (true); } else diff --git a/lily/constrained-breaking.cc b/lily/constrained-breaking.cc index d269cff485..1e7fe96c51 100644 --- a/lily/constrained-breaking.cc +++ b/lily/constrained-breaking.cc @@ -517,7 +517,8 @@ Constrained_breaking::fill_line_details (Line_details *const out, vsize start, v 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->footnote_heights_ = sys->get_footnote_heights_in_range (start_rank, end_rank); + out->in_note_heights_ = sys->get_in_note_heights_in_range (start_rank, end_rank); out->refpoint_extent_ = sys->pure_refpoint_extent (start_rank, end_rank); if (out->refpoint_extent_.is_empty ()) @@ -554,7 +555,15 @@ Line_details::Line_details (Prob *pb, Output_def *paper) if (scm_is_pair (footnotes)) for (SCM s = footnotes; scm_is_pair (s); s = scm_cdr (s)) - footnotes_.push_back (unsmob_stencil (scm_caddar (s))); + { + Stencil *sten = unsmob_stencil (scm_caddar (s)); + if (!sten) + { + programming_error ("expecting stencil, got empty pointer"); + continue; + } + footnote_heights_.push_back (sten->extent (Y_AXIS).length ()); + } last_column_ = 0; force_ = 0; diff --git a/lily/include/constrained-breaking.hh b/lily/include/constrained-breaking.hh index 1887d87273..e540487971 100644 --- a/lily/include/constrained-breaking.hh +++ b/lily/include/constrained-breaking.hh @@ -45,9 +45,12 @@ struct Line_details Grob *last_column_; Real force_; Line_shape shape_; - vector footnotes_; /* The footnotes at the bottom of the + vector footnote_heights_; /* The footnotes at the bottom of the page, where each stencil represents a different footnote. */ + vector in_note_heights_; /* The in-notes under a system, + where each stencil represents + a different in-note. */ Interval refpoint_extent_; /* The refpoints of the first and last spaceable staff in this line. min-distance should be measured from the bottom diff --git a/lily/include/page-breaking.hh b/lily/include/page-breaking.hh index 7d50db2524..eb2fe5370d 100644 --- a/lily/include/page-breaking.hh +++ b/lily/include/page-breaking.hh @@ -126,6 +126,7 @@ public: vsize system_count () const; Real footnote_separator_stencil_height () const; Real footnote_padding () const; + Real in_note_padding () const; Real footnote_number_raise () const; Real footnote_footer_padding () const; Real line_count_penalty (int line_count) const; @@ -190,6 +191,7 @@ private: vsize system_count_; Real footnote_separator_stencil_height_; Real footnote_padding_; + Real in_note_padding_; Real footnote_number_raise_; Real footnote_footer_padding_; int orphan_penalty_; @@ -230,7 +232,7 @@ private: void create_system_list (); void find_chunks_and_breaks (Break_predicate, Prob_break_predicate); SCM make_page (int page_num, bool last) const; - SCM get_page_configuration (SCM systems, int page_num, int footnote_count, bool ragged, bool last); - SCM draw_page (SCM systems, SCM config, int page_num, int footnote_num, bool last); + SCM get_page_configuration (SCM systems, int page_num, bool ragged, bool last); + SCM draw_page (SCM systems, SCM config, int page_num, bool last); }; #endif /* PAGE_BREAKING_HH */ diff --git a/lily/include/page-layout-problem.hh b/lily/include/page-layout-problem.hh index 6c952e3eed..665f15396b 100644 --- a/lily/include/page-layout-problem.hh +++ b/lily/include/page-layout-problem.hh @@ -26,7 +26,7 @@ class Page_layout_problem { public: - Page_layout_problem (Paper_book *, SCM page, SCM systems, int footnote_count); + Page_layout_problem (Paper_book *, SCM page, SCM systems); SCM solution (bool ragged); void set_header_height (Real); @@ -35,7 +35,8 @@ public: static bool is_spaceable (Grob *g); static SCM get_details (Grob *g); static vsize get_footnote_count (SCM lines); - static SCM get_footnotes_from_lines (SCM lines, int counter, Paper_book *pb); + static SCM get_footnotes_from_lines (SCM lines); + static void add_footnotes_to_lines (SCM lines, int counter, Paper_book *pb); 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); @@ -95,6 +96,8 @@ protected: Real footer_height_; Real header_padding_; Real footer_padding_; + Real in_note_padding_; + Direction in_note_direction_; }; #endif /* PAGE_LAYOUT_HH */ diff --git a/lily/include/system.hh b/lily/include/system.hh index 4a3c3c1b48..f002d72c0f 100644 --- a/lily/include/system.hh +++ b/lily/include/system.hh @@ -46,7 +46,9 @@ public: 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 get_footnotes_in_range (vsize st, vsize end); + vector get_footnote_heights_in_range (vsize st, vsize end); + vector get_in_note_heights_in_range (vsize st, vsize end); + vector internal_get_note_heights_in_range (vsize st, vsize end, bool foot); void get_footnote_grobs_in_range (vector &out, vsize st, vsize end); vector *footnote_grobs (); vsize num_footnotes (); diff --git a/lily/page-breaking.cc b/lily/page-breaking.cc index c46a04efa5..01d7469f52 100644 --- a/lily/page-breaking.cc +++ b/lily/page-breaking.cc @@ -183,8 +183,12 @@ compress_lines (const vector &orig) compressed.title_ = old.title_; // adds footnotes of one line to the footnotes of another - compressed.footnotes_.insert (compressed.footnotes_.begin (), - old.footnotes_.begin (), old.footnotes_.end ()); + compressed.footnote_heights_.insert (compressed.footnote_heights_.begin (), + old.footnote_heights_.begin (), + old.footnote_heights_.end ()); + compressed.in_note_heights_.insert (compressed.in_note_heights_.begin (), + old.in_note_heights_.begin (), + old.in_note_heights_.end ()); ret.back () = compressed; } @@ -263,6 +267,7 @@ Page_breaking::Page_breaking (Paper_book *pb, Break_predicate is_break, Prob_bre footnote_separator_stencil_height_ = 0.0; footnote_padding_ = robust_scm2double (pb->paper_->c_variable ("footnote-padding"), 0.0); + in_note_padding_ = robust_scm2double (pb->paper_->c_variable ("in-note-padding"), 0.0); footnote_footer_padding_ = robust_scm2double (pb->paper_->c_variable ("footnote-footer-padding"), 0.0); footnote_number_raise_ = robust_scm2double (pb->paper_->c_variable ("footnote-number-raise"), 0.0); @@ -332,6 +337,12 @@ Page_breaking::footnote_separator_stencil_height () const return footnote_separator_stencil_height_; } +Real +Page_breaking::in_note_padding () const +{ + return in_note_padding_; +} + Real Page_breaking::footnote_padding () const { @@ -529,15 +540,15 @@ Page_breaking::breakpoint_property (vsize breakpoint, char const *str) } SCM -Page_breaking::get_page_configuration (SCM systems, int page_num, int footnote_count, bool ragged, bool last) +Page_breaking::get_page_configuration (SCM systems, int page_num, bool ragged, bool last) { SCM dummy_page = make_page (page_num, last); - Page_layout_problem layout (book_, dummy_page, systems, footnote_count); + Page_layout_problem layout (book_, dummy_page, systems); return scm_is_pair (systems) ? layout.solution (ragged) : SCM_EOL; } SCM -Page_breaking::draw_page (SCM systems, SCM configuration, int page_num, int footnote_num, bool last) +Page_breaking::draw_page (SCM systems, SCM configuration, int page_num, bool last) { // Create a stencil for each system. SCM paper_systems = SCM_EOL; @@ -565,13 +576,7 @@ Page_breaking::draw_page (SCM systems, SCM configuration, int page_num, int foot Stencil *foot = unsmob_stencil (p->get_property ("foot-stencil")); - footnote_num = (to_boolean (book_->paper_->c_variable ("reset-footnotes-on-new-page")) - ? 0 - : footnote_num); - - SCM footnotes = Page_layout_problem::get_footnotes_from_lines (systems, - footnote_num, - book_); + SCM footnotes = Page_layout_problem::get_footnotes_from_lines (systems); Page_layout_problem::add_footnotes_to_footer (footnotes, foot, book_); @@ -591,6 +596,7 @@ Page_breaking::make_pages (vector lines_per_page, SCM systems) int first_page_number = robust_scm2int (book_->paper_->c_variable ("first-page-number"), 1); SCM ret = SCM_EOL; + bool reset_footnotes_on_new_page = to_boolean (book_->top_paper ()->c_variable ("reset-footnotes-on-new-page")); SCM label_page_table = book_->top_paper ()->c_variable ("label-page-table"); if (label_page_table == SCM_UNDEFINED) label_page_table = SCM_EOL; @@ -612,9 +618,11 @@ Page_breaking::make_pages (vector lines_per_page, SCM systems) SCM line_count = scm_from_int (lines_per_page[i]); SCM lines = scm_list_head (systems, line_count); int fn_lines = Page_layout_problem::get_footnote_count (lines); - SCM config = get_page_configuration (lines, page_num, footnote_count, rag, bookpart_last_page); + Page_layout_problem::add_footnotes_to_lines (lines, reset_footnotes_on_new_page ? 0 : footnote_count, book_); + + SCM config = get_page_configuration (lines, page_num, rag, bookpart_last_page); - systems_configs_fncounts = scm_cons (scm_list_3 (lines, config, scm_from_int ((int)footnote_count)), systems_configs_fncounts); + systems_configs_fncounts = scm_cons (scm_cons (lines, config), systems_configs_fncounts); footnote_count += fn_lines; systems = scm_list_tail (systems, line_count); } @@ -624,11 +632,10 @@ Page_breaking::make_pages (vector lines_per_page, SCM systems) for (SCM s = systems_configs_fncounts; scm_is_pair (s); s = scm_cdr (s)) { SCM lines = scm_caar (s); - SCM config = scm_cadar (s); - int footnote_num = scm_to_int (scm_caddar (s)); + SCM config = scm_cdar (s); bool bookpart_last_page = (s == systems_configs_fncounts); - SCM page = draw_page (lines, config, page_num, footnote_num, bookpart_last_page); + SCM page = draw_page (lines, config, page_num, bookpart_last_page); /* collect labels */ SCM page_num_scm = scm_from_int (page_num); for (SCM l = lines; scm_is_pair (l); l = scm_cdr (l)) diff --git a/lily/page-layout-problem.cc b/lily/page-layout-problem.cc index 82c0dc7181..562f0aeb90 100644 --- a/lily/page-layout-problem.cc +++ b/lily/page-layout-problem.cc @@ -67,16 +67,52 @@ Page_layout_problem::get_footnote_count (SCM lines) return fn_count; } +SCM +Page_layout_problem::get_footnotes_from_lines (SCM lines) +{ + if (!scm_is_pair (lines)) + return SCM_EOL; + + bool footnotes_added; + if (Grob *g = unsmob_grob (scm_car (lines))) + footnotes_added = !scm_is_null (g->get_property ("footnote-stencil")); + else if (Prob *p = unsmob_prob (scm_car (lines))) + footnotes_added = !scm_is_null (p->get_property ("footnote-stencil")); + else + { + programming_error ("Systems on a page must be a prob or grob."); + return SCM_EOL; + } + if (!footnotes_added) + { + programming_error ("Footnotes must be added to lines before they are retrieved."); + return SCM_EOL; + } + + SCM out = SCM_EOL; + for (SCM s = lines; scm_is_pair (s); s = scm_cdr (s)) + { + if (Grob *g = unsmob_grob (scm_car (s))) + out = scm_cons (g->get_property ("footnote-stencil"), out); + else if (Prob *p = unsmob_prob (scm_car (s))) + out = scm_cons (p->get_property ("footnote-stencil"), out); + else + programming_error ("Systems on a page must be a prob or grob."); + } + + return scm_reverse (out); +} + /* - Returns a stencil for the footnote of each system. This stencil may + Adds a footnote stencil to each system. This stencil may itself be comprised of several footnotes. This is a long function, but it seems better to keep it intact rather than splitting it into parts. */ -SCM -Page_layout_problem::get_footnotes_from_lines (SCM lines, int counter, Paper_book *pb) +void +Page_layout_problem::add_footnotes_to_lines (SCM lines, int counter, Paper_book *pb) { /* first, we have to see how many footnotes are on this page. @@ -88,7 +124,7 @@ Page_layout_problem::get_footnotes_from_lines (SCM lines, int counter, Paper_boo if (!paper) { programming_error ("Cannot get footnotes because there is no valid paper block."); - return SCM_EOL; + return; } SCM number_footnote_table = pb->top_paper ()->c_variable ("number-footnote-table"); @@ -149,14 +185,14 @@ Page_layout_problem::get_footnotes_from_lines (SCM lines, int counter, Paper_boo { *in_text_tail = scm_cons (footnote_number_markups[i], SCM_EOL); in_text_tail = SCM_CDRLOC (*in_text_tail); - footnote_number_stencils[i]->translate_axis (max_length - footnote_number_stencils[i]->extent (X_AXIS).length (), X_AXIS); + footnote_number_stencils[i]->translate_axis ((max_length + - footnote_number_stencils[i]->extent (X_AXIS).length ()), + X_AXIS); *tail = scm_cons (footnote_number_stencils[i]->smobbed_copy (), SCM_EOL); tail = SCM_CDRLOC (*tail); } // build the footnotes - SCM footnotes = SCM_EOL; - for (SCM s = lines; scm_is_pair (s); s = scm_cdr (s)) { // Take care of musical systems. @@ -169,7 +205,7 @@ Page_layout_problem::get_footnotes_from_lines (SCM lines, int counter, Paper_boo continue; } Stencil mol; - + Stencil in_note_mol; for (vsize i = 0; i < sys->footnote_grobs ()->size (); i++) { Grob *footnote = sys->footnote_grobs ()->at (i); @@ -178,9 +214,6 @@ Page_layout_problem::get_footnotes_from_lines (SCM lines, int counter, Paper_boo if (orig->is_broken ()) footnote_markup = orig->broken_intos_[0]->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"), paper->self_scm ()); @@ -193,7 +226,8 @@ Page_layout_problem::get_footnotes_from_lines (SCM lines, int counter, Paper_boo { if (orig->is_broken ()) for (vsize i = 0; i < orig->broken_intos_.size (); i++) - do_numbering = do_numbering || to_boolean (orig->broken_intos_[i]->get_property ("automatically-numbered")); + do_numbering = do_numbering + || to_boolean (orig->broken_intos_[i]->get_property ("automatically-numbered")); } if (do_numbering) { @@ -208,55 +242,67 @@ Page_layout_problem::get_footnotes_from_lines (SCM lines, int counter, Paper_boo } Stencil *annotation = unsmob_stencil (scm_car (numbers)); - annotation->translate_axis (footnote_stencil->extent (Y_AXIS)[UP] + number_raise - annotation->extent (Y_AXIS)[UP], Y_AXIS); + annotation->translate_axis ((footnote_stencil->extent (Y_AXIS)[UP] + + number_raise + - annotation->extent (Y_AXIS)[UP]), + Y_AXIS); footnote_stencil->add_at_edge (X_AXIS, LEFT, *annotation, 0.0); numbers = scm_cdr (numbers); in_text_numbers = scm_cdr (in_text_numbers); } - mol.add_at_edge (Y_AXIS, DOWN, *footnote_stencil, padding); + if (!footnote_stencil->is_empty ()) + { + if (to_boolean (footnote->get_property ("footnote"))) + mol.add_at_edge (Y_AXIS, DOWN, *footnote_stencil, padding); + else + in_note_mol.add_at_edge (Y_AXIS, DOWN, *footnote_stencil, padding); + } } - footnotes = scm_cons (mol.smobbed_copy (), footnotes); + sys->set_property ("in-note-stencil", in_note_mol.smobbed_copy ()); + sys->set_property ("footnote-stencil", mol.smobbed_copy ()); } // Take care of top-level markups else if (Prob *p = unsmob_prob (scm_car (s))) { SCM stencils = p->get_property ("footnotes"); - if (stencils == SCM_EOL) - continue; - Stencil footnote_stencil; + Stencil mol; for (SCM st = stencils; scm_is_pair (st); st = scm_cdr (st)) { - Stencil mol; + Stencil footnote_stencil; Stencil *footnote = unsmob_stencil (scm_caddar (st)); - mol.add_stencil (*footnote); + footnote_stencil.add_stencil (*footnote); bool do_numbering = to_boolean (scm_cadar (st)); SCM in_text_stencil = Stencil ().smobbed_copy (); if (do_numbering) { Stencil *annotation = unsmob_stencil (scm_car (numbers)); SCM in_text_annotation = scm_car (in_text_numbers); - in_text_stencil = Text_interface::interpret_markup (layout, props, in_text_annotation); + in_text_stencil = Text_interface::interpret_markup (layout, + props, + in_text_annotation); if (!unsmob_stencil (in_text_stencil)) in_text_stencil = SCM_EOL; - annotation->translate_axis (mol.extent (Y_AXIS)[UP] + number_raise - annotation->extent (Y_AXIS)[UP], Y_AXIS); - mol.add_at_edge (X_AXIS, LEFT, *annotation, 0.0); + annotation->translate_axis ((footnote_stencil.extent (Y_AXIS)[UP] + + number_raise + - annotation->extent (Y_AXIS)[UP]), + Y_AXIS); + footnote_stencil.add_at_edge (X_AXIS, LEFT, *annotation, 0.0); numbers = scm_cdr (numbers); in_text_numbers = scm_cdr (in_text_numbers); } - number_footnote_table = scm_cons (scm_cons (scm_caar (st), in_text_stencil), number_footnote_table); - footnote_stencil.add_at_edge (Y_AXIS, DOWN, mol, padding); + number_footnote_table = scm_cons (scm_cons (scm_caar (st), + in_text_stencil), + number_footnote_table); + if (!footnote_stencil.is_empty ()) + mol.add_at_edge (Y_AXIS, DOWN, footnote_stencil, padding); } - footnotes = scm_cons (footnote_stencil.smobbed_copy (), footnotes); + p->set_property ("footnote-stencil", mol.smobbed_copy ()); } } // note that this line of code doesn't do anything if numbering isn't turned on pb->top_paper ()->set_variable (ly_symbol2scm ("number-footnote-table"), number_footnote_table); - if (!scm_is_pair (footnotes)) - return SCM_EOL; - - return scm_reverse (footnotes); } Stencil * @@ -314,7 +360,7 @@ Page_layout_problem::add_footnotes_to_footer (SCM footnotes, Stencil *foot, Pape } } -Page_layout_problem::Page_layout_problem (Paper_book *pb, SCM page_scm, SCM systems, int footnote_count) +Page_layout_problem::Page_layout_problem (Paper_book *pb, SCM page_scm, SCM systems) : bottom_skyline_ (DOWN) { Prob *page = unsmob_prob (page_scm); @@ -331,9 +377,7 @@ Page_layout_problem::Page_layout_problem (Paper_book *pb, SCM page_scm, SCM syst if (pb && pb->paper_) { - if (to_boolean (pb->paper_->c_variable ("reset-footnotes-on-new-page"))) - footnote_count = 0; - SCM footnotes = get_footnotes_from_lines (systems, footnote_count, pb); + SCM footnotes = get_footnotes_from_lines (systems); add_footnotes_to_footer (footnotes, foot, pb); } else @@ -382,6 +426,8 @@ Page_layout_problem::Page_layout_problem (Paper_book *pb, SCM page_scm, SCM syst read_spacing_spec (top_system_spacing, &header_padding_, ly_symbol2scm ("padding")); read_spacing_spec (last_bottom_spacing, &footer_padding_, ly_symbol2scm ("padding")); + in_note_padding_ = robust_scm2double (paper->c_variable ("in-note-padding"), 0.5); + in_note_direction_ = robust_scm2dir (paper->c_variable ("in-note-direction"), UP); } bool last_system_was_title = false; @@ -490,6 +536,18 @@ Page_layout_problem::append_system (System *sys, Spring const &spring, Real inde build_system_skyline (elts, minimum_offsets_with_min_dist, &up_skyline, &down_skyline); up_skyline.shift (indent); down_skyline.shift (indent); + Stencil *in_note_stencil = unsmob_stencil (sys->get_property ("in-note-stencil")); + + if (in_note_stencil && in_note_stencil->extent (Y_AXIS).length () > 0) + { + sys->set_property ("in-note-padding", scm_from_double (in_note_padding_)); + sys->set_property ("in-note-direction", scm_from_int (in_note_direction_)); + Skyline *sky = in_note_direction_ == UP ? &up_skyline : &down_skyline; + sky->set_minimum_height (sky->max_height () + + in_note_direction_ + * (in_note_padding_ + + in_note_stencil->extent (Y_AXIS).length ())); + } /* We need to call distance with skyline-horizontal-padding because @@ -497,7 +555,10 @@ Page_layout_problem::append_system (System *sys, Spring const &spring, Real inde of an individual staff. So we add the padding for the distance check at the time of adding in the system. */ - Real minimum_distance = up_skyline.distance (bottom_skyline_, robust_scm2double (sys->get_property ("skyline-horizontal-padding"), 0)) + padding; + Real minimum_distance = up_skyline.distance (bottom_skyline_, + robust_scm2double (sys->get_property ("skyline-horizontal-padding"), + 0)) + + padding; Spring spring_copy = spring; spring_copy.ensure_min_distance (minimum_distance); diff --git a/lily/page-spacing.cc b/lily/page-spacing.cc index 3255006633..7e20f8416c 100644 --- a/lily/page-spacing.cc +++ b/lily/page-spacing.cc @@ -72,7 +72,18 @@ Real Page_spacing::account_for_footnotes (Line_details const &line) { Real footnote_height = 0.0; - for (vsize i = 0; i < line.footnotes_.size (); i++) + Real in_note_height = 0.0; + bool has_in_notes = false; + for (vsize i = 0; i < line.in_note_heights_.size (); i++) + { + in_note_height += (has_in_notes + ? 0.0 + : breaker_->in_note_padding ()); + has_in_notes = true; + in_note_height += line.in_note_heights_[i]; + } + + for (vsize i = 0; i < line.footnote_heights_.size (); i++) { footnote_height += (has_footnotes_ ? 0.0 @@ -81,12 +92,16 @@ Page_spacing::account_for_footnotes (Line_details const &line) + breaker_->footnote_number_raise ())); has_footnotes_ = true; - Interval extent = line.footnotes_[i]->extent (Y_AXIS); - footnote_height += extent[UP] - extent[DOWN]; + footnote_height += line.footnote_heights_[i]; footnote_height += breaker_->footnote_padding (); } - return (footnote_height + return (in_note_height + - (has_in_notes + ? breaker_->in_note_padding () + : 0.0)) + + + (footnote_height - (has_footnotes_ ? breaker_->footnote_padding () + breaker_->footnote_footer_padding () : 0.0)); diff --git a/lily/system.cc b/lily/system.cc index f4a37cd24d..e3b48bda71 100644 --- a/lily/system.cc +++ b/lily/system.cc @@ -249,7 +249,6 @@ System::get_footnote_grobs_in_range (vector &out, vsize start, vsize end for (vsize i = 0; i < footnote_grobs_.size (); i++) { int pos = footnote_grobs_[i]->spanned_rank_interval ()[LEFT]; - bool end_of_line_visible = true; if (Spanner *s = dynamic_cast(footnote_grobs_[i])) { Direction spanner_placement = robust_scm2dir (s->get_property ("spanner-placement"), LEFT); @@ -264,17 +263,18 @@ System::get_footnote_grobs_in_range (vector &out, vsize start, vsize end if (!Item::break_visible (item)) continue; // safeguard to bring down the column rank so that end of line footnotes show up on the correct line - end_of_line_visible = (LEFT == item->break_status_dir ()); + if (pos == int (start) && item->break_status_dir () != RIGHT) + continue; + if (pos == int (end) && item->break_status_dir () != LEFT) + continue; + if (pos != int (end) && pos != int (start) && item->break_status_dir () != CENTER) + continue; } if (pos < int (start)) continue; if (pos > int (end)) break; - if (pos == int (start) && end_of_line_visible) - continue; - if (pos == int (end) && !end_of_line_visible) - continue; if (!footnote_grobs_[i]->is_live ()) continue; @@ -282,12 +282,30 @@ System::get_footnote_grobs_in_range (vector &out, vsize start, vsize end } } -vector -System::get_footnotes_in_range (vsize start, vsize end) +vector +System::get_footnote_heights_in_range (vsize start, vsize end) +{ + return internal_get_note_heights_in_range (start, end, true); +} + +vector +System::get_in_note_heights_in_range (vsize start, vsize end) +{ + return internal_get_note_heights_in_range (start, end, false); +} + +vector +System::internal_get_note_heights_in_range (vsize start, vsize end, bool foot) { vector footnote_grobs; get_footnote_grobs_in_range (footnote_grobs, start, end); - vector out; + vector out; + + for (vsize i = footnote_grobs.size (); i--;) + if (foot + ? !to_boolean (footnote_grobs[i]->get_property ("footnote")) + : to_boolean (footnote_grobs[i]->get_property ("footnote"))) + footnote_grobs.erase (footnote_grobs.begin () + i); for (vsize i = 0; i < footnote_grobs.size (); i++) { @@ -303,7 +321,7 @@ System::get_footnotes_in_range (vsize start, vsize end) props, footnote_markup); Stencil *footnote_stencil = unsmob_stencil (footnote_stl); - out.push_back (footnote_stencil); + out.push_back (footnote_stencil->extent (Y_AXIS).length ()); } return out; @@ -905,6 +923,10 @@ ADD_INTERFACE (System, /* properties */ "all-elements " "columns " + "footnote-stencil " + "in-note-direction " + "in-note-padding " + "in-note-stencil " "labels " "pure-Y-extent " "skyline-horizontal-padding " diff --git a/scm/define-grob-interfaces.scm b/scm/define-grob-interfaces.scm index 7b6535f1e3..2047d6c630 100644 --- a/scm/define-grob-interfaces.scm +++ b/scm/define-grob-interfaces.scm @@ -84,7 +84,7 @@ note)." (ly:add-interface 'footnote-interface "Make a footnote." - '(automatically-numbered footnote-text)) + '(automatically-numbered footnote footnote-text)) (ly:add-interface 'footnote-spanner-interface diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index acda4c25c3..0cc9eb5a0e 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -298,6 +298,7 @@ include @code{upright}, @code{italic}, @code{caps}.") @w{@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 ,boolean? "Should this be a footnote or in-note?") (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 @@ -1028,6 +1029,7 @@ in addition to notes and stems.") (figures ,ly:grob-array? "Figured bass objects for continuation line.") (flag ,ly:grob? "A pointer to a @code{Flag} object.") + (footnote-stencil ,ly:stencil? "The stencil of a system's footnotes.") (glissando-index ,integer? "The index of a glissando in its note column.") @@ -1037,6 +1039,9 @@ column.") (items-worth-living ,ly:grob-array? "An array of interesting items. If empty in a particular staff, then that staff is erased.") + (in-note-direction ,ly:dir? "Direction to place in-notes above a system.") + (in-note-padding ,number? "Padding between in-notes.") + (in-note-stencil ,ly:stencil? "The stencil of a system's in-notes.") (keep-alive-with ,ly:grob-array? "An array of other @code{VerticalAxisGroup}s. If any of them are alive, then we will stay alive.") diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index f86fe11f54..9e213c6daa 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -887,6 +887,7 @@ (annotation-line . #t) (automatically-numbered . ,(grob::calc-property-by-copy 'automatically-numbered)) (break-visibility . ,inherit-y-parent-visibility) + (footnote . #t) (footnote-text . ,(grob::calc-property-by-copy 'footnote-text)) (stencil . ,ly:balloon-interface::print) (text . ,(grob::calc-property-by-copy 'text)) @@ -905,6 +906,7 @@ (annotation-balloon . #f) (annotation-line . #t) (automatically-numbered . ,(grob::calc-property-by-copy 'automatically-numbered)) + (footnote . #t) (footnote-text . ,(grob::calc-property-by-copy 'footnote-text)) (spanner-placement . ,LEFT) (stencil . ,ly:balloon-interface::print-spanner) diff --git a/scm/paper-system.scm b/scm/paper-system.scm index d60836199d..7d8bdf1a31 100644 --- a/scm/paper-system.scm +++ b/scm/paper-system.scm @@ -25,8 +25,21 @@ (equal? #t (ly:prob-property system 'is-title) )) +(define (system-stencil system-grob main-stencil) + (let* ((padding (ly:grob-property system-grob 'in-note-padding #f)) + (in-notes (if padding (ly:grob-property system-grob 'in-note-stencil) empty-stencil)) + (in-notes (if in-notes in-notes empty-stencil)) + (direction (if padding (ly:grob-property system-grob 'in-note-direction) UP))) + (if padding + (ly:stencil-combine-at-edge main-stencil Y direction in-notes padding) + main-stencil))) + (define-public (paper-system-stencil system) - (ly:prob-property system 'stencil)) + (let ((main-stencil (ly:prob-property system 'stencil)) + (system-grob (ly:prob-property system 'system-grob))) + (if (ly:grob? system-grob) + (system-stencil system-grob main-stencil) + main-stencil))) (define-public (paper-system-layout system) (let*