]> git.donarmstrong.com Git - lilypond.git/commitdiff
* scm/define-music-types.scm (music-descriptions): remove
authorJoe Neeman <joeneeman@gmail.com>
Sun, 17 Sep 2006 11:02:29 +0000 (11:02 +0000)
committerJoe Neeman <joeneeman@gmail.com>
Sun, 17 Sep 2006 11:02:29 +0000 (11:02 +0000)
BreakEvent and fix {Page,Line}{Break,Turn}Event so
Music::to_event doesn't complain.

* lily/accidental-placement.cc (ape_compare):
* lily/semi-tie.cc (compare):
* lily/note-column.cc (shift_compare): replace by XXX_less

* lily/tie-formatting-problem.cc (set_chord_outline):
* lily/tie-column.cc (calc_positioning_done):
* lily/system.cc (post_processing)
(get_paper_system):
* lily/stem.cc (note_head_positions)
(calc_positioning_done):
* lily/spanner.cc (do_break_processing)
(find_broken_piece):
* lily/span-bar.cc (print):
* lily/semi-tie-column.cc (calc_positioning_done):
* lily/rest-collision.cc (calc_positioning_done):
* lily/program-option.cc (get_help_string):
* lily/note-collision.cc (get_clash_groups):
* lily/new-fingering-engraver.cc (position_scripts):
* lily/keyword.cc (Keyword_table):
* lily/hara-kiri-group-spanner.cc (request_suicide):
* lily/grob-pq-engraver.cc (stop_translation_timestep):
* lily/accidental-placement.cc (calc_positioning_done):
(stagger_apes):
* lily/beam.cc (get_beam_segments):
* lily/grob-array.cc (remove_duplicates):
use new vector_sort

* input/mutopia/W.A.Mozart/mozart-hrn3-defs.ily:
ragged-last-bottom = ##f (test the new page breaker)

* flower/include/std-vector.hh (vector_sort): use STL sort stuff

* scm/define-context-properties.scm
(all-internal-translation-properties): remove properties that
were used to communicate page-turn stuff to the paper-column
engraver.

* lily/lily-guile.cc (robust_scm2string): new function

* lily/paper-column-engraver.cc: Clean up page turn stuff

* lily/page-turn-engraver.cc: Re-write the page turn logic here
instead of cluttering up paper-column-engraver.cc

38 files changed:
ChangeLog
flower/include/interval.hh
flower/include/std-vector.hh
input/mutopia/W.A.Mozart/mozart-hrn3-defs.ily
lily/accidental-placement.cc
lily/beam.cc
lily/dot-column.cc
lily/grob-array.cc
lily/grob-pq-engraver.cc
lily/hara-kiri-group-spanner.cc
lily/include/lily-guile.hh
lily/include/note-column.hh
lily/include/paper-column-engraver.hh
lily/include/semi-tie.hh
lily/include/spanner.hh
lily/include/staff-symbol-referencer.hh
lily/include/tie.hh
lily/keyword.cc
lily/lily-guile.cc
lily/new-fingering-engraver.cc
lily/note-collision.cc
lily/note-column.cc
lily/page-turn-engraver.cc
lily/paper-column-engraver.cc
lily/program-option.cc
lily/rest-collision.cc
lily/semi-tie-column.cc
lily/semi-tie.cc
lily/span-bar.cc
lily/spanner.cc
lily/staff-symbol-referencer.cc
lily/stem.cc
lily/system.cc
lily/tie-column.cc
lily/tie-formatting-problem.cc
lily/tie.cc
scm/define-context-properties.scm
scm/define-music-types.scm

index 8460604166e78e60283a7c4c1d422175bae243bc..6919772b256d78135802d412ae50a7c7922cd3fe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,53 @@
+2006-09-17  Joe Neeman  <joeneeman@gmail.com>
+
+       * scm/define-music-types.scm (music-descriptions): remove
+       BreakEvent and fix {Page,Line}{Break,Turn}Event so
+       Music::to_event doesn't complain.
+
+       * lily/accidental-placement.cc (ape_compare):
+       * lily/semi-tie.cc (compare): 
+       * lily/note-column.cc (shift_compare): replace by XXX_less
+
+       * lily/tie-formatting-problem.cc (set_chord_outline): 
+       * lily/tie-column.cc (calc_positioning_done): 
+       * lily/system.cc (post_processing)
+       (get_paper_system): 
+       * lily/stem.cc (note_head_positions)
+       (calc_positioning_done): 
+       * lily/spanner.cc (do_break_processing)
+       (find_broken_piece): 
+       * lily/span-bar.cc (print): 
+       * lily/semi-tie-column.cc (calc_positioning_done): 
+       * lily/rest-collision.cc (calc_positioning_done): 
+       * lily/program-option.cc (get_help_string): 
+       * lily/note-collision.cc (get_clash_groups):
+       * lily/new-fingering-engraver.cc (position_scripts):
+       * lily/keyword.cc (Keyword_table):
+       * lily/hara-kiri-group-spanner.cc (request_suicide):
+       * lily/grob-pq-engraver.cc (stop_translation_timestep):
+       * lily/accidental-placement.cc (calc_positioning_done):
+       (stagger_apes):
+       * lily/beam.cc (get_beam_segments):
+       * lily/grob-array.cc (remove_duplicates):
+       use new vector_sort
+       
+       * input/mutopia/W.A.Mozart/mozart-hrn3-defs.ily:
+       ragged-last-bottom = ##f (test the new page breaker)
+
+       * flower/include/std-vector.hh (vector_sort): use STL sort stuff
+
+       * scm/define-context-properties.scm
+       (all-internal-translation-properties): remove properties that
+       were used to communicate page-turn stuff to the paper-column
+       engraver.
+
+       * lily/lily-guile.cc (robust_scm2string): new function
+
+       * lily/paper-column-engraver.cc: Clean up page turn stuff
+
+       * lily/page-turn-engraver.cc: Re-write the page turn logic here
+       instead of cluttering up paper-column-engraver.cc
+
 2006-09-17  Nicolas Sceaux  <nicolas.sceaux@free.fr>
 
        * scm/layout-page-dump.scm (scm): export utility function names,
