]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/system.cc
Fix 1259/1433: linebreaks with \breakDynamicSpan or spanners with style=#'none
[lilypond.git] / lily / system.cc
index 8196736eca5d007565b36d8fe035f50164ced2c5..1cd582de7525bc2d628b24cb062ddfc188ac7904 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 1996--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  Copyright (C) 1996--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
   LilyPond is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -22,6 +22,7 @@
 #include "align-interface.hh"
 #include "all-font-metrics.hh"
 #include "axis-group-interface.hh"
+#include "break-align-interface.hh"
 #include "grob-array.hh"
 #include "hara-kiri-group-spanner.hh"
 #include "international.hh"
@@ -35,6 +36,7 @@
 #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)
@@ -43,6 +45,7 @@ System::System (System const &src)
   all_elements_ = 0;
   pscore_ = 0;
   rank_ = 0;
+  checked_footnotes_ = false;
   init_elements ();
 }
 
@@ -51,6 +54,7 @@ System::System (SCM s)
 {
   all_elements_ = 0;
   rank_ = 0;
+  checked_footnotes_ = false;
   init_elements ();
 }
 
@@ -162,7 +166,7 @@ System::do_break_substitution_and_fixup_refpoints ()
          Grob *g = all_elts[j];
          g->fixup_refpoint ();
        }
-
+        
       count += all_elts.size ();
     }
 
@@ -226,6 +230,114 @@ System::get_paper_systems ()
   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]->internal_has_interface (ly_symbol2scm ("footnote-interface")))
+      footnote_grobs_.push_back (all_elts[i]);
+
+  sort (footnote_grobs_.begin (), footnote_grobs_.end (), Grob::less);
+  checked_footnotes_ = true;
+}
+
+void
+System::get_footnote_grobs_in_range (vector<Grob *> &out, vsize start, vsize end)
+{
+  if (!checked_footnotes_)
+    populate_footnote_grob_vector ();
+
+  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);
+          if (spanner_placement == CENTER)
+            spanner_placement = LEFT;
+
+          pos = s->spanned_rank_interval ()[spanner_placement];
+        }
+      
+      if (Item *item = dynamic_cast<Item *>(footnote_grobs_[i]))
+        {
+          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))
+        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;
+
+      out.push_back (footnote_grobs_[i]);
+    }
+}
+
+vector<Stencil *>
+System::get_footnotes_in_range (vsize start, vsize end)
+{
+  vector<Grob *> footnote_grobs;
+  get_footnote_grobs_in_range (footnote_grobs, start, end);
+  vector<Stencil *> out;
+
+  for (vsize i = 0; i < footnote_grobs.size (); i++)
+    {
+      SCM footnote_markup = footnote_grobs[i]->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 < footnote_grobs_.size (); i++)
+    {
+      SCM footnote_markup = footnote_grobs_[i]->get_property ("footnote-text");
+      if (Spanner *orig = dynamic_cast<Spanner *>(footnote_grobs_[i]))
+        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"),
+                              pscore_->layout ()->self_scm ());
+
+      SCM footnote_stl = Text_interface::interpret_markup (pscore_->layout ()->self_scm (),
+                                                           props, footnote_markup);
+
+      mol.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (footnote_stl), padding);
+    }
+
+  return mol;
+}
+
 void
 System::break_into_pieces (vector<Column_x_positions> const &breaking)
 {
@@ -242,6 +354,8 @@ 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));
 
+      get_footnote_grobs_in_range (system->footnote_grobs_, st, end);
+
       system->set_bound (LEFT, c[0]);
       system->set_bound (RIGHT, c.back ());
       SCM system_labels = SCM_EOL;
@@ -250,10 +364,16 @@ System::break_into_pieces (vector<Column_x_positions> const &breaking)
          c[j]->translate_axis (breaking[i].config_[j], X_AXIS);
          dynamic_cast<Paper_column *> (c[j])->set_system (system);
          /* collect the column labels */
-         SCM col_labels = c[j]->get_property ("labels");
-         if (scm_is_pair (col_labels))
-           system_labels = scm_append (scm_list_2 (col_labels, system_labels));
+         collect_labels (c[j], &system_labels);
        }
+      /*
+       Collect labels from any loose columns too: theses will be set on
+       an empty bar line or a column which is otherwise unused mid-line
+      */
+      vector<Grob *> loose (breaking[i].loose_cols_);
+      for (vsize j = 0; j < loose.size (); j++)
+       collect_labels (loose[j], &system_labels);
+
       system->set_property ("labels", system_labels);
 
       set_loose_columns (system, &breaking[i]);
@@ -261,6 +381,14 @@ System::break_into_pieces (vector<Column_x_positions> const &breaking)
     }
 }
 
+void
+System::collect_labels (Grob const *col, SCM *labels)
+{
+  SCM col_labels = col->get_property ("labels");
+  if (scm_is_pair (col_labels))
+    *labels = scm_append (scm_list_2 (col_labels, *labels));
+}
+
 void
 System::add_column (Paper_column *p)
 {
@@ -581,7 +709,7 @@ System::pure_refpoint_extent (vsize start, vsize end)
     return Interval ();
 
   extract_grob_set (alignment, "elements", staves);
-  vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end);
+  vector<Real> offsets = Align_interface::get_pure_minimum_translations (alignment, staves, Y_AXIS, start, end);
 
   for (vsize i = 0; i < offsets.size (); ++i)
     if (Page_layout_problem::is_spaceable (staves[i]))
@@ -608,7 +736,7 @@ System::part_of_line_pure_height (vsize start, vsize end, bool begin)
     return Interval ();
 
   extract_grob_set (alignment, "elements", staves);
-  vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end);
+  vector<Real> offsets = Align_interface::get_pure_minimum_translations (alignment, staves, Y_AXIS, start, end);
 
   Interval ret;
   for (vsize i = 0; i < staves.size (); ++i)
@@ -704,6 +832,29 @@ System::calc_pure_height (SCM smob, SCM start_scm, SCM end_scm)
   return ly_interval2scm (begin);
 }
 
+Grob*
+System::get_pure_bound (Direction d, int start, int end)
+{
+  vector<vsize> ranks = pscore_->get_break_ranks ();
+  vector<vsize> indices = pscore_->get_break_indices ();
+  vector<Grob*> cols = pscore_->get_columns ();
+
+  vsize target_rank = (d == LEFT ? start : end);
+  vector<vsize>::const_iterator i =
+    lower_bound (ranks.begin (), ranks.end (), target_rank, std::less<vsize> ());
+
+  if (i != ranks.end () && (*i) == target_rank)
+    return cols[indices[i - ranks.begin ()]];
+  else
+    return 0;
+}
+
+Grob*
+System::get_maybe_pure_bound (Direction d, bool pure, int start, int end)
+{
+  return pure ? get_pure_bound (d, start, end) : get_bound (d);
+}
+
 ADD_INTERFACE (System,
               "This is the top-level object: Each object in a score"
               " ultimately has a @code{System} object as its X and"