]> git.donarmstrong.com Git - lilypond.git/commitdiff
Adds in-notes to LilyPond.
authorMike Solomon <mike@apollinemike.com>
Wed, 2 Nov 2011 13:26:56 +0000 (14:26 +0100)
committerDavid Kastrup <dak@gnu.org>
Thu, 3 Nov 2011 15:19:27 +0000 (16:19 +0100)
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.

16 files changed:
input/regression/footnote-break-visibility.ly
input/regression/in-note.ly [new file with mode: 0644]
lily/align-interface.cc
lily/constrained-breaking.cc
lily/include/constrained-breaking.hh
lily/include/page-breaking.hh
lily/include/page-layout-problem.hh
lily/include/system.hh
lily/page-breaking.cc
lily/page-layout-problem.cc
lily/page-spacing.cc
lily/system.cc
scm/define-grob-interfaces.scm
scm/define-grob-properties.scm
scm/define-grobs.scm
scm/paper-system.scm

index 23e9035a7128688ffb8ab050ab39291fb6ed843c..c23d5d6d2b830c6a2c9855bc63fa4a704418e3e3 100644 (file)
@@ -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 (file)
index 0000000..1d08d5c
--- /dev/null
@@ -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\! }
+    }
+  }
+}
index 44c30e6013027c78a74ef90c3b7f1a66960a91ba..00ea0029e31717f0767efdb6c260f6ac799850d5 100644 (file)
@@ -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
index d269cff48571d91fcfda5bd25a8ade3a0863d86b..1e7fe96c51502b44cfdb70da7eb3955cf97bf98a 100644 (file)
@@ -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;
index 1887d872732396190d15f1b92aa9c055d0f693d0..e54048797175fffaf0e9d96c3ed0a25b76dd368a 100644 (file)
@@ -45,9 +45,12 @@ struct Line_details
   Grob *last_column_;
   Real force_;
   Line_shape shape_;
-  vector<Stencil *> footnotes_; /* The footnotes at the bottom of the
+  vector<Real> footnote_heights_; /* The footnotes at the bottom of the
                                    page, where each stencil represents
                                    a different footnote. */
+  vector<Real> 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
index 7d50db2524e9eaffc55705ce1fc2be206067aadc..eb2fe5370d9b25c7611692d79bd4dd74f59fd28e 100644 (file)
@@ -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 */
index 6c952e3eedc0526847673566afce7959345d0fcf..665f15396bf311a32f1d981ad492a87feb5e1e84 100644 (file)
@@ -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 */
index 4a3c3c1b48d0700f1864e5d9cc8bb92472cab38c..f002d72c0f40724c1b75a4f73b7fa2e84554310b 100644 (file)
@@ -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<Stencil *> get_footnotes_in_range (vsize st, vsize end);
+  vector<Real> get_footnote_heights_in_range (vsize st, vsize end);
+  vector<Real> get_in_note_heights_in_range (vsize st, vsize end);
+  vector<Real> internal_get_note_heights_in_range (vsize st, vsize end, bool foot);
   void get_footnote_grobs_in_range (vector<Grob *> &out, vsize st, vsize end);
   vector<Grob *> *footnote_grobs ();
   vsize num_footnotes ();
index c46a04efa5c363b596da1fbf0ee83b91732cfa25..01d7469f52ed80ff45a1f9e5c102e1b262076ca3 100644 (file)
@@ -183,8 +183,12 @@ compress_lines (const vector<Line_details> &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<vsize> 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<vsize> 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<vsize> 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))
index 82c0dc7181fd92893b4c73006d73f4344ed9dc51..562f0aeb901c98e1eaa121af331ff0d8af45d9c5 100644 (file)
@@ -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);
index 32550066334e33ce22ea42cb1ebf88c805e17de8..7e20f8416c5aa534983068a7987cfab5a85ec78e 100644 (file)
@@ -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));
index f4a37cd24dfa66d13eb4f891cf7c02cea064abfa..e3b48bda713a311afc0798bb358c6d5637c5d999 100644 (file)
@@ -249,7 +249,6 @@ System::get_footnote_grobs_in_range (vector<Grob *> &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<Spanner *>(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<Grob *> &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<Grob *> &out, vsize start, vsize end
     }
 }
 
-vector<Stencil *>
-System::get_footnotes_in_range (vsize start, vsize end)
+vector<Real>
+System::get_footnote_heights_in_range (vsize start, vsize end)
+{
+  return internal_get_note_heights_in_range (start, end, true);
+}
+
+vector<Real>
+System::get_in_note_heights_in_range (vsize start, vsize end)
+{
+  return internal_get_note_heights_in_range (start, end, false);
+}
+
+vector<Real>
+System::internal_get_note_heights_in_range (vsize start, vsize end, bool foot)
 {
   vector<Grob *> footnote_grobs;
   get_footnote_grobs_in_range (footnote_grobs, start, end);
-  vector<Stencil *> out;
+  vector<Real> 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 "
index 7b6535f1e38ef069e7464e32b856673f4df3b6cc..2047d6c63083b8213dd006159825e4bad59f1b1f 100644 (file)
@@ -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
index acda4c25c3c7a787712fae306b685c2c637bde5f..0cc9eb5a0ebdfa0c90c6cc80a616e0b836205838 100644 (file)
@@ -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.")
index f86fe11f54f9ab9f65e7b7b17eca3e2acb48bc9f..9e213c6daad1d7b52ea41877447230a7a13d186f 100644 (file)
        (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))
        (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)
index d60836199db4622ddcf9b55f182767066fc11028..7d8bdf1a314d91d8b66795bc03824e44f2f874e8 100644 (file)
   (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*