index 1b095dedc307e1ed8a5460b561a5fc87b23e3b90..7b7d4f54e5b98c74310e569986c187ab6481e17c 100644 (file)
@@ -128,9 +128,9 @@ struct Interval_t : public Drul_array<T>
     at (RIGHT) = t;
   }
 
-  static int left_comparison (Interval_t<T> const &a, Interval_t<T> const &b)
+  static bool left_less (Interval_t<T> const &a, Interval_t<T> const &b)
   {
-    return sign (a[LEFT] - b[RIGHT]);
+    return a[LEFT] < b[RIGHT];
   }
 };
 
index da3686a07c813eb7ab036d3e151c7c6af762d4ee..10641dc5a00daa8e1569352469fc97c86e7b5e9d 100644 (file)
@@ -191,46 +191,17 @@ binary_search (vector<T> const &v,
   return lb;
 }
 
-#if 0
-/* FIXME: the COMPARE functionality is broken?  */
-template<typename T>
+template<typename T, typename Compare>
 void
-vector_sort (vector<T> &v, int (*compare) (T const &, T const &),
-            vsize lower=VPOS, vsize upper=VPOS)
+vector_sort (vector<T> &v,
+            Compare less,
+            vsize b=0, vsize e=VPOS)
 {
-  typename vector<T>::iterator b = v.begin ();
-  typename vector<T>::iterator e = v.begin ();
-  if (lower == VPOS)
-    {
-      lower = 0;
-      upper = v.size ();
-    }
-  sort (b + lower, e + upper, compare);
-}
-#else
+  if (e == VPOS)
+    e = v.size ();
 
-// ugh, c&p
-template<typename T> void
-vector_sort (vector<T> &v, int (*compare) (T const &, T const &),
-            vsize lower=VPOS, vsize upper=VPOS)
-{
-  if (lower == VPOS)
-    {
-      lower = 0;
-      upper = v.size () - 1;
-    }
-  if (upper == VPOS || lower >= upper)
-    return;
-  swap (v[lower], v[(lower + upper) / 2]);
-  vsize last = lower;
-  for (vsize i = lower +1; i <= upper; i++)
-    if (compare (v[i], v[lower]) < 0)
-      swap (v[++last], v[i]);
-  swap (v[lower], v[last]);
-  vector_sort (v, compare, lower, last - 1);
-  vector_sort (v, compare, last + 1, upper);
+  sort (v.begin () + b, v.begin () + e, less);
 }
-#endif
 
 template<typename T>
 void
index c383c429de07c136ec604c3e1fe827427160d1b5..3a101125242b5d6c86e6ece459d197f0a755ae11 100644 (file)
@@ -45,6 +45,7 @@ cresc =  {
     
     indent = 10. \mm
     line-width = 189. \mm
+    ragged-last-bottom = ##f
 
 }
 
index f05a5e67f552b34a1f5b952af9dc4ba4fe6919d0..2a97f7f38242f2f9a74b6e1d0a89f9fea326f78f 100644 (file)
@@ -135,6 +135,12 @@ int ape_compare (Accidental_placement_entry *const &a,
   return sign (ape_priority (a) - ape_priority (b));
 }
 
+bool ape_less (Accidental_placement_entry *const &a,
+              Accidental_placement_entry *const &b)
+{
+  return ape_priority (a) < ape_priority (b);
+}
+
 int ape_rcompare (Accidental_placement_entry *const &a,
                  Accidental_placement_entry *const &b)
 {
@@ -154,7 +160,7 @@ stagger_apes (vector<Accidental_placement_entry*> *apes)
 {
   vector<Accidental_placement_entry*> asc = *apes;
 
-  vector_sort (asc, &ape_compare);
+  vector_sort (asc, &ape_less);
 
   apes->clear ();
 
@@ -293,7 +299,7 @@ Accidental_placement::calc_positioning_done (SCM smob)
   for (vsize i = note_cols.size (); i--;)
     concat (heads, extract_grob_array (note_cols[i], "note-heads"));
 
-  vector_sort (heads, default_compare);
+  vector_sort (heads, less<Grob*> ());
   uniq (heads);
   common[Y_AXIS] = common_refpoint_of_array (heads, common[Y_AXIS], Y_AXIS);
 
index 9dd66cef9a4124658bf447b14d81dc1f9ecac1d1..c52b6f14f974f567a52fad449e4987dbc6161d8f 100644 (file)
@@ -368,7 +368,7 @@ Beam::get_beam_segments (Grob *me_grob, Grob **common)
        i != stem_segments.end (); i++)
     {
       vector<Beam_stem_segment> segs = (*i).second;
-      vector_sort (segs, default_compare);
+      vector_sort (segs, less<Beam_stem_segment> ());
 
       Beam_segment current;
 
index 3ebddc69a015267561adb67a24a35a3f5a9a474e..ac76bd4a1631782cf6994b40b9d864680ac07252 100644 (file)
@@ -233,7 +233,7 @@ Dot_column::calc_positioning_done (SCM smob)
       }
   }
 
-  vector_sort (dots, &compare_position);
+  vector_sort (dots, position_less);
   for (vsize i = dots.size (); i--;)
     if (!dots[i]->is_live ())
       dots.erase (dots.begin () + i);
index dff5102a83c776406473e5ba60ed4ae6e54e8ee7..bf85be414c7fc82ec8c73e516f0a075c63fe83b4 100644 (file)
@@ -87,7 +87,7 @@ Grob_array::remove_duplicates ()
 {
   assert (!ordered_);
   
-  vector_sort (grobs_, default_compare);
+  vector_sort (grobs_, less<Grob*> ());
   ::uniq (grobs_);
 }
 
index e4e8b944f968aefd5647185bc9f2ef21c87a560f..80d072b404fff458548a8ccb1b9b435f5bffbe7b 100644 (file)
@@ -15,13 +15,14 @@ struct Grob_pq_entry
 {
   Grob *grob_;
   Moment end_;
-  static int compare (Grob_pq_entry const &a,
-                     Grob_pq_entry const &b)
-  {
-    return Moment::compare (a.end_, b.end_);
-  }
 };
 
+bool
+operator< (Grob_pq_entry const &a, Grob_pq_entry const &b)
+{
+  return a.end_ < b.end_;
+}
+
 class Grob_pq_engraver : public Engraver
 {
 public:
@@ -95,7 +96,7 @@ Grob_pq_engraver::stop_translation_timestep ()
   while (scm_is_pair (busy) && *unsmob_moment (scm_caar (busy)) == now)
     busy = scm_cdr (busy);
 
-  vector_sort (started_now_, Grob_pq_entry::compare);
+  vector_sort (started_now_, less<Grob_pq_entry> ());
   SCM lst = SCM_EOL;
   SCM *tail = &lst;
   for (vsize i = 0; i < started_now_.size (); i++)
index bc59b12ae782452fc1085189e0a242b29d6b3c1e..1515e8fea21ef25f1bd9de571d0a907dd51685cb 100644 (file)
@@ -82,7 +82,7 @@ Hara_kiri_group_spanner::request_suicide (Grob *me, int start, int end)
          for (int j = iv[LEFT]; j <= iv[RIGHT]; j++)
            ranks.push_back (j);
        }
-      vector_sort (ranks, default_compare);
+      vector_sort (ranks, less<int> ());
       uniq (ranks);
 
       SCM scm_vec = scm_c_make_vector (ranks.size (), SCM_EOL);
index 23b3c64785edef95c978f2553d734da4a394f8a3..07abff74ef41f52c813b97fab2e7eff0f02772b1 100644 (file)
@@ -64,6 +64,7 @@ Drul_array<Real> robust_scm2drul (SCM, Drul_array<Real>);
 Drul_array<bool> robust_scm2booldrul (SCM, Drul_array<bool>);
 Interval robust_scm2interval (SCM, Drul_array<Real>);
 Offset robust_scm2offset (SCM, Offset);
+string robust_scm2string (SCM, string);
 
 SCM ly_quote_scm (SCM s);
 bool type_check_assignment (SCM val, SCM sym, SCM type_symbol);
index 5085ee52ebf8a91287360b60726512b4c3487395..ec12414539031d490301ca5f327b37a0d433085e 100644 (file)
@@ -19,7 +19,7 @@
 class Note_column
 {
 public:
-  static int shift_compare (Grob *const &, Grob *const &);
+  static bool shift_less (Grob *const &, Grob *const &);
   static Direction dir (Grob *me);
   static Grob *accidentals (Grob *me);
   static Grob *arpeggio (Grob *me);
index e5db58c7a308ccb092ead6c3306d0483eeb723e1..5f3131ccb009411731cf1b1bac2f313cc360b51e 100644 (file)
@@ -44,9 +44,6 @@ protected:
   bool first_;
   Moment last_moment_;
 
-  Paper_column *last_special_barline_column_;
-  Paper_column *last_breakable_column_;
-  vector<Paper_column*> page_turnable_columns_;
 public:
 };
 
index d0a0baf5b705c6605eaab7ddb07a35b8c45b2722..ec63c627ef3aee49bd2a388fc137469ade4448c9 100644 (file)
@@ -20,8 +20,8 @@ struct Semi_tie
   
   DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_control_points, (SCM));
-  static int compare (Grob *const &s1,
-                     Grob *const &s2);
+  static bool less (Grob *const &s1,
+                   Grob *const &s2);
   static int get_position (Grob *);
 };
 
index 2e8906ab96217168333f157b598913a00fd831e1..91153b79b8e43b5ed959fc379003ad869f638add 100644 (file)
@@ -56,7 +56,7 @@ public:
   Real spanner_length () const;
 
   static int compare (Spanner *const &, Spanner *const &);
-  static bool less_than (Spanner *const &, Spanner *const &);
+  static bool less (Spanner *const &, Spanner *const &);
   virtual Grob *find_broken_piece (System *) const;
   virtual void derived_mark () const;
   static bool has_interface (Grob *);
index 5e1fd878fdd5128b3450321dabf0289d18d6e20b..1b4c096b8ee4b38fa0351a360191342f4f2e649b 100644 (file)
@@ -40,6 +40,7 @@ public:
   static int get_rounded_position (Grob *);
 };
 
-int compare_position (Grob *const &, Grob *const &);
+int compare_position (Grob *const &, Grob *const &);\
+bool position_less (Grob *const &, Grob *const &);
 #endif /* STAFF_SYMBOL_REFERENCER_HH */
 
index 5b3706dafd0c2db68d675acbac348078b63d50d8..7f96b826cffd20ab84e4902b197381ab47fbc694 100644 (file)
@@ -33,8 +33,8 @@ public:
   DECLARE_SCHEME_CALLBACK (set_spacing_rods, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_control_points, (SCM));
-  static int compare (Grob *const &s1,
-                     Grob *const &s2);
+  static bool less (Grob *const &s1,
+                   Grob *const &s2);
 };
 
 
index 8f969e6ce858822471c2a0d49adbee8fe663d999..b5f7947ada203e31550ee041a557f37f439b115c 100644 (file)
@@ -14,17 +14,12 @@ bool tab_less (Keyword_ent const &p1, Keyword_ent const &p2)
   return strcmp (p1.name_, p2.name_) < 0;
 }
 
-int tabcmp (Keyword_ent const &p1, Keyword_ent const &p2)
-{
-  return strcmp (p1.name_, p2.name_);
-}
-
 Keyword_table::Keyword_table (Keyword_ent *tab)
 {
   while (tab->name_)
     table_.push_back (*tab++);
 
-  vector_sort (table_, tabcmp);
+  vector_sort (table_, tab_less);
 }
 
 vsize
index 971063e54ec382c823785f5833e5caa61f99df34..e1a0e9bffdc059fde75766d07b559dff3393bd2e 100644 (file)
@@ -653,6 +653,14 @@ robust_scm2offset (SCM k, Offset o)
   return o;
 }
 
+string
+robust_scm2string (SCM k, string s)
+{
+  if (scm_is_string (k))
+    s = ly_scm2string (k);
+  return s;
+}
+
 int
 robust_scm2int (SCM k, int o)
 {
index cb2a1bd20274288ae4386b3bfa03f5564e4671f2..75e893c351e585e056970becf1a28d9c65b641bb 100644 (file)
@@ -35,12 +35,14 @@ struct Finger_tuple
     note_event_ = finger_event_ = 0;
     follow_into_staff_ = false;
   }
-  static int compare (Finger_tuple const &c1, Finger_tuple const &c2)
-  {
-    return c1.position_- c2.position_;
-  }
 };
 
+bool
+operator< (Finger_tuple const &a, Finger_tuple const &b)
+{
+  return a.position_ < b.position_;
+}
+
 class New_fingering_engraver : public Engraver
 {
   vector<Finger_tuple> fingerings_;
@@ -220,7 +222,7 @@ New_fingering_engraver::position_scripts (SCM orientations,
        }
     }
 
-  vector_sort (*scripts, Finger_tuple::compare);
+  vector_sort (*scripts, less<Finger_tuple> ());
 
   bool up_p = scm_c_memq (ly_symbol2scm ("up"), orientations) != SCM_BOOL_F;
   bool down_p = scm_c_memq (ly_symbol2scm ("down"), orientations) != SCM_BOOL_F;
index e84e5263c63a57160ce55f577232db2e40a40e83..d9a08dcdc87741f8f7b50b1466e8c4b40c8af208 100644 (file)
@@ -371,7 +371,7 @@ Note_collision_interface::get_clash_groups (Grob *me)
   do
     {
       vector<Grob*> &clashes (clash_groups[d]);
-      vector_sort (clashes, Note_column::shift_compare);
+      vector_sort (clashes, Note_column::shift_less);
     }
   while ((flip (&d)) != UP);
 
index c77aa351f5a8f379189187e3311b9ac6889d385a..146b3b06545c9eecf3c6b1fd691f34b3ddcd22b8 100644 (file)
@@ -34,15 +34,15 @@ Note_column::has_rests (Grob *me)
   return unsmob_grob (me->get_object ("rest"));
 }
 
-int
-Note_column::shift_compare (Grob *const &p1, Grob *const &p2)
+bool
+Note_column::shift_less (Grob *const &p1, Grob *const &p2)
 {
   SCM s1 = p1->get_property ("horizontal-shift");
   SCM s2 = p2->get_property ("horizontal-shift");
 
   int h1 = (scm_is_number (s1)) ? scm_to_int (s1) : 0;
   int h2 = (scm_is_number (s2)) ? scm_to_int (s2) : 0;
-  return h1 - h2;
+  return h1 < h2;
 }
 
 Item *
index 1a2bf5f5b46a7928841f1a3e93a4a04494a6a9c1..56abfb256c2dcef31b63a01c00d1b3b5962fe863 100644 (file)
 #include "grob.hh"
 #include "international.hh"
 #include "moment.hh"
+#include "paper-column.hh"
+#include "stream-event.hh"
 #include "warn.hh"
 
+#include "translator.icc"
+
+class Page_turn_event {
+public:
+  SCM permission_;
+  Real penalty_;
+  Interval_t<Rational> duration_;
+
+  Page_turn_event (Rational start, Rational end, SCM perm, Real pen)
+  {
+    duration_[LEFT] = start;
+    duration_[RIGHT] = end;
+    permission_ = perm;
+    penalty_ = pen;
+  }
+
+  /* Suppose we have decided on a possible page turn, only to change
+     out mind later (for example, if there is a volta repeat and it
+     would be difficult to turn the page back). Then we need to
+     re-penalize a region of the piece. Depending on how the events
+     intersect, we may have to split it into as many as 3 pieces.
+  */
+  vector<Page_turn_event> penalize (Page_turn_event const &penalty)
+  {
+    Interval_t<Rational> intersect = intersection (duration_, penalty.duration_);
+    vector<Page_turn_event> ret;
+
+    if (intersect.is_empty ())
+      {
+       ret.push_back (*this);
+       return ret;
+      }
+
+    Real new_pen = max (penalty_, penalty.penalty_);
+
+    if (duration_[LEFT] < penalty.duration_[LEFT])
+      ret.push_back (Page_turn_event (duration_[LEFT], penalty.duration_[LEFT], permission_, penalty_));
+
+    if (penalty.permission_ != SCM_EOL)
+      ret.push_back (Page_turn_event (intersect[LEFT], intersect[RIGHT], permission_, new_pen));
+
+    if (penalty.duration_[RIGHT] < duration_[RIGHT])
+      ret.push_back (Page_turn_event (penalty.duration_[RIGHT], duration_[LEFT], permission_, penalty_));
+
+    return ret;
+  }
+};
+
 class Page_turn_engraver : public Engraver
 {
   Moment rest_begin_;
@@ -22,14 +72,28 @@ class Page_turn_engraver : public Engraver
   Moment note_end_;
   Rational repeat_begin_rest_length_;
 
+  vector<Page_turn_event> forced_breaks_;
+  vector<Page_turn_event> automatic_breaks_;
+  vector<Page_turn_event> repeat_penalties_;
+
+  /* the next 3 are in sync (ie. same number of elements, etc.) */
+  vector<Rational> breakable_moments_;
+  vector<Grob*> breakable_columns_;
+  vector<bool> special_barlines_;
+
+  SCM max_permission (SCM perm1, SCM perm2);
   Real penalty (Rational rest_len);
+  Grob *breakable_column (Page_turn_event const &);
 
 protected:
+  DECLARE_TRANSLATOR_LISTENER (break);
   DECLARE_ACKNOWLEDGER (note_head);
 
 public:
   TRANSLATOR_DECLARATIONS (Page_turn_engraver);
   void stop_translation_timestep ();
+  void start_translation_timestep ();
+  void finalize ();
 };
 
 Page_turn_engraver::Page_turn_engraver ()
@@ -40,10 +104,32 @@ Page_turn_engraver::Page_turn_engraver ()
   note_end_ = 0;
 }
 
+Grob*
+Page_turn_engraver::breakable_column (Page_turn_event const &brk)
+{
+  vsize start = lower_bound (breakable_moments_, brk.duration_[LEFT], less<Rational> ());
+  vsize end = upper_bound (breakable_moments_, brk.duration_[RIGHT], less<Rational> ());
+
+  if (start == breakable_moments_.size ())
+    return NULL;
+  if (end == breakable_moments_.size () || breakable_moments_[end] > brk.duration_[RIGHT])
+    {
+      if (end == 0)
+       return NULL;
+      end--;
+    }
+
+  for (vsize i = end + 1; i-- > start;)
+    if (special_barlines_[i])
+      return breakable_columns_[i];
+
+  return breakable_columns_[end];
+}
+
 Real
 Page_turn_engraver::penalty (Rational rest_len)
 {
-  Rational min_turn = robust_scm2moment (get_property ("minPageTurnLength"), Moment (1)).main_part_;
+  Rational min_turn = robust_scm2moment (get_property ("minimumPageTurnLength"), Moment (1)).main_part_;
 
   return (rest_len < min_turn) ? infinity_f : 0;
 }
@@ -62,10 +148,9 @@ Page_turn_engraver::acknowledge_note_head (Grob_info gi)
     {
       Real pen = penalty ((now_mom () - rest_begin_).main_part_);
       if (!isinf (pen))
-       {
-          SCM val = scm_cons (rest_begin_.smobbed_copy (), scm_from_double (pen));
-          context ()->get_score_context ()->set_property ("allowPageTurn", val);
-        }
+         automatic_breaks_.push_back (Page_turn_event (rest_begin_.main_part_,
+                                                       now_mom ().main_part_,
+                                                       ly_symbol2scm ("allow"), 0));
     }
 
   if (rest_begin_ <= repeat_begin_)
@@ -73,9 +158,59 @@ Page_turn_engraver::acknowledge_note_head (Grob_info gi)
   note_end_ = now_mom () + Moment (Duration (dur_log, dot_count).get_length ());
 }
 
+IMPLEMENT_TRANSLATOR_LISTENER (Page_turn_engraver, break);
+void
+Page_turn_engraver::listen_break (Stream_event *ev)
+{
+  string name = ly_scm2string (scm_symbol_to_string (ev->get_property ("class")));
+
+  if (name == "page-turn-event")
+    {
+      SCM permission = ev->get_property ("break-permission");
+      Real penalty = robust_scm2double (ev->get_property ("break-penalty"), 0);
+      Rational now = now_mom ().main_part_;
+
+      forced_breaks_.push_back (Page_turn_event (now, now, permission, penalty));
+    }
+}
+
+void
+Page_turn_engraver::start_translation_timestep ()
+{
+  /* What we want to do is to build a list of all the
+     breakable paper columns. In general, paper-columns won't be marked as
+     such until the Paper_column_engraver has done stop_translation_timestep.
+
+     Therefore, we just grab /all/ paper columns (in the
+     stop_translation_timestep, since they're not created here yet)
+     and remove the non-breakable ones at the beginning of the following
+     timestep.
+  */
+
+  if (breakable_columns_.size () && !Paper_column::is_breakable (breakable_columns_.back ()))
+    {
+      breakable_columns_.pop_back ();
+      breakable_moments_.pop_back ();
+      special_barlines_.pop_back ();
+    }
+}
+
 void
 Page_turn_engraver::stop_translation_timestep ()
 {
+  Grob *pc = unsmob_grob (get_property ("currentCommandColumn"));
+
+  if (pc)
+    {
+      breakable_columns_.push_back (pc);
+      breakable_moments_.push_back (now_mom ().main_part_);
+
+      SCM bar_scm = get_property ("whichBar");
+      string bar = robust_scm2string (bar_scm, "");
+
+      special_barlines_.push_back (bar != "" && bar != "|");
+    }
+
   /* C&P from Repeat_acknowledge_engraver */
   SCM cs = get_property ("repeatCommands");
   bool start = false;
@@ -92,17 +227,20 @@ Page_turn_engraver::stop_translation_timestep ()
 
   if (end && repeat_begin_.main_part_ >= Moment (0))
     {
+      Rational now = now_mom ().main_part_;
       Real pen = penalty ((now_mom () - rest_begin_).main_part_ + repeat_begin_rest_length_);
       Moment *m = unsmob_moment (get_property ("minimumRepeatLengthForPageTurn"));
       if (m && *m > (now_mom () - repeat_begin_))
        pen = infinity_f;
-      if (pen > 0)
-       {
-         SCM val = scm_cons (repeat_begin_.smobbed_copy (), scm_from_double (pen));
-         context ()->get_score_context ()->set_property ("revokePageTurns", val);
-       }
+
+      if (pen == infinity_f)
+       repeat_penalties_.push_back (Page_turn_event (repeat_begin_.main_part_, now, SCM_EOL, -infinity_f));
+      else
+       repeat_penalties_.push_back (Page_turn_event (repeat_begin_.main_part_, now, ly_symbol2scm ("allow"), pen));
+
       repeat_begin_ = Moment (-1);
     }
+
   if (start)
     {
       repeat_begin_ = now_mom ();
@@ -111,15 +249,92 @@ Page_turn_engraver::stop_translation_timestep ()
   rest_begin_ = note_end_;
 }
 
-#include "translator.icc"
+/* return the most permissive symbol (where force is the most permissive and
+   forbid is the least
+*/
+SCM
+Page_turn_engraver::max_permission (SCM perm1, SCM perm2)
+{
+  if (perm1 == SCM_EOL)
+    return perm2;
+  if (perm1 == ly_symbol2scm ("allow") && perm2 == ly_symbol2scm ("force"))
+    return perm2;
+  return perm1;
+}
+
+void
+Page_turn_engraver::finalize ()
+{
+  vsize rep_index = 0;
+  vector<Page_turn_event> auto_breaks;
+
+  /* filter the automatic breaks through the repeat penalties */
+  for (vsize i = 0; i < automatic_breaks_.size (); i++)
+    {
+      Page_turn_event &brk = automatic_breaks_[i];
+
+      /* find the next applicable repeat penalty */
+      for (;
+          rep_index < repeat_penalties_.size ()
+            && repeat_penalties_[rep_index].duration_[RIGHT] <= brk.duration_[LEFT];
+          rep_index++)
+       ;
+
+      if (rep_index >= repeat_penalties_.size ()
+         || brk.duration_[RIGHT] <= repeat_penalties_[rep_index].duration_[LEFT])
+       auto_breaks.push_back (brk);
+      else
+       {
+         vector<Page_turn_event> split = brk.penalize (repeat_penalties_[rep_index]);
+
+         /* it's possible that the last of my newly-split events overlaps the next repeat_penalty,
+            in which case we need to refilter that event */
+         if (rep_index < repeat_penalties_.size () - 1
+             && split.size ()
+             && split.back ().duration_[RIGHT] > repeat_penalties_[rep_index+1].duration_[LEFT])
+           {
+             automatic_breaks_[i] = split.back ();
+             split.pop_back ();
+             i--;
+           }
+         auto_breaks.insert (auto_breaks.end (), split.begin (), split.end ());
+       }
+    }
+
+  /* apply the automatic breaks */
+  for (vsize i = 0; i < auto_breaks.size (); i++)
+    {
+      Page_turn_event const &brk = auto_breaks[i];
+      Grob *pc = breakable_column (auto_breaks[i]);
+      if (pc)
+       {
+         SCM perm = max_permission (pc->get_property ("page-turn-permission"), brk.permission_);
+         Real pen = min (robust_scm2double (pc->get_property ("page-turn-penalty"), infinity_f), brk.penalty_);
+         pc->set_property ("page-turn-permission", perm);
+         pc->set_property ("page-turn-penalty", scm_from_double (pen));
+       }
+    }
+
+  /* apply the manual breaks */
+  for (vsize i = 0; i < forced_breaks_.size (); i++)
+    {
+      Page_turn_event const &brk = forced_breaks_[i];
+      Grob *pc = breakable_column (forced_breaks_[i]);
+      if (pc)
+       {
+         pc->set_property ("page-turn-permission", brk.permission_);
+         pc->set_property ("page-turn-penalty", scm_from_double (brk.penalty_));
+       }
+    }
+}
 
 ADD_ACKNOWLEDGER (Page_turn_engraver, note_head);
 ADD_TRANSLATOR (Page_turn_engraver,
                 /* doc */ "Decide where page turns are allowed to go",
                 /* create */ "",
                 /* accept */ "",
-                /* read */ "",
-                /* write */
-               "allowPageTurn "
-               "revokePageTurns "
+                /* read */
+               "minimumPageTurnLength "
+               "minimumRepeatLengthForPageTurn ",
+                /* write */ ""
                );
index 276834951175821cdd15b9f4e14c339c07a1b2f5..af67b67fe21d2a727a7328cec659c92aaa7ae189 100644 (file)
@@ -28,8 +28,6 @@ Paper_column_engraver::Paper_column_engraver ()
   musical_column_ = 0;
   breaks_ = 0;
   system_ = 0;
-  last_special_barline_column_ = 0;
-  last_breakable_column_ = 0;
   first_ = true;
 }
 
@@ -171,56 +169,6 @@ Paper_column_engraver::process_music ()
     }
 }
 
-/* return either
-   - the last column with a special (ie. not "|" or "") barline
-   - the last column
-   after the given moment
-*/
-Paper_column*
-Paper_column_engraver::find_turnable_column (Moment after_this)
-{
-  if (last_special_barline_column_)
-    {
-      Moment m = *unsmob_moment (last_special_barline_column_->get_property ("when"));
-      if (m >= after_this)
-       return last_special_barline_column_;
-    }
-  if (last_breakable_column_)
-    {
-      Moment m = *unsmob_moment (last_breakable_column_->get_property ("when"));
-      if (m >= after_this)
-       return last_breakable_column_;
-    }
-  return 0;
-}
-
-void
-Paper_column_engraver::revoke_page_turns (Moment after_this, Real new_penalty)
-{
-  if (!page_turnable_columns_.size ())
-    return;
-
-  for (vsize i = page_turnable_columns_.size () - 1; i--;)
-    {
-      Paper_column *col = page_turnable_columns_[i];
-      Moment mom = *unsmob_moment (col->get_property ("when"));
-      if (mom >= after_this)
-       {
-         if (isinf (new_penalty))
-           {
-             col->del_property ( ly_symbol2scm ("page-turn-permission"));
-             page_turnable_columns_.erase (page_turnable_columns_.begin () + i);
-           }
-         else
-           {
-             Real prev_pen = robust_scm2double (col->get_property ("page-turn-penalty"), 0);
-             if (new_penalty > prev_pen)
-               col->set_property ("page-turn-penalty", scm_from_double (new_penalty));
-           }
-       }
-    }
-}
-
 void
 Paper_column_engraver::stop_translation_timestep ()
 {
@@ -245,51 +193,12 @@ Paper_column_engraver::stop_translation_timestep ()
   else if (Paper_column::is_breakable (command_column_))
     {
       breaks_++;
-      last_breakable_column_ = command_column_;
-
-      SCM which_bar = get_property ("whichBar");
-      if (scm_is_string (which_bar))
-       {
-         string bar = ly_scm2string (which_bar);
-         if (bar != "" && bar != "|")
-           last_special_barline_column_ = command_column_;
-       }
 
       if (! (breaks_%8))
        progress_indication ("[" + to_string (breaks_) + "]");
     }
 
-  SCM page_br = get_property ("allowPageTurn");
-  if (scm_is_pair (page_br) && last_breakable_column_)
-    {
-      SCM pen = scm_cdr (page_br);
-      Moment *m = unsmob_moment (scm_car (page_br));
-      if (m)
-       {
-         Paper_column *turn = find_turnable_column (*m);
-         if (turn)
-           {
-             turn->set_property ("page-turn-permission", ly_symbol2scm ("allow"));
-             turn->set_property ("page-turn-penalty", pen);
-             page_turnable_columns_.push_back (turn);
-           }
-       }
-    }
-
-  /* The page-turn-engraver is allowed to change its mind and revoke previously-allowed
-     page turns (for example if there is a volta repeat where a turn is inconvenient) */
-  SCM revokes = get_property ("revokePageTurns");
-  if (scm_is_pair (revokes))
-    {
-      Moment *start = unsmob_moment (scm_car (revokes));
-      Real pen = robust_scm2double (scm_cdr (revokes), infinity_f);
-      if (start)
-       revoke_page_turns (*start, pen);
-    }
-
   context ()->get_score_context ()->unset_property (ly_symbol2scm ("forbidBreak"));
-  context ()->get_score_context ()->unset_property (ly_symbol2scm ("allowPageTurn"));
-  context ()->get_score_context ()->unset_property (ly_symbol2scm ("revokePageTurns"));
 
   first_ = false;
   break_events_.clear ();
@@ -326,13 +235,9 @@ ADD_TRANSLATOR (Paper_column_engraver,
                /* accept */ "break-event",
                /* read */
                 "forbidBreak "
-                "allowPageTurn "
-               "revokePageTurns "
                ,
                /* write */
                 "forbidBreak "
-                "allowPageTurn "
-               "revokePageTurns "
                "currentCommandColumn "
                "currentMusicalColumn "
                );
index 279cb376863840674ba5061d30d501b0cea56e17..9ec4901c857bbadcfd8d7673d8ed944232dd0ada 100644 (file)
@@ -133,7 +133,7 @@ get_help_string ()
     }
 
   string help ("Options supported by ly:set-option\n\n");
-  vector_sort (opts, string_compare);
+  vector_sort (opts, less<string> ());
   for (vsize i = 0; i < opts.size (); i++)
     help += opts[i];
 
index e10a7f0cc49fca061aa20925ca41d88a6edff31c..a2c9fa63c0e7e497ab6f22a6f1b9d7238384635c 100644 (file)
@@ -151,7 +151,7 @@ Rest_collision::calc_positioning_done (SCM smob)
 
       Direction d = LEFT;
       do
-       vector_sort (ordered_rests[d], Note_column::shift_compare);
+       vector_sort (ordered_rests[d], Note_column::shift_less);
       while (flip (&d) != LEFT)
        ;
 
index a7542249b119165e12008e018350fc7bfcb66fb0..055b377c72107416ea3f7080a8e47232164a62fa 100644 (file)
@@ -45,7 +45,7 @@ Semi_tie_column::calc_positioning_done (SCM smob)
   extract_grob_set (me, "ties", lv_ro_ties);
   vector<Grob*> lv_ties (lv_ro_ties);
 
-  vector_sort (lv_ties, &Semi_tie::compare);
+  vector_sort (lv_ties, Semi_tie::less);
 
   Ties_configuration ties_config;
   
index bddae0e2b2330ae7024803445b8609e0f2b7dad0..fbc98f20aa1db6eb6ce1c1a094c8cb4a44bc06bc 100644 (file)
@@ -70,10 +70,10 @@ Semi_tie::get_position (Grob *me)
   return (int) rint (Staff_symbol_referencer::get_position (h));
 }
 
-int
-Semi_tie::compare (Grob *const &s1,
-                            Grob *const &s2)
+bool
+Semi_tie::less (Grob *const &s1,
+               Grob *const &s2)
 {
-  return sign (get_position (s1) - get_position (s2));
+  return get_position (s1) < get_position (s2);
 }
                                 
index 84fe893a0c4b0287752e78185564c8ff6efcc0ae..5c1c76e85590febc2e757f56c731e54ff27c874f 100644 (file)
@@ -72,7 +72,7 @@ Span_bar::print (SCM smobbed_me)
   if (!model_bar)
     model_bar = me;
 
-  vector_sort (extents, Interval::left_comparison);
+  vector_sort (extents, Interval::left_less);
 
   Stencil span_bar;
   for (vsize i = 1; i < extents.size (); i++)
index f8726a864709386c9efdea83193d554150e4ebbd..77285e8ed12599b45120eec59d79f52ba431adb5 100644 (file)
@@ -124,7 +124,7 @@ Spanner::do_break_processing ()
            }
        }
     }
-  vector_sort (broken_intos_, Spanner::compare);
+  vector_sort (broken_intos_, Spanner::less);
   for (vsize i = broken_intos_.size (); i--;)
     broken_intos_[i]->break_index_ = i;
 }
@@ -238,7 +238,7 @@ Spanner::get_system () const
 Grob *
 Spanner::find_broken_piece (System *l) const
 {
-  vsize idx = binary_search (broken_intos_, (Spanner *)l, Spanner::less_than);
+  vsize idx = binary_search (broken_intos_, (Spanner *)l, Spanner::less);
   if (idx != VPOS)
     return broken_intos_ [idx];
   return 0;
@@ -251,7 +251,7 @@ Spanner::compare (Spanner *const &p1, Spanner *const &p2)
 }
 
 bool
-Spanner::less_than (Spanner *const &a, Spanner *const &b)
+Spanner::less (Spanner *const &a, Spanner *const &b)
 {
   return a->get_system ()->get_rank () < b->get_system ()->get_rank ();
 }
index 87e83fadad1523842f0cddf291c30c0715f6726c..aa45e55e7a4baf8c2b6bc0936fff409b98b3236b 100644 (file)
@@ -156,6 +156,13 @@ compare_position (Grob *const &a, Grob *const &b)
               - Staff_symbol_referencer::get_position ((Grob *) b));
 }
 
+bool
+position_less (Grob *const &a, Grob *const &b)
+{
+  return Staff_symbol_referencer::get_position (a)
+    < Staff_symbol_referencer::get_position (b);
+}
+
 ADD_INTERFACE (Staff_symbol_referencer, "staff-symbol-referencer-interface",
               "An object whose Y position is meant relative to a staff "
               "symbol. "
index d95ff4be3951c8ac7b6403a76fa0e09e09f2225e..6a0fb43485b42cde4af7e0c79d9e3cec368a79d0 100644 (file)
@@ -180,12 +180,6 @@ Stem::extremal_heads (Grob *me)
   return exthead;
 }
 
-static int
-integer_compare (int const &a, int const &b)
-{
-  return a - b;
-}
-
 /* The positions, in ascending order.  */
 vector<int>
 Stem::note_head_positions (Grob *me)
@@ -201,7 +195,7 @@ Stem::note_head_positions (Grob *me)
       ps.push_back (p);
     }
 
-  vector_sort (ps, integer_compare);
+  vector_sort (ps, less<int> ());
   return ps;
 }
 
@@ -410,7 +404,7 @@ Stem::calc_positioning_done (SCM smob)
 
   extract_grob_set (me, "note-heads", ro_heads);
   vector<Grob*> heads (ro_heads);
-  vector_sort (heads, compare_position);
+  vector_sort (heads, position_less);
   Direction dir = get_grob_direction (me);
 
   if (dir < 0)
index 54562cdc04be4608b83f0a4c8e48f6ff0772f8f2..07c705ffe6ba4dfb13f80531b532af5be32a5c99 100644 (file)
@@ -317,7 +317,7 @@ System::post_processing ()
      anyway. */
 
   vector<Grob*> all_elts_sorted (all_elements_->array ());
-  vector_sort (all_elts_sorted, default_compare);
+  vector_sort (all_elts_sorted, std::less<Grob*> ());
   uniq (all_elts_sorted);
   this->get_stencil ();
   for (vsize i = all_elts_sorted.size (); i--;)
@@ -357,7 +357,7 @@ System::get_paper_system ()
       entries.push_back (e); 
     }
 
-  vector_sort (entries, default_compare);
+  vector_sort (entries, std::less<Layer_entry> ());
   for (vsize j = 0; j < entries.size (); j++)
     {
       Grob *g = entries[j].grob_;
index e8384f18554e820e28462d678093ed8396c2a54a..13d5fb0177c1fba2577b293ee0e75c2cb8a3c7b3 100644 (file)
@@ -83,7 +83,7 @@ Tie_column::calc_positioning_done (SCM smob)
       return SCM_BOOL_T;
     }
   
-  vector_sort (ties, &Tie::compare);
+  vector_sort (ties, Tie::less);
 
   Tie_formatting_problem problem;
   problem.from_ties (ties);
index dada24694cb14f1f0c0673f61ed8e2f546bc29ca..d5bd961887a3f6f8d8c41aedc7179f22fda993e0 100644 (file)
@@ -219,7 +219,7 @@ Tie_formatting_problem::set_chord_outline (vector<Item*> bounds,
   for (vsize i = 0; i < bounds.size (); i++)
     ranks.push_back (bounds[i]->get_column ()->get_rank ());
 
-  vector_sort (ranks, default_compare);
+  vector_sort (ranks, less<int> ());
   uniq (ranks);
 
   for (vsize i = 0; i < ranks.size (); i++)
index 3f282071e77fe393bad531df74895ef3a97ef840..f6561fa576fb685dd3621110bddb07d1eeb27fe5 100644 (file)
 #include "warn.hh"
 
 
-int
-Tie::compare (Grob *const &s1,
-             Grob *const &s2)
+bool
+Tie::less (Grob *const &s1,
+          Grob *const &s2)
 {
-  return sign (Tie::get_position (s1) - Tie::get_position (s2));
+  return Tie::get_position (s1) < Tie::get_position (s2);
 }
 
 void
index 2eee74626affcc534b0198bc0f93487fef81e59b..7e2aca836c6d09bce34e962c12da04801276c582 100644 (file)
@@ -39,8 +39,6 @@
                                 "If true, then the accidentals are aligned in bass figure context.")
 
      (allowBeamBreak ,boolean? "If true allow line breaks for beams over bar lines.")
-     (allowPageTurn ,pair? "In the form (moment-start . penalty). Allow a page turn
-at the most recent breakpoint if it was after moment-start.")
      (associatedVoice ,string? "Name of the
 @code{Voice} that has the melody for this @code{Lyrics} line.")
      (autoBeamSettings ,list? "Specifies
@@ -313,6 +311,9 @@ markup.  Called with 2 arguments, event and context.")
      (midiMaximumVolume ,number? "Analogous to @code{midiMinimumVolume}.")
      (minimumFret ,number? "The tablature auto string-selecting mechanism
 selects the highest string with a fret at least @code{minimumFret}")
+     (minimumPageTurnLength ,ly:moment? "Minimum length of a rest for a page turn to be allowed")
+     (minimumRepeatLengthForPageTurn ,ly:moment? "Minimum length of a repeated section for a page
+turn to be allowed within that section")
      (minimumVerticalExtent ,number-pair? "minimum vertical extent, same
 format as @var{verticalExtent}")
      (output ,ly:music-output? "The output produced by a score-level translator during music interpretation")
@@ -346,7 +347,6 @@ whether they are processed in this context.")
      (restNumberThreshold ,number?
                          "If a multimeasure rest has more measures
 than this, a number is printed. ")
-     (revokePageTurns ,pair? "Signals to the paper-column-engraver to revoke (or increase the penalties for) all the page turns within a time interval. Used to disable page turns that occur within an unturnable volta repeat.")
      (shapeNoteStyles ,vector? "Vector of symbols, listing style for each note
 head relative to the tonic (qv.) of the scale.")
      (shortInstrumentName ,markup? "See @code{instrument}")
index 41ded2f8719b61319ed51ded6c15b67a70494305..bfed38e04d9aa202751169e2accfb7bcbd9427c7 100644 (file)
@@ -104,17 +104,10 @@ Syntax for manual control:
 c8-[ c c-] c8")
        (types . (general-music event beam-event span-event))
        ))
-
     (BendAfterEvent
      . ((description . "A drop/fall/doit jazz articulation")
        (types . (general-music bend-after-event event))))
 
-    (BreakEvent
-     . (
-       (description .  "Create a line break, Syntax: \\break or page break, Syntax: \\pagebreak.")
-       
-       (types . (general-music break-event event))
-       ))
     (BreathingEvent
      . (
        (description .  "Creates a `breath mark' or `comma'.  
@@ -343,12 +336,12 @@ SYNTAX
     (PageBreakEvent
      . (
        (description .  "Allow, forbid or force a page break.")
-       (types . (general-music break-event event))
+       (types . (general-music break-event page-break-event event))
        ))
     (PageTurnEvent
      . (
        (description .  "Allow, forbid or force a page turn.")
-       (types . (general-music break-event event))
+       (types . (general-music break-event page-turn-event event))
        ))
     (PartCombineMusic
      . (