]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge branch 'master' into jneeman
authorJoe Neeman <joeneeman@gmail.com>
Wed, 4 Jul 2007 09:32:22 +0000 (19:32 +1000)
committerJoe Neeman <joeneeman@gmail.com>
Wed, 4 Jul 2007 09:32:22 +0000 (19:32 +1000)
60 files changed:
Documentation/user/advanced-notation.itely
input/regression/dynamics-hairpin-length.ly
input/regression/fill-line-test.ly
input/regression/finger-chords.ly
input/regression/spacing-accidental-stretch.ly
input/regression/spacing-bar-arpeggio.ly
lily/accidental-engraver.cc
lily/accidental-placement.cc
lily/arpeggio-engraver.cc
lily/axis-group-interface.cc
lily/dot-column.cc
lily/dynamic-engraver.cc
lily/grob.cc
lily/include/accidental-placement.hh
lily/include/note-column.hh
lily/include/note-spacing.hh
lily/include/paper-column.hh
lily/include/separating-group-spanner.hh [deleted file]
lily/include/separation-item.hh
lily/include/simple-spacer.hh
lily/include/spaceable-grob.hh
lily/include/spacing-interface.hh
lily/include/spacing-options.hh
lily/include/spacing-spanner.hh
lily/include/spring.hh
lily/include/staff-spacing.hh
lily/multi-measure-rest-engraver.cc
lily/multi-measure-rest.cc
lily/note-collision.cc
lily/note-column.cc
lily/note-spacing-engraver.cc
lily/note-spacing.cc
lily/paper-column-engraver.cc
lily/paper-column.cc
lily/rhythmic-column-engraver.cc
lily/separating-group-spanner.cc [deleted file]
lily/separating-line-group-engraver.cc
lily/separation-item.cc
lily/simple-spacer-scheme.cc
lily/simple-spacer.cc
lily/skyline.cc
lily/slur-engraver.cc
lily/spaceable-grob.cc
lily/spacing-basic.cc
lily/spacing-determine-loose-columns.cc
lily/spacing-interface.cc [new file with mode: 0644]
lily/spacing-loose-columns.cc
lily/spacing-options.cc
lily/spacing-spanner.cc
lily/spring-smob.cc
lily/spring.cc [new file with mode: 0644]
lily/staff-spacing.cc
lily/system.cc
lily/tie-engraver.cc
lily/tie-formatting-problem.cc
ly/engraver-init.ly
scm/define-context-properties.scm
scm/define-grob-properties.scm
scm/define-grobs.scm
scm/safe-lily.scm

index e7cd36b3a22c72657594ad0ba658d4b9a4c9c285..726f66c7106965b0b8b54fef954b46dd22e23dd1 100644 (file)
@@ -354,15 +354,15 @@ bar lines,
   c1
   \key cis \major
   \clef alto
-  \override Score.RehearsalMark #'break-align-symbol = #'key-signature
+  \override Score.RehearsalMark #'break-align-symbols = #'(key-signature)
   \mark "on key"
   cis
   \key ces \major
-  \override Score.RehearsalMark #'break-align-symbol = #'clef
+  \override Score.RehearsalMark #'break-align-symbols = #'(clef)
   \clef treble
   \mark "on clef"
   ces
-  \override Score.RehearsalMark #'break-align-symbol = #'time-signature
+  \override Score.RehearsalMark #'break-align-symbols = #'(time-signature)
   \key d \minor
   \clef tenor
   \time 3/4
@@ -371,6 +371,35 @@ bar lines,
 }
 @end lilypond
 
+The text marks will, by default, be aligned with the middle of the notation
+object, but this can be changed by overriding the
+@code{break-align-anchor-alignment} and
+@code{break-align-anchor} properties for the appropriate grob.
+
+@lilypond[fragment,quote,ragged-right,verbatim]
+{
+  \override Score.RehearsalMark #'break-align-symbols = #'(key-signature)
+  c1
+  \key cis \major
+
+  % the RehearsalMark will be aligned with the left edge of the KeySignature
+  \once \override Staff.KeySignature #'break-align-anchor-alignment = #LEFT
+  \mark \default
+  cis1
+  \key ces \major
+
+  % the RehearsalMark will be aligned with the right edge of the KeySignature
+  \once \override Staff.KeySignature #'break-align-anchor-alignment = #RIGHT
+  \mark \default
+  ces1
+
+  % the RehearsalMark will be aligned with the right edge of the KeySignature
+  % and then shifted right by an additional 2 units.
+  \once \override Staff.KeySignature #'break-align = #2
+  \mark \default
+  ces1
+}
+
 Although text marks are normally only printed above the topmost
 staff, you may alter this to print them on every staff,
 
index ef00c6418f2e59d41cb1bf21fac067cc359e9401..c7f280bfc6d79f56876ca88b2870b3196f280a52 100644 (file)
@@ -1,7 +1,7 @@
 \header {
 
     texidoc = "Hairpins extend to the extremes of the bound if there
-    is no adjacent hairpin of dynamic-text.  If there is, the hairpin
+    is no adjacent hairpin or dynamic-text.  If there is, the hairpin
     extends to the center of the column or the bound of the text
     respectively."
 
index 888390e655830d7c9592b0af78fb967c487705e1..66b9512642470e863168834650fd8cd13719933a 100644 (file)
@@ -3,7 +3,7 @@
 \header {
 
   texidoc = "The fill-line markup command should align texts in
-  columns. For examlpe, the characters in the center should form one
+  columns. For example, the characters in the center should form one
   column."
 
 }
index bf000a70618166cab12c8f168b8a509848ed8d01..3b966ebd72703247ce18a11e5867f598c9fa7dc6 100644 (file)
@@ -2,7 +2,7 @@
 \version "2.10.0"
 \header {
 
-  texidoc = "With the new chord syntax, it is possible to associate
+  texidoc = "It is possible to associate
 fingerings uniquely with notes. This makes it possible to add
 horizontal fingerings to notes.
 
index f8f6bb41aea9b4031e6db45ec8fa642233599386..f862dc8a2fd26c200c7acd2f7455f6610d999130 100644 (file)
@@ -11,7 +11,7 @@ The accidental does add a little non-stretchable space.
 \layout {
   line-width = 18.\cm
 }
-\relative c'' \context GrandStaff {
+\relative c'' {
   #(set-accidental-style 'piano-cautionary)
   \time 2/4 
   d16 d d d d d cis d dis dis dis dis 
index fd84be5a9b3f20332f3f6169b01bc9d9e407e8d9..8318b5f24a1fdcbf3b3f7585fcd32926b58252e1 100644 (file)
@@ -12,5 +12,5 @@
   \override Score.NonMusicalPaperColumn #'layer = #1
   
   s1
-  <b' c'' c'>1\arpeggio
+  <b' c'' c'>2\arpeggio
 }
index 351ab2045a035df90825c9ce8edd99c973b05d8f..910c62d282040d55021db4cca8703f4bcdd0520c 100644 (file)
@@ -17,6 +17,7 @@
 #include "pitch.hh"
 #include "protected-scm.hh"
 #include "rhythmic-head.hh"
+#include "separation-item.hh"
 #include "side-position-interface.hh"
 #include "stream-event.hh"
 #include "tie.hh"
@@ -64,6 +65,7 @@ protected:
   void acknowledge_arpeggio (Grob_info);
   void acknowledge_rhythmic_head (Grob_info);
   void acknowledge_finger (Grob_info);
+  void acknowledge_note_column (Grob_info);
 
   void stop_translation_timestep ();
   void process_acknowledged ();
@@ -81,6 +83,7 @@ public:
 
   vector<Accidental_entry> accidentals_;
   vector<Spanner*> ties_;
+  vector<Grob*> note_columns_;
 };
 
 /*
@@ -521,6 +524,10 @@ Accidental_engraver::stop_translation_timestep ()
        }
     }
 
+  if (accidental_placement_)
+    for (vsize i = 0; i < note_columns_.size (); i++)
+      Separation_item::add_conditional_item (note_columns_[i], accidental_placement_);
+
   accidental_placement_ = 0;
   accidentals_.clear ();
   left_objects_.clear ();
@@ -558,6 +565,12 @@ Accidental_engraver::acknowledge_tie (Grob_info info)
   ties_.push_back (dynamic_cast<Spanner *> (info.grob ()));
 }
 
+void
+Accidental_engraver::acknowledge_note_column (Grob_info info)
+{
+  note_columns_.push_back (info.grob ());
+}
+
 void
 Accidental_engraver::acknowledge_arpeggio (Grob_info info)
 {
@@ -582,6 +595,7 @@ ADD_ACKNOWLEDGER (Accidental_engraver, arpeggio);
 ADD_ACKNOWLEDGER (Accidental_engraver, finger);
 ADD_ACKNOWLEDGER (Accidental_engraver, rhythmic_head);
 ADD_ACKNOWLEDGER (Accidental_engraver, tie);
+ADD_ACKNOWLEDGER (Accidental_engraver, note_column);
 
 ADD_TRANSLATOR (Accidental_engraver,
                
index 8e75206dc81bafeb5da5451d625ac70b4d1ca8aa..bb1419977ef262fb9ef7a4fada49be8362c15e87 100644 (file)
@@ -76,54 +76,23 @@ Accidental_placement::split_accidentals (Grob *accs,
 }
 
 vector<Grob*>
-Accidental_placement::get_break_reminder_accidentals (vector<Grob*> const &elts, Grob *left)
+Accidental_placement::get_relevant_accidentals (vector<Grob*> const &elts, Grob *left)
 {
   vector<Grob*> br;
   vector<Grob*> ra;
   vector<Grob*> ret;
-
-  if (dynamic_cast<Item *> (left)->break_status_dir () != RIGHT)
-    return vector<Grob*> ();
+  bool right = dynamic_cast<Item *> (left)->break_status_dir () == RIGHT;
 
   for (vsize i = 0; i < elts.size (); i++)
     {
       split_accidentals (elts[i], &br, &ra);
-      ret.insert (ret.end (), br.begin (), br.end ());
-    }
-  return ret;
-}
-
-/*
-  Accidentals are special, because they appear and disappear after
-  ties at will.
-*/
-Interval
-Accidental_placement::get_relevant_accidental_extent (Grob *me,
-                                                     Item *item_col,
-                                                     Grob *left_object)
-{
-  vector<Grob*> br, ra;
-  vector<Grob*> *which = 0;
-
-  Accidental_placement::split_accidentals (me, &br, &ra);
-  concat (br, ra);
-
-  if (dynamic_cast<Item *> (left_object)->break_status_dir () == RIGHT)
-    which = &br;
-  else
-    which = &ra;
-
-  Interval extent;
-  for (vsize i = 0; i < which->size (); i++)
-    extent.unite (which->at (i)->extent (item_col, X_AXIS));
+      
+      ret.insert (ret.end (), ra.begin (), ra.end ());
 
-  if (!extent.is_empty ())
-    {
-      Real p = robust_scm2double (me->get_property ("left-padding"), 0.2);
-      extent[LEFT] -= p;
+      if (right)
+       ret.insert (ret.end (), br.begin (), br.end ());
     }
-
-  return extent;
+  return ret;
 }
 
 struct Accidental_placement_entry
index 0528f71d9f576b644c3cd730c17e26b6903e5fee..399823408f88d501a246a97a3ae5cd54fa321ce2 100644 (file)
@@ -26,7 +26,6 @@ public:
 
   void acknowledge_stem (Grob_info);
   void acknowledge_rhythmic_head (Grob_info);
-  void acknowledge_note_column (Grob_info);
 protected:
   void process_music ();
   void stop_translation_timestep ();
@@ -73,13 +72,6 @@ Arpeggio_engraver::acknowledge_rhythmic_head (Grob_info info)
     Side_position_interface::add_support (arpeggio_, info.grob ());
 }
 
-void
-Arpeggio_engraver::acknowledge_note_column (Grob_info info)
-{
-  if (arpeggio_)
-    info.grob ()->set_object ("arpeggio", arpeggio_->self_scm ());
-}
-
 void
 Arpeggio_engraver::process_music ()
 {
@@ -98,7 +90,6 @@ Arpeggio_engraver::stop_translation_timestep ()
 
 ADD_ACKNOWLEDGER (Arpeggio_engraver, stem);
 ADD_ACKNOWLEDGER (Arpeggio_engraver, rhythmic_head);
-ADD_ACKNOWLEDGER (Arpeggio_engraver, note_column);
 
 ADD_TRANSLATOR (Arpeggio_engraver,
                /* doc */ "Generate an Arpeggio symbol",
index da08f53526eb4f1fa333df1126cd3ccdb77478c1..b9641d41c3ec735ebacdb447b5bcbc5beab3fc7c 100644 (file)
@@ -478,7 +478,7 @@ add_boxes (Grob *me, Grob *x_common, Grob *y_common, vector<Box> *const boxes, S
    positions, one for above the staff, one for below).
 
    In each pass, we loop through the unplaced grobs from left to right.
-   If the grob overlaps the right-most affected position, we place it
+   If the grob doesn't overlap the right-most affected position, we place it
    (and then update the right-most affected position to point to the right
    edge of the just-placed grob).  Otherwise, we skip it until the next pass.
 */
index 36c95137970240f526faff57515c68e8f7753f07..1698ef51eb8aa98da084c4804fd27b170f9a497b 100644 (file)
@@ -36,6 +36,13 @@ Dot_column::calc_positioning_done (SCM smob)
 {
   Grob *me = unsmob_grob (smob);  
 
+  /*
+    Trigger note collision resolution first, since that may kill off
+    dots when merging.
+  */
+  if (Grob *collision = unsmob_grob (me->get_object ("note-collision")))
+    (void) collision->get_property ("positioning-done");
+
   me->set_property ("positioning-done", SCM_BOOL_T);
 
   vector<Grob*> dots
@@ -45,24 +52,19 @@ Dot_column::calc_positioning_done (SCM smob)
   Real ss = 0;
 
   Grob *commonx = me;
-  { /*
-      Trigger note collision resolution first, since that may kill off
-      dots when merging.
-    */
-    for (vsize i = 0; i < dots.size (); i++)
-      {
-       Grob *n = dots[i]->get_parent (Y_AXIS);
-       commonx = n->common_refpoint (commonx, X_AXIS);
-
-       if (Grob *stem = unsmob_grob (n->get_object("stem")))
-         {
-           commonx = stem->common_refpoint (commonx, X_AXIS);
-
-           if (Stem::first_head (stem) == n)
-             main_heads.push_back (n);
-         }
-      }
-  }
+  for (vsize i = 0; i < dots.size (); i++)
+    {
+      Grob *n = dots[i]->get_parent (Y_AXIS);
+      commonx = n->common_refpoint (commonx, X_AXIS);
+      
+      if (Grob *stem = unsmob_grob (n->get_object("stem")))
+       {
+         commonx = stem->common_refpoint (commonx, X_AXIS);
+         
+         if (Stem::first_head (stem) == n)
+           main_heads.push_back (n);
+       }
+    }
 
   vector<Box> boxes;
   set<Grob*> stems;
index 18ebeda94301a50fa6bf962f50da52b6dd633a09..5de751602481e8e732951b1ceabbc8f6b1b5320c 100644 (file)
@@ -344,16 +344,9 @@ Dynamic_engraver::typeset_all ()
          || use_bar)
        {
                  
-         Grob *column_bound = 0;
-         if (use_bar)
-           {
-             column_bound = unsmob_grob (get_property ("breakableSeparationItem"));
-           }
-         
-         if (!column_bound)
-           column_bound = unsmob_grob (use_bar
-                                       ? get_property ("currentCommandColumn")
-                                       : get_property ("currentMusicalColumn"));
+         Grob *column_bound = unsmob_grob (use_bar
+                                           ? get_property ("currentCommandColumn")
+                                           : get_property ("currentMusicalColumn"));
          
          finished_cresc_->set_bound (RIGHT, script_
                                      ? script_
index 495fe2437f97cbddabfb90712d08afbc9c6f3928..34b742e7f576c6de8a5a63252312abd56540cf3b 100644 (file)
@@ -288,16 +288,23 @@ Grob::pure_relative_y_coordinate (Grob const *refp, int start, int end)
   Real off = 0;
 
   if (dim_cache_[Y_AXIS].offset_)
-    off = *dim_cache_[Y_AXIS].offset_;
+    {
+      if (to_boolean (get_property ("pure-Y-offset-in-progress")))
+       programming_error ("cyclic chain in pure-Y-offset callbacks");
+
+      off = *dim_cache_[Y_AXIS].offset_;
+    }
   else
     {
       SCM proc = get_property_data ("Y-offset");
 
       dim_cache_[Y_AXIS].offset_ = new Real (0.0);
+      set_property ("pure-Y-offset-in-progress", SCM_BOOL_T);
       off = robust_scm2double (call_pure_function (proc,
                                                   scm_list_1 (self_scm ()),
                                                   start, end),
                               0.0);
+      del_property ("pure-Y-offset-in-progress");
       delete dim_cache_[Y_AXIS].offset_;
       dim_cache_[Y_AXIS].offset_ = 0;
     }
@@ -625,6 +632,7 @@ ADD_INTERFACE (Grob,
               "outside-staff-horizontal-padding "
               "outside-staff-padding "
               "outside-staff-priority "
+              "pure-Y-offset-in-progress "
               "rotation "
               "springs-and-rods "
               "staff-symbol "
index f6c17621edb9f81c13143fb75bd49c3a79eb8301..99281a5b14b1dbbe2d0a415b05f892e21c368663 100644 (file)
@@ -18,11 +18,7 @@ public:
   DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element));
   static void add_accidental (Grob *, Grob *);
 
-  static vector<Grob*> get_break_reminder_accidentals (vector<Grob*> const &elts,
-                                                      Grob *left);
-  static Interval get_relevant_accidental_extent (Grob *me,
-                                                 Item *item_col,
-                                                 Grob *acc);
+  static vector<Grob*> get_relevant_accidentals (vector<Grob*> const &elts, Grob *left);
   static void split_accidentals (Grob *accs,
                                 vector<Grob*> *break_reminder,
                                 vector<Grob*> *real_acc);
index 8646f120fed818d568d7aa54b061602b326c09cf..34a30ab5ddaff3b5df7ea79b8970d8d6c0c8471e 100644 (file)
@@ -30,7 +30,6 @@ public:
   static Grob *first_head (Grob *me);
   static Grob *get_rest (Grob *me);
   static void set_stem (Grob *me, Grob *);
-  static void set_dotcol (Grob *me, Grob *);
   static void add_head (Grob *me, Grob *);
   static bool has_rests (Grob *me);
   static Grob *dot_column (Grob *me);
index af04260ceab39f07243c754a843efe938a7a3639..a14c43c8b79860e1acdcc1b3d1d41ab028068184 100644 (file)
 
 #include "grob-interface.hh"
 #include "lily-proto.hh"
+#include "spring.hh"
 
 class Note_spacing
 {
 public:
   DECLARE_GROB_INTERFACE();
 
-  static void get_spacing (Grob *me, Item *, Real, Real, Real *, Real *);
+  static Spring get_spacing (Grob *me, Item *, Real, Real);
   static void stem_dir_correction (Grob *me, Item *next_col, Real incr,
                                   Real *, Real *);
-  static Item *right_column (Grob *);
-  static Item *left_column (Grob *);
 };
 
 #endif /* NOTE_SPACING_HH */
index 0157eb6bb9a64079af671078cca25d0f2102e3a1..9109e4e6971fd18f3e23c8cb70bfc948a37182fd 100644 (file)
@@ -48,6 +48,7 @@ public:
   static Moment when_mom (Grob *);
   static bool is_used (Grob *);
   static bool is_breakable (Grob *);
+  static Real minimum_distance (Grob *l, Grob *r);
 };
 
 #endif // PAPER_COLUMN_HH
diff --git a/lily/include/separating-group-spanner.hh b/lily/include/separating-group-spanner.hh
deleted file mode 100644 (file)
index d48705c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-  separating-group-spanner.hh -- declare Separating_group_spanner
-
-  source file of the GNU LilyPond music typesetter
-
-  (c) 1998--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
-*/
-
-#ifndef SEPARATING_GROUP_SPANNER_HH
-#define SEPARATING_GROUP_SPANNER_HH
-
-#include "grob-interface.hh"
-#include "lily-proto.hh"
-
-class Separating_group_spanner
-{
-  static void find_rods (Item *,
-                        vector<Grob*> const &separators,
-                        vsize idx,
-                        Real);
-public:
-  static void add_spacing_unit (Grob *me, Item *);
-
-  DECLARE_GROB_INTERFACE();
-  DECLARE_SCHEME_CALLBACK (set_spacing_rods, (SCM));
-};
-
-#endif /* SEPARATING_GROUP_SPANNER_HH */
-
index 1b2471118dff16a64492f2b03bc75523988f2fe2..bf9681957ed36feae08351a3243d950f29a1cd57 100644 (file)
@@ -22,11 +22,9 @@ struct Separation_item
 
   static vector<Box> boxes (Grob *me, Grob *left);
   static Skyline conditional_skyline (Grob *, Grob *);
-  static Interval width (Grob *);
-  static Interval relative_width (Grob *, Grob *);
   static Grob *extremal_break_aligned_grob (Grob *, Direction, Interval *);
-  static bool set_distance (Drul_array<Item *>, Real);
-  static void set_skyline_distance (Drul_array<Item*>, Real);
+  static void set_distance (Drul_array<Item *>, Real);
+  static bool is_empty (Grob *me);
   static void add_item (Grob *, Item *);
   static void add_conditional_item (Grob *, Grob *);
 };
index ae3206ac5f70c0c75ae452e27542872e7eb90136..90784e4c743cff3b5692f95a36101698f977af36 100644 (file)
 
 #include "std-vector.hh"
 #include "lily-proto.hh"
+#include "spring.hh"
 #include "smobs.hh"
 
-struct Spring_description
-{
-  Real ideal_;
-  Real inverse_hooke_;
-  Real block_force_;
-
-  Real length (Real force) const;
-  Spring_description ();
-
-  bool is_sane () const;
-
-  bool operator> (const Spring_description &s) const
-  {
-    return block_force_ > s.block_force_;
-  }
-
-  bool operator< (const Spring_description &s) const
-  {
-    return block_force_ < s.block_force_;
-  }
-};
-
 class Simple_spacer
 {
 public:
@@ -42,9 +21,9 @@ public:
 
   void solve (Real line_len, bool ragged);
   void add_rod (int l, int r, Real dist);
-  void add_spring (Real, Real);
+  void add_spring (Spring const&);
   Real range_ideal_len (int l, int r) const;
-  Real range_stiffness (int l, int r) const;
+  Real range_stiffness (int l, int r, bool stretch) const;
   Real configuration_length (Real) const;
   vector<Real> spring_positions () const;
 
@@ -59,7 +38,7 @@ private:
   Real compress_line ();
   Real rod_force (int l, int r, Real dist);
 
-  vector<Spring_description> springs_;
+  vector<Spring> springs_;
   Real line_len_;
   Real force_;
   bool ragged_;
index 5625bfd61e7e66d2d7319aba512b79eef813c999..f7ae552f8402636dbf3b275e834fc29f2accceec 100644 (file)
 
 #include "lily-proto.hh"
 #include "grob-interface.hh"
+#include "spring.hh"
 
 struct Spaceable_grob
 {
   /// set a minimum distance
   static void add_rod (Grob *me, Grob *to, Real distance);
-  static void add_spring (Grob *me, Grob *to, Real dist, Real strength);
-  static void get_spring (Grob *me, Grob *other, Real *dist, Real *inv_strength);
+  static void add_spring (Grob *me, Grob *to, Spring sp);
+  static Spring get_spring (Grob *me, Grob *other);
 
   DECLARE_GROB_INTERFACE();
   static SCM get_minimum_distances (Grob *);
index b558ede709aa46f9a69ad54f9fc910c564c79938..14b8c2bf03c468fa9bdab9365a33d371b683e080 100644 (file)
@@ -8,8 +8,19 @@
 #include "grob-interface.hh"
 #include "lily-proto.hh"
 
+#ifndef SPACING_INTERFACE_HH
+#define SPACING_INTERFACE_HH
+
 struct Spacing_interface
 {
+  static Real minimum_distance (Grob *me, Grob *right_col);
+  static vector<Item*> right_note_columns (Grob *me);
+  static vector<Item*> left_note_columns (Grob *me);
+  static Item* right_column (Grob *me);
+  static Item* left_column (Grob *me);
+  static Drul_array<Skyline> skylines (Grob *me, Grob *right_col);
+
   DECLARE_GROB_INTERFACE();
 };
 
+#endif /* SPACING_INTERFACE_HH */
index 0b2d30b6640c255360ab9af752e84c52e3801ef4..c202c7d64d5f194017e77acd3b7bd6e99e47a3bd 100644 (file)
@@ -31,6 +31,6 @@ struct Spacing_options
   
   Spacing_options();
   void init_from_grob (Grob *me);
-  Real get_duration_space (Rational d, bool *) const;
+  Real get_duration_space (Rational d) const;
 };
 #endif /* SPACING_OPTIONS_HH */
index 3018cadebcfffdc4a375a4d6cdcd05edf8bda39d..9193a187d476324cc4fa5332239d7078efc1d596 100644 (file)
@@ -13,6 +13,7 @@
 #include "rational.hh"
 #include "std-vector.hh"
 #include "grob-interface.hh"
+#include "spring.hh"
 
 class Spacing_spanner
 {
@@ -23,7 +24,6 @@ private:
                                     Paper_column *nextr,
                                     Spacing_options const *options);
   static Real default_bar_spacing (Grob *, Grob *, Grob *, Moment);
-  static Real get_duration_space (Moment dur, Spacing_options const *, bool *);
   static Rational effective_shortest_duration (Grob *me, vector<Grob*> const &all);
   static void breakable_column_spacing (Grob *, Item *l, Item *r, Spacing_options const *);
   static void prune_loose_columns (Grob *, vector<Grob*> *cols, Spacing_options  *);
@@ -34,10 +34,8 @@ private:
   static bool fills_measure (Grob *, Item *, Item *);
 public:
   static vector<Grob*> get_columns (Grob *me);
-  static Real note_spacing (Grob *, Grob *, Grob *, Spacing_options const *, bool *);
-  static void standard_breakable_column_spacing (Grob *me, Item *l, Item *r,
-                                                Real *fixed, Real *space,
-                                                Spacing_options const *);
+  static Real note_spacing (Grob *, Grob *, Grob *, Spacing_options const *);
+  static Spring standard_breakable_column_spacing (Grob *me, Item *l, Item *r, Spacing_options const *);
   
   DECLARE_SCHEME_CALLBACK (set_springs, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_common_shortest_duration, (SCM));
index 11989b3ad03c6735fdf21e26afb4fb29a3f76578..4022173201f45d00852568d7f5e8cd0c181a5ef8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  spring.hh -- declare Spring, Column_spring
+  spring.hh -- declare Spring
 
   source file of the GNU LilyPond music typesetter
 
 #include "lily-proto.hh"
 #include "smobs.hh"
 
-struct Spring_smob
+class Spring
 {
-  Grob *other_;
   Real distance_;
-  bool expand_only_b_;
-  Real inverse_strength_;
+  Real min_distance_;
 
-  DECLARE_SIMPLE_SMOBS (Spring_smob);
-public:
-  Spring_smob ();
-};
-DECLARE_UNSMOB (Spring_smob, spring);
+  Real inverse_stretch_strength_;
+  Real inverse_compress_strength_;
 
-struct Spring
-{
-  Drul_array<Item *> item_drul_;
-  Real distance_;
-  bool expand_only_b_;
-
-  /*
-    TODO: make 2 strengths: one for stretching, and one for shrinking.
-  */
-  Real inverse_strength_;
-  void add_to_cols ();
-  void set_to_cols ();
+  Real blocking_force_;
+
+  void update_blocking_force ();
+
+  DECLARE_SIMPLE_SMOBS (Spring);
+public:
   Spring ();
+  Spring (Real distance, Real min_distance);
+
+  Real distance () const {return distance_;}
+  Real min_distance () const {return min_distance_;}
+  Real inverse_stretch_strength () const {return inverse_stretch_strength_;}
+  Real inverse_compress_strength () const {return inverse_compress_strength_;}
+  Real blocking_force () const {return blocking_force_;}
+  
+  Real length (Real f) const;
+
+  void set_distance (Real);
+  void set_min_distance (Real);
+  void set_inverse_stretch_strength (Real);
+  void set_inverse_compress_strength (Real);
+  void set_blocking_force (Real);
+  void set_default_strength ();
+
+  void operator*= (Real);
+  bool operator> (Spring const&) const;
 };
+DECLARE_UNSMOB (Spring, spring);
+
+Spring merge_springs (vector<Spring> const &springs);
 
 #endif /* SPRING_HH */
 
index b4241f2800b323363efc57cd57cc7d0a44b8dae4..9503c610ec4b59cb90094e6e29355e8d9cda8dc9 100644 (file)
 
 #include "lily-proto.hh"
 #include "grob-interface.hh"
+#include "spring.hh"
 
 class Staff_spacing
 {
+  static Real optical_correction (Grob *, Grob *, Interval);
+  static Real next_notes_correction (Grob *, Grob *);
+
 public:
-  static void next_notes_correction (Grob *, Grob *, Real, Real, Real *, Real *);
-  static void next_note_correction (Grob *, Grob *, Interval, Real, Real, Real*, Real *, int *);
   DECLARE_GROB_INTERFACE();
-  static void get_spacing_params (Grob *, Real *, Real *);
-
+  static Spring get_spacing (Grob *, Grob *right_col);
   static Interval bar_y_positions (Grob *);
 };
 
index c8ea549701b57a4537c7e4f387c632e278a05ca8..cf5f25a613f6099d70f76d91182a7b140694e5f1 100644 (file)
@@ -148,12 +148,13 @@ void
 Multi_measure_rest_engraver::stop_translation_timestep ()
 {
   /* We cannot do this earlier, as breakableSeparationItem is not yet
-     there.  */
+     there.
+
+     Actually, we no longer use breakableSeparationItem -- should this be moved?
+     -- jneem */
   if (bar_seen_)
     {
-      Grob *cmc = unsmob_grob (get_property ("breakableSeparationItem"));
-      if (!cmc)
-       cmc = unsmob_grob (get_property ("currentCommandColumn"));
+      Grob *cmc = unsmob_grob (get_property ("currentCommandColumn"));
 
       /* Ugh, this is a kludge - need this for multi-measure-rest-grace.ly  */
       last_command_item_ = dynamic_cast<Item *> (cmc);
index 1b66670a7c780bc05e22a2e0544edd17cc2d1852..279f2d011f2bc6a63d2ccf0294d727dc9e22ebbf 100644 (file)
@@ -79,9 +79,7 @@ Multi_measure_rest::print (SCM smob)
     {
       Item *b = sp->get_bound (d);
 
-      Interval coldim = (Separation_item::has_interface (b))
-       ? Separation_item::relative_width (b, common)
-       : b->extent (common, X_AXIS);
+      Interval coldim = b->extent (common, X_AXIS);
 
       sp_iv[d] = coldim.is_empty () ? b->relative_coordinate (common, X_AXIS) : coldim[-d];
     }
index 6feb71c8633f0e00f26e4f59c5bc32dbf44f4a20..8ee404cb067e5a0d1468ed69112a09d9b88f516a 100644 (file)
@@ -434,8 +434,7 @@ Note_collision_interface::get_clash_groups (Grob *me)
 */
 SCM
 Note_collision_interface::automatic_shift (Grob *me,
-                                          Drul_array < vector<Grob*>
-                                          > clash_groups)
+                                          Drul_array<vector<Grob*> > clash_groups)
 {
   Drul_array < vector<int> > shifts;
   SCM tups = SCM_EOL;
index 3f57d3e63c888b09fb564849aa3809b4307366b3..b1c6b9f272204417ddf050f2ebd1a2a036068bb4 100644 (file)
@@ -142,12 +142,6 @@ Note_column::translate_rests (Grob *me, int dy)
     }
 }
 
-void
-Note_column::set_dotcol (Grob *me, Grob *d)
-{
-  Axis_group_interface::add_element (me, d);
-}
-
 Grob *
 Note_column::first_head (Grob *me)
 {
index 569735f85920ea9b988087db6d9ca2fa9ab03fe2..68593604de12420214b390b78adda3536567e10c 100644 (file)
@@ -104,13 +104,13 @@ Note_spacing_engraver::stop_translation_timestep ()
 {
   if (last_spacing_
       && last_spacing_parent_context_
-      && last_spacing_parent_context_ == context ()->get_parent_context ())
+      && last_spacing_parent_context_ == context ()->get_parent_context ()
+      && to_boolean (get_property ("hasStaffSpacing")))
     {
-      Grob *sep = unsmob_grob (get_property ("breakableSeparationItem"));
-      if (sep)
-       Pointer_group_interface::add_grob (last_spacing_,
-                                          ly_symbol2scm ("right-items"),
-                                          sep);
+      Grob *col = unsmob_grob (get_property ("currentCommandColumn"));
+      Pointer_group_interface::add_grob (last_spacing_,
+                                        ly_symbol2scm ("right-items"),
+                                        col);
     }
   
   if (spacing_)
index 2839309ecb39c39aa065a1a2cc87b2693babb0dd..61af354f4cb1ebc161c289437a86e0333156db2a 100644 (file)
@@ -16,6 +16,7 @@
 #include "warn.hh"
 #include "stem.hh"
 #include "separation-item.hh"
+#include "spacing-interface.hh"
 #include "staff-spacing.hh"
 #include "accidental-placement.hh"
 #include "output-def.hh"
   spacing?
 */
 
-void
+Spring
 Note_spacing::get_spacing (Grob *me, Item *right_col,
-                          Real base_space, Real increment, Real *space, Real *fixed)
+                          Real base_space, Real increment)
 {
-  Drul_array<SCM> props (me->get_object ("left-items"),
-                        me->get_object ("right-items"));
-  Direction d = LEFT;
-  Direction col_dir = right_col->break_status_dir ();
-  Drul_array<Interval> extents;
+  vector<Item*> note_columns = Spacing_interface::left_note_columns (me);
+  Real left_head_end = 0;
 
-  Interval left_head_wid;
-  do
+  for (vsize i = 0; i < note_columns.size (); i++)
     {
-      vector<Grob*> const &items (ly_scm2link_array (props [d]));
-      for (vsize i = items.size (); i--;)
-       {
-         Item *it = dynamic_cast<Item *> (items[i]);
-
-         if (d == RIGHT && it->break_status_dir () != col_dir)
-           it = it->find_prebroken_piece (col_dir);
-
-         /*
-           some kind of mismatch, eg. a note column, that is behind a
-           linebreak.
-         */
-         if (!it)
-           continue;
-
-         Item *it_col = it->get_column ();
-         if (d == RIGHT && right_col != it_col)
-           continue;
-
-         if (Separation_item::has_interface (it))
-           {
-             extents[d].unite (Separation_item::width (it));
-             continue;
-           }
-
-         if (d == LEFT
-             && Note_column::has_interface (it))
-           {
-             SCM r = it->get_object ("rest");
-             Grob *g = unsmob_grob (r);
-             if (!g)
-               g = Note_column::first_head (it);
-
-             /*
-               Ugh. If Stem is switched off, we don't know what the
-               first note head will be.
-             */
-             if (g)
-               {
-                 if (g->common_refpoint (it_col, X_AXIS) != it_col)
-                   programming_error ("Note_spacing::get_spacing (): Common refpoint incorrect");
-                 else
-                   left_head_wid = g->extent (it_col, X_AXIS);
-               }
-           }
-
-         extents[d].unite (it->extent (it_col, X_AXIS));
-         if (d == RIGHT)
-           {
-             Grob *accs = Note_column::accidentals (it);
-             if (!accs)
-               accs = Note_column::accidentals (it->get_parent (X_AXIS));
-
-             if (accs)
-               {
-                 Interval v
-                   = Accidental_placement::get_relevant_accidental_extent (accs, it_col, me);
-
-                 extents[d].unite (v);
-               }
-
-             if (Grob *arpeggio = Note_column::arpeggio (it))
-               extents[d].unite (arpeggio->extent (it_col, X_AXIS));
-           }
-       }
-
-      if (extents[d].is_empty ())
-       extents[d] = Interval (0, 0);
+       SCM r = note_columns[i]->get_object ("rest");
+       Grob *g = unsmob_grob (r);
+       Grob *col = note_columns[i]->get_column ();
+
+       if (!g)
+        g = Note_column::first_head (note_columns[i]);
+
+       /*
+        Ugh. If Stem is switched off, we don't know what the
+        first note head will be.
+       */
+       if (g)
+        {
+          if (g->common_refpoint (col, X_AXIS) != col)
+            programming_error ("Note_spacing::get_spacing (): Common refpoint incorrect");
+          else
+            left_head_end = g->extent (col, X_AXIS)[RIGHT];
+        }
     }
-  while (flip (&d) != LEFT);
 
   /*
-    We look at the width of the note head, since smaller heads get less space
+    The main factor that determines the amount of space is the width of the
+    note head (or the rest). For example, a quarter rest gets almost 0.5 ss
+    less horizontal space than a note.
 
-    eg. a quarter rest gets almost 0.5 ss less horizontal space than a note.
-
-    What is sticking out of the note head (eg. a flag), doesn't get
-    the full amount of space.
-
-    FIXED also includes the left part of the right object.
+    The other parts of a note column (eg. flags, accidentals, etc.) don't get
+    the full amount of space. We give them half the amount of space, but then
+    adjust things so there are no collisions.
   */
-  *fixed
-    = (left_head_wid.is_empty () ? increment
-       :        /*
-                 Size of the head:
-               */
-       (left_head_wid[RIGHT]+
-
-       /*
-         What's sticking out of the head, eg. a flag:
-       */
-       (extents[LEFT][RIGHT] - left_head_wid[RIGHT]) / 2))
-
-    /*
-      What is sticking out on the left side of the right note:
-    */
-    + (extents[RIGHT].is_empty ()
-       ? 0.0
-       : ((- extents[RIGHT][LEFT] / 2)
-
-         /*
-           Add that which sticks out a lot.
-         */
-         + max (0.0, -extents[RIGHT][LEFT] - (base_space - 0.5 * increment))));
+  Drul_array<Skyline> skys = Spacing_interface::skylines (me, right_col);
+  Real min_dist = max (0.0, skys[LEFT].distance (skys[RIGHT]));
+  Real min_desired_space = left_head_end + (min_dist - left_head_end) / 2;
 
-  /*
-    We don't do complicated stuff: (base_space - increment) is the
-    normal amount of white, which also determines the amount of
-    stretch. Upon (extreme) stretching, notes with accidentals should
-    stretch as much as notes without accidentals.
-  */
-  *space = (base_space - increment) + *fixed;
+  /* if the right object sticks out a lot, include a bit of extra space.
+     But only for non-musical-columns; this shouldn't apply to accidentals */
+  if (!Paper_column::is_musical (right_col))
+    min_desired_space = max (min_desired_space,
+                            left_head_end + LEFT * skys[RIGHT].max_height ());
 
-#if 0
-  /*
-    The below situation is now handled by the "sticks out a lot" case
-    above. However we keep around the code for a few releases before
-    we drop it.
-   */
-  if (!extents[RIGHT].is_empty ()
-      && (Paper_column::is_breakable (right_col)))
-    {
-      /*
-       This is for the situation
+  Real ideal = base_space - increment + min_desired_space;
 
-       rest | 3/4 (eol)
+  stem_dir_correction (me, right_col, increment, &ideal, &min_desired_space);
 
-       Since we only take half of the right-object space above, the
-       barline will bump into the notes preceding it, if the right
-       thing is big. We add the rest of the extents here:
-      */
-
-      *space += -extents[RIGHT][LEFT] / 2;
-      *fixed += -extents[RIGHT][LEFT] / 2;
-    }
-#endif
-  
-  stem_dir_correction (me, right_col, increment, space, fixed);
+  Spring ret (ideal, min_dist);
+  ret.set_inverse_compress_strength (max (0.0, ideal - max (min_dist, min_desired_space)));
+  ret.set_inverse_stretch_strength (max (0.1, base_space - increment));
+  return ret;
 }
 
-Item *
-Note_spacing::left_column (Grob *me)
-{
-  if (!me->is_live ())
-    return 0;
-
-  return dynamic_cast<Item *> (me)->get_column ();
-}
-
-/*
-  Compute the column of the right-items.  This is a big function,
-  since RIGHT-ITEMS may span more columns (eg. if a clef if inserted,
-  this will add a new columns to RIGHT-ITEMS. Here we look at the
-  columns, and return the left-most. If there are multiple columns, we
-  prune RIGHT-ITEMS.
-*/
-Item *
-Note_spacing::right_column (Grob *me)
-{
-  if (!me->is_live ())
-    return 0;
-
-  Grob_array *a = unsmob_grob_array (me->get_object ("right-items"));
-  Item *mincol = 0;
-  int min_rank = INT_MAX;
-  bool prune = false;
-  for (vsize i = 0; a && i < a->size (); i++)
-    {
-      Item *ri = a->item (i);
-      Item *col = ri->get_column ();
-
-      int rank = Paper_column::get_rank (col);
-
-      if (rank < min_rank)
-       {
-         min_rank = rank;
-         if (mincol)
-           prune = true;
-
-         mincol = col;
-       }
-    }
-
-  if (prune && a)
-    {
-      vector<Grob*> &right = a->array_reference ();
-      for (vsize i = right.size (); i--;)
-       {
-         if (dynamic_cast<Item *> (right[i])->get_column () != mincol)
-           right.erase (right.begin () + i);
-       }
-    }
-
-  if (!mincol)
-    return 0;
-
-  return mincol;
-}
 
 /**
    Correct for optical illusions. See [Wanske] p. 138. The combination
    up-stem + down-stem should get extra space, the combination
    down-stem + up-stem less.
 
-   TODO: have to check wether the stems are in the same staff.
+   TODO: have to check whether the stems are in the same staff.
 */
 void
 Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn,
@@ -379,12 +227,7 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn,
              if (!head_extent.is_empty ())
                note_head_width = head_extent[RIGHT];
 
-             if (st)
-               {
-                 Real thick = Stem::thickness (st);
-
-                 note_head_width -= thick;
-               }
+             note_head_width -= Stem::thickness (st);
            }
 
          correction = note_head_width * stem_dirs[LEFT];
index 6ed851243d93809d2a6d226bd73faaf64d6cbb9c..1396c1280d94f8815e0ce6ba32f5ee26fd41bd52 100644 (file)
@@ -9,11 +9,13 @@
 #include "paper-column-engraver.hh"
 #include "system.hh"
 #include "international.hh"
+#include "accidental-placement.hh"
 #include "axis-group-interface.hh"
 #include "context.hh"
 #include "note-spacing.hh"
 #include "paper-column.hh"
 #include "pointer-group-interface.hh"
+#include "separation-item.hh"
 #include "staff-spacing.hh"
 #include "system.hh"
 #include "warn.hh"
@@ -192,12 +194,17 @@ Paper_column_engraver::stop_translation_timestep ()
   for (vsize i = 0; i < items_.size (); i++)
     {
       Item *elem = items_[i];
+      Grob *col = Item::is_non_musical (elem) ? command_column_ : musical_column_;
+
       if (!elem->get_parent (X_AXIS)
          || !unsmob_grob (elem->get_object ("axis-group-parent-X")))
        {
-         bool br = Item::is_non_musical (elem);
-         Axis_group_interface::add_element (br ? command_column_ : musical_column_, elem);
+         Axis_group_interface::add_element (col, elem);
        }
+      else if (Accidental_placement::has_interface (elem))
+       Separation_item::add_conditional_item (col, elem);
+      else
+       Separation_item::add_item (col, elem);
     }
   items_.clear ();
 
index 1578688925befd5e7eb9de5f68ab3fbfb3954529..bb827db18b72fe183cc0d7b9a59ea706710f572a 100644 (file)
@@ -22,6 +22,7 @@
 #include "system.hh"
 #include "spring.hh"
 #include "lookup.hh"
+#include "separation-item.hh"
 #include "string-convert.hh"
 
 Grob *
@@ -136,6 +137,24 @@ Paper_column::is_breakable (Grob *me)
   return scm_is_symbol (me->get_property ("line-break-permission"));
 }
 
+Real
+Paper_column::minimum_distance (Grob *left, Grob *right)
+{
+  Drul_array<Grob*> cols (left, right);
+  Drul_array<Skyline> skys = Drul_array<Skyline> (Skyline (RIGHT), Skyline (LEFT));
+
+  Direction d = LEFT;
+  do
+    {
+      Skyline_pair *sp = Skyline_pair::unsmob (cols[d]->get_property ("horizontal-skylines"));
+      if (sp)
+       skys[d] = (*sp)[-d];
+    }
+  while (flip (&d) != LEFT);
+
+  return max (0.0, skys[LEFT].distance (skys[RIGHT]));
+}
+
 /*
   Print a vertical line and  the rank number, to aid debugging.
 */
@@ -175,8 +194,9 @@ Paper_column::print (SCM p)
   for (SCM s = me->get_object ("ideal-distances");
        scm_is_pair (s); s = scm_cdr (s))
     {
-      Spring_smob *sp = unsmob_spring (scm_car (s));
-      if (!sp->other_->get_system ())
+      Spring *sp = unsmob_spring (scm_caar (s));
+      if (!unsmob_grob (scm_cdar (s))
+         || !unsmob_grob (scm_cdar (s))->get_system ())
        continue;
       
       j++;
@@ -184,7 +204,7 @@ Paper_column::print (SCM p)
       vector<Offset> pts;
       pts.push_back (Offset (0, y));
 
-      Offset p2 (sp->distance_, y);
+      Offset p2 (sp->distance (), y);
       pts.push_back (p2);
       
       Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
@@ -192,9 +212,9 @@ Paper_column::print (SCM p)
 
       SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (),
                                                           small_letters,
-                                                          ly_string2scm (String_convert::form_string ("%5.2lf", sp->distance_)));
+                                                          ly_string2scm (String_convert::form_string ("%5.2lf", sp->distance ())));
       
-      id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (sp->distance_/3, y+1)));
+      id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (sp->distance ()/3, y+1)));
       id_stencil.add_stencil (head.translated (p2));
       id_stencil = id_stencil.in_color (0,0,1);
       l.add_stencil (id_stencil);
index fc21e618eb202059a234c64e33e29101aed22721..827a6fb94ff2a621c6685d050a070085126f613b 100644 (file)
@@ -46,13 +46,14 @@ class Rhythmic_column_engraver : public Engraver
   Grob *stem_;
   Grob *note_column_;
   Grob *dotcol_;
+  Grob *arpeggio_;
 
   TRANSLATOR_DECLARATIONS (Rhythmic_column_engraver);
 protected:
 
-  DECLARE_ACKNOWLEDGER (dot_column);
   DECLARE_ACKNOWLEDGER (stem);
   DECLARE_ACKNOWLEDGER (rhythmic_head);
+  DECLARE_ACKNOWLEDGER (arpeggio);
   void process_acknowledged ();
   void stop_translation_timestep ();
 };
@@ -62,7 +63,7 @@ Rhythmic_column_engraver::Rhythmic_column_engraver ()
 
   stem_ = 0;
   note_column_ = 0;
-  dotcol_ = 0;
+  arpeggio_ = 0;
 }
 
 
@@ -72,30 +73,29 @@ Rhythmic_column_engraver::process_acknowledged ()
   if (rheads_.size ())
     {
       if (!note_column_)
-       {
-         note_column_ = make_item ("NoteColumn", rheads_[0]->self_scm ());
-       }
+       note_column_ = make_item ("NoteColumn", rheads_[0]->self_scm ());
 
       for (vsize i = 0; i < rheads_.size (); i++)
-       {
-         if (!rheads_[i]->get_parent (X_AXIS))
-           Note_column::add_head (note_column_, rheads_[i]);
-       }
+       if (!rheads_[i]->get_parent (X_AXIS))
+         Note_column::add_head (note_column_, rheads_[i]);
+
       rheads_.resize (0);
     }
 
   if (note_column_)
     {
-      if (dotcol_
-         && !dotcol_->get_parent (X_AXIS))
-       Note_column::set_dotcol (note_column_, dotcol_);
-
       if (stem_
          && !stem_->get_parent (X_AXIS))
        {
          Note_column::set_stem (note_column_, stem_);
          stem_ = 0;
        }
+
+      if (arpeggio_)
+       {
+         Pointer_group_interface::add_grob (note_column_, ly_symbol2scm ("elements"), arpeggio_);
+         note_column_->set_object ("arpeggio", arpeggio_->self_scm ());
+       }
     }
 }
 
@@ -112,22 +112,22 @@ Rhythmic_column_engraver::acknowledge_rhythmic_head (Grob_info i)
 }
 
 void
-Rhythmic_column_engraver::acknowledge_dot_column (Grob_info i)
+Rhythmic_column_engraver::acknowledge_arpeggio (Grob_info i)
 {
-  dotcol_ = i.grob ();
+  arpeggio_ = i.grob ();
 }
 
 void
 Rhythmic_column_engraver::stop_translation_timestep ()
 {
   note_column_ = 0;
-  dotcol_ = 0;
   stem_ = 0;
+  arpeggio_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Rhythmic_column_engraver, dot_column);
 ADD_ACKNOWLEDGER (Rhythmic_column_engraver, stem);
 ADD_ACKNOWLEDGER (Rhythmic_column_engraver, rhythmic_head);
+ADD_ACKNOWLEDGER (Rhythmic_column_engraver, arpeggio);
 
 ADD_TRANSLATOR (Rhythmic_column_engraver,
                /* doc */ "Generates NoteColumn, an objects that groups stems, noteheads and rests.",
diff --git a/lily/separating-group-spanner.cc b/lily/separating-group-spanner.cc
deleted file mode 100644 (file)
index 7de9341..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-  separating-group-spanner.cc -- implement Separating_group_spanner
-
-  source file of the GNU LilyPond music typesetter
-
-  (c) 1998--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
-*/
-
-#include "separating-group-spanner.hh"
-
-#include "separation-item.hh"
-#include "paper-column.hh"
-#include "output-def.hh"
-#include "dimensions.hh"
-#include "pointer-group-interface.hh"
-#include "moment.hh"
-
-void
-Separating_group_spanner::find_rods (Item *r,
-                                    vector<Grob*> const &separators,
-                                    vsize idx,
-                                    Real padding)
-{
-
-  /*
-    This is an inner loop: look for the first normal (unbroken) Left
-    grob.  This looks like an inner loop (ie. quadratic total), but in
-    most cases, the interesting L will just be the first entry of
-    NEXT, making it linear in most of the cases.
-  */
-  for (; idx != VPOS; idx--)
-    {
-      Item *l = dynamic_cast<Item *> (separators[idx]);
-      Item *lb = l->find_prebroken_piece (RIGHT);
-
-      if (lb)
-       {
-         Separation_item::set_distance (Drul_array<Item*> (lb, r), padding);
-       }
-
-      if (Separation_item::set_distance (Drul_array<Item *> (l, r), padding)
-         /*
-           This check is because grace notes are set very tight, and
-           the accidentals of main note may stick out so far to cover
-           a barline preceding the grace note.
-          */
-         && spanned_time_interval (l, r).length ().main_part_ > Rational (0))
-       break;
-
-      /*
-       this grob doesn't cause a constraint. We look further until we
-       find one that does.
-      */
-    }
-}
-
-MAKE_SCHEME_CALLBACK (Separating_group_spanner, set_spacing_rods, 1);
-SCM
-Separating_group_spanner::set_spacing_rods (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-
-  /*
-    Ugh: padding is added doubly, also for SeparationItem
-  */
-  Real padding = robust_scm2double (me->get_property ("padding"), 0.1);
-
-  extract_grob_set (me, "elements", elts);
-  for (vsize i = elts.size (); i-- > 1;)
-    {
-      Item *r = dynamic_cast<Item *> (elts[i]);
-      if (!r)
-       continue;
-
-      if (Separation_item::width (r).is_empty ())
-       continue;
-
-      Item *rb
-       = dynamic_cast<Item *> (r->find_prebroken_piece (LEFT));
-
-      find_rods (r, elts, i - 1, padding);
-      if (rb)
-       find_rods (rb, elts, i - 1, padding);
-    }
-
-  return SCM_UNSPECIFIED;
-}
-
-void
-Separating_group_spanner::add_spacing_unit (Grob *me, Item *i)
-{
-  Pointer_group_interface::add_unordered_grob (me, ly_symbol2scm ("elements"), i);
-}
-
-ADD_INTERFACE (Separating_group_spanner,
-              "A spanner that calculates spacing constraints (\"rods\") "
-              "using the @code{separation-item-interface} grobs in @code{elements}.",
-
-              /* properties */
-              "elements "
-              "padding ");
index f493840d9585290af83648a7c86c17e4f2f5a8b4..31bd53a2d53f39cb53a1ee78183b70fe5bc12db1 100644 (file)
@@ -8,7 +8,6 @@
 
 #include "engraver.hh"
 
-#include "separating-group-spanner.hh"
 #include "separation-item.hh"
 #include "paper-column.hh"
 #include "output-def.hh"
@@ -46,18 +45,10 @@ struct Spacings
 class Separating_line_group_engraver : public Engraver
 {
 protected:
-  Item *break_item_;
-  Item *musical_item_;
-  Item *last_musical_item_;
-
   Spacings current_spacings_;
   Spacings last_spacings_;
 
-  Spanner *sep_span_;
-
   DECLARE_ACKNOWLEDGER (item);
-  void process_music ();
-  virtual void finalize ();
   void stop_translation_timestep ();
   void start_translation_timestep ();
 public:
@@ -66,50 +57,12 @@ public:
 
 Separating_line_group_engraver::Separating_line_group_engraver ()
 {
-  sep_span_ = 0;
-  break_item_ = 0;
-  musical_item_ = 0;
-}
-
-void
-Separating_line_group_engraver::process_music ()
-{
-  if (!sep_span_)
-    {
-      sep_span_ = make_spanner ("SeparatingGroupSpanner", SCM_EOL);
-
-      sep_span_->set_bound (LEFT, unsmob_grob (get_property ("currentCommandColumn")));
-    }
-}
-void
-Separating_line_group_engraver::finalize ()
-{
-  if (!sep_span_)
-    return;
-
-  SCM ccol = get_property ("currentCommandColumn");
-  Grob *column = unsmob_grob (ccol);
-
-  sep_span_->set_bound (RIGHT, unsmob_grob (ccol));
-  sep_span_ = 0;
-
-  if (last_spacings_.staff_spacing_
-      && last_spacings_.staff_spacing_->get_column () == column)
-    last_spacings_.staff_spacing_->suicide ();
 }
 
 void
 Separating_line_group_engraver::acknowledge_item (Grob_info i)
 {
   Item *it = i.item ();
-  if (it->get_parent (X_AXIS)
-      && it->get_parent (X_AXIS) == it->get_parent (Y_AXIS)
-      && Axis_group_interface::has_axis (it->get_parent (X_AXIS), X_AXIS)
-      && Axis_group_interface::has_axis (it->get_parent (Y_AXIS), Y_AXIS))
-    return;
-
-  if (to_boolean (it->get_property ("no-spacing-rods")))
-    return;
 
   if (Note_spacing::has_interface (it))
     {
@@ -117,97 +70,61 @@ Separating_line_group_engraver::acknowledge_item (Grob_info i)
       return;
     }
 
-  bool ib = Item::is_non_musical (it);
-  Item *&p_ref_ (ib ? break_item_
-                : musical_item_);
-
-  if (!p_ref_)
+  if (Item::is_non_musical (it)
+      && !current_spacings_.staff_spacing_
+      && to_boolean (get_property ("createSpacing")))
     {
-      p_ref_ = make_item ("SeparationItem", SCM_EOL);
+      Grob *col = unsmob_grob (get_property ("currentCommandColumn"));
 
-      if (ib)
-       {
-         p_ref_->set_property ("non-musical", SCM_BOOL_T);
-         context ()->set_property ("breakableSeparationItem", p_ref_->self_scm ());
-       }
+      current_spacings_.staff_spacing_ = make_item ("StaffSpacing", SCM_EOL);
+      context ()->set_property ("hasStaffSpacing", SCM_BOOL_T);
 
-      if (to_boolean (get_property ("createSpacing"))
-         && p_ref_ == break_item_)
+      Pointer_group_interface::add_grob (current_spacings_.staff_spacing_,
+                                        ly_symbol2scm ("left-items"),
+                                        col);
+      
+      if (!last_spacings_.note_spacings_.size ()
+         && last_spacings_.staff_spacing_)
        {
-         Item *it = make_item ("StaffSpacing", SCM_EOL);
-         current_spacings_.staff_spacing_ = it;
-         Pointer_group_interface::add_grob (it, ly_symbol2scm ("left-items"),
-                                            break_item_);
-
-         if (!last_spacings_.note_spacings_.size ()
-             && last_spacings_.staff_spacing_)
+         SCM ri = last_spacings_.staff_spacing_->get_object ("right-items");
+         Grob_array *ga = unsmob_grob_array (ri);
+         if (!ga)
            {
-             SCM ri = last_spacings_.staff_spacing_->get_object ("right-items");
-             Grob_array *ga = unsmob_grob_array (ri);
-             if (!ga)
-               {
-                 SCM ga_scm = Grob_array::make_array ();
-                 last_spacings_.staff_spacing_->set_object ("right-items", ga_scm);
-                 ga = unsmob_grob_array (ga_scm);
-               }
-
-             ga->clear ();
-             ga->add (break_item_);
+             SCM ga_scm = Grob_array::make_array ();
+             last_spacings_.staff_spacing_->set_object ("right-items", ga_scm);
+             ga = unsmob_grob_array (ga_scm);
            }
+         
+         ga->clear ();
+         ga->add (col);
        }
     }
-
-  if (Accidental_placement::has_interface (it))
-    Separation_item::add_conditional_item (p_ref_, it);
-  else
-    Separation_item::add_item (p_ref_, it);
 }
 
 void
 Separating_line_group_engraver::start_translation_timestep ()
 {
-  if (break_item_)
-    {
-      context ()->unset_property (ly_symbol2scm ("breakableSeparationItem"));
-      break_item_ = 0;
-    }
+  context ()->unset_property (ly_symbol2scm ("hasStaffSpacing"));
 }
 
 void
 Separating_line_group_engraver::stop_translation_timestep ()
 {
-  if (break_item_)
-    Separating_group_spanner::add_spacing_unit (sep_span_, break_item_);
-
-  if (Item *sp = current_spacings_.staff_spacing_)
-    {
-      /*
-       TODO: should really look at the left-items of following
-       note-spacing grobs.
-      */
-      if (musical_item_)
-       Pointer_group_interface::add_grob (sp, ly_symbol2scm ("right-items"),
-                                          musical_item_);
-    }
-
   if (!current_spacings_.is_empty ())
     last_spacings_ = current_spacings_;
 
-  current_spacings_.clear ();
-
-  if (musical_item_)
-    Separating_group_spanner::add_spacing_unit (sep_span_, musical_item_);
+  if (Item *sp = current_spacings_.staff_spacing_)
+    if (Grob *col = unsmob_grob (get_property ("currentMusicalColumn")))
+      Pointer_group_interface::add_grob (sp, ly_symbol2scm ("right-items"), col);
 
-  musical_item_ = 0;
+  current_spacings_.clear ();
 }
 
 ADD_ACKNOWLEDGER (Separating_line_group_engraver, item);
 ADD_TRANSLATOR (Separating_line_group_engraver,
                /* doc */ "Generates objects for computing spacing parameters.",
 
-               /* create */
-               "SeparationItem "
-               "SeparatingGroupSpanner "
-               "StaffSpacing",
+               /* create */ "StaffSpacing",
                /* read */ "createSpacing",
-               /* write */ "breakableSeparationItem");
+               /* write */ "hasStaffSpacing"
+               );
index 8a83e2b7a1e2eefeec1b5bdbaa3e75281fd5b2c1..a692fc0b9b558b7e0b30d4419b96232d6aaefc2a 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "separation-item.hh"
 
+#include "axis-group-interface.hh"
 #include "lookup.hh"
 #include "stencil.hh"
 #include "skyline.hh"
@@ -30,7 +31,7 @@ Separation_item::add_conditional_item (Grob *me, Grob *e)
 }
 
 void
-Separation_item::set_skyline_distance (Drul_array<Item *> items,
+Separation_item::set_distance (Drul_array<Item *> items,
                                       Real padding)
 {
   Drul_array<Skyline_pair*> lines (Skyline_pair::unsmob (items[LEFT]->get_property ("horizontal-skylines")),
@@ -51,11 +52,10 @@ Separation_item::set_skyline_distance (Drul_array<Item *> items,
 }
 
 bool
-Separation_item::set_distance (Drul_array<Item *> items,
-                              Real padding)
+Separation_item::is_empty (Grob *me)
 {
-  set_skyline_distance (items, padding);
-  return true;
+  Skyline_pair *sky = Skyline_pair::unsmob (me->get_property ("horizontal-skylines"));
+  return (!sky || sky->is_empty ());
 }
 
 /*
@@ -97,7 +97,7 @@ Separation_item::boxes (Grob *me, Grob *left)
   vector<Grob*> elts;
 
   if (left)
-    elts = Accidental_placement::get_break_reminder_accidentals (read_only_elts, left);
+    elts = Accidental_placement::get_relevant_accidentals (read_only_elts, left);
   else
     elts = read_only_elts;
 
@@ -107,41 +107,27 @@ Separation_item::boxes (Grob *me, Grob *left)
     {
       Item *il = dynamic_cast<Item *> (elts[i]);
       if (pc != il->get_column ())
-       {
-         continue;
-       }
+       continue;
+      if (Axis_group_interface::has_interface (il))
+       continue;
 
       Interval y (il->pure_height (ycommon, 0, very_large));
       Interval x (il->extent (pc, X_AXIS));
 
       Interval extra = robust_scm2interval (elts[i]->get_property ("extra-spacing-width"),
-                                           Interval (0, 0));
+                                           Interval (-0.1, 0.1));
       x[LEFT] += extra[LEFT];
       x[RIGHT] += extra[RIGHT];
       if (to_boolean (elts[i]->get_property ("infinite-spacing-height")))
        y = Interval (-infinity_f, infinity_f);
  
+      if (!x.is_empty () && !y.is_empty ())
       out.push_back (Box (x, y));
     }
 
   return out;      
 }
 
-Interval
-Separation_item::width (Grob *me)
-{
-  SCM sw = me->get_property ("X-extent");
-  return ly_scm2interval (sw);
-}
-
-Interval
-Separation_item::relative_width (Grob *me, Grob *common)
-{
-  Interval iv = width (me);
-
-  return dynamic_cast<Item *> (me)->get_column ()->relative_coordinate (common, X_AXIS) + iv;
-}
-
 /*
   Try to find the break-aligned symbol in SEPARATION_ITEM that is
   sticking out at direction D. The x size is put in LAST_EXT
@@ -201,7 +187,7 @@ Separation_item::print (SCM smob)
 
 ADD_INTERFACE (Separation_item,
               "Item that computes widths to generate spacing rods. "
-              "This is done in concert with @ref{separating-group-spanner-interface}.",
+              ,
 
               "X-extent "
               "conditional-elements "
index fda38ab503bb41de7039116a15448f34b8a38525..48f127bfca5ae710b5778c73b343e6d08e994839 100644 (file)
@@ -44,7 +44,11 @@ LY_DEFINE (ly_solve_spring_rod_problem, "ly:solve-spring-rod-problem",
       Real ideal = scm_to_double (scm_caar (s));
       Real inv_hooke = scm_to_double (scm_cadar (s));
 
-      spacer.add_spring (ideal, inv_hooke);
+      Spring sp (ideal, 0.0);
+      sp.set_inverse_compress_strength (inv_hooke);
+      sp.set_inverse_stretch_strength (inv_hooke);
+
+      spacer.add_spring (sp);
     }
 
   for (SCM s = rods; scm_is_pair (s); s = scm_cdr (s))
index 04c35dd4e597f13a813301d61af4f4dafdba97c2..8e0722438e4195c7fa45a4cb544639dd9849079a 100644 (file)
@@ -80,8 +80,8 @@ Simple_spacer::fits () const
 Real
 Simple_spacer::rod_force (int l, int r, Real dist)
 {
-  Real c = range_stiffness (l, r);
   Real d = range_ideal_len (l, r);
+  Real c = range_stiffness (l, r, dist > d);
   Real block_stretch = dist - d;
   return c * block_stretch;
 }
@@ -102,13 +102,13 @@ Simple_spacer::add_rod (int l, int r, Real dist)
       Real spring_dist = range_ideal_len (l, r);
       if (spring_dist < dist)
        for (int i = l; i < r; i++)
-         springs_[i].ideal_ *= dist / spring_dist;
+         springs_[i].set_distance (springs_[i].distance () * dist / spring_dist);
 
       return;
     }
   force_ = max (force_, block_force);
   for (int i = l; i < r; i++)
-    springs_[i].block_force_ = max (block_force, springs_[i].block_force_);
+    springs_[i].set_blocking_force (max (block_force, springs_[i].blocking_force ()));
 }
 
 Real
@@ -116,16 +116,17 @@ Simple_spacer::range_ideal_len (int l, int r) const
 {
   Real d = 0.;
   for (int i = l; i < r; i++)
-    d += springs_[i].ideal_;
+    d += springs_[i].distance ();
   return d;
 }
 
 Real
-Simple_spacer::range_stiffness (int l, int r) const
+Simple_spacer::range_stiffness (int l, int r, bool stretch) const
 {
   Real den = 0.0;
   for (int i = l; i < r; i++)
-    den += springs_[i].inverse_hooke_;
+    den += stretch ? springs_[i].inverse_stretch_strength ()
+      : springs_[i].inverse_compress_strength ();
 
   return 1 / den;
 }
@@ -144,13 +145,10 @@ void
 Simple_spacer::solve (Real line_len, bool ragged)
 {
   Real conf = configuration_length (force_);
-  double inv_hooke = 0;
-  for (vsize i=0; i < springs_.size (); i++)
-    inv_hooke += springs_[i].inverse_hooke_;
 
   ragged_ = ragged;
   line_len_ = line_len;
-  if ((inv_hooke > 0) && (conf < line_len_))
+  if (conf < line_len_)
     force_ = expand_line ();
   else if (conf > line_len_)
     force_ = compress_line ();
@@ -167,7 +165,7 @@ Simple_spacer::expand_line ()
 
   fits_ = true;
   for (vsize i=0; i < springs_.size (); i++)
-    inv_hooke += springs_[i].inverse_hooke_;
+    inv_hooke += springs_[i].inverse_stretch_strength ();
 
   assert (cur_len <= line_len_);
   return (line_len_ - cur_len) / inv_hooke + force_;
@@ -179,39 +177,54 @@ Simple_spacer::compress_line ()
   double inv_hooke = 0;
   double cur_len = configuration_length (force_);
   double cur_force = force_;
+  bool compressed = false;
+
+  /* just because we are in compress_line () doesn't mean that the line
+     will actually be compressed (as in, a negative force) because
+     we start out with a stretched line. Here, we check whether we
+     will be compressed or stretched (so we know which spring constant to use) */
+  if (configuration_length (0.0) > line_len_)
+    {
+      cur_force = 0.0;
+      cur_len = configuration_length (0.0);
+      compressed = true;
+    }
 
   fits_ = true;
   for (vsize i=0; i < springs_.size (); i++)
-    inv_hooke += springs_[i].inverse_hooke_;
+    inv_hooke += compressed
+      ? springs_[i].inverse_compress_strength ()
+      : springs_[i].inverse_stretch_strength ();
 
   assert (line_len_ <= cur_len);
 
-  vector<Spring_description> sorted_springs = springs_;
-  sort (sorted_springs.begin (), sorted_springs.end (), greater<Spring_description> ());
+  vector<Spring> sorted_springs = springs_;
+  sort (sorted_springs.begin (), sorted_springs.end (), greater<Spring> ());
+
   for (vsize i = 0; i < sorted_springs.size (); i++)
     {
-      Spring_description sp = sorted_springs[i];
+      Spring sp = sorted_springs[i];
 
-      assert (sp.block_force_ <= cur_force);
-      if (isinf (sp.block_force_))
+      assert (sp.blocking_force () <= cur_force);
+      if (isinf (sp.blocking_force ()))
        break;
 
-      double block_dist = (cur_force - sp.block_force_) * inv_hooke;
+      double block_dist = (cur_force - sp.blocking_force ()) * inv_hooke;
       if (cur_len - block_dist < line_len_)
        {
-        cur_force += (line_len_ - cur_len) / inv_hooke;
-        cur_len = line_len_;
+         cur_force += (line_len_ - cur_len) / inv_hooke;
+         cur_len = line_len_;
 
-        /*
-          Paranoia check.
+         /*
+           Paranoia check.
          */
-        assert (fabs (configuration_length (cur_force) - cur_len) < 1e-6);
-        return cur_force;
+         assert (fabs (configuration_length (cur_force) - cur_len) < 1e-6);
+         return cur_force;
        }
       
       cur_len -= block_dist;
-      inv_hooke -= sp.inverse_hooke_;
-      cur_force = sp.block_force_;
+      inv_hooke -= sp.inverse_compress_strength ();
+      cur_force = sp.blocking_force ();
     }
 
   fits_ = false;
@@ -219,24 +232,10 @@ Simple_spacer::compress_line ()
 }
 
 void
-Simple_spacer::add_spring (Real ideal, Real inverse_hooke)
+Simple_spacer::add_spring (Spring const &sp)
 {
-  Spring_description description;
-
-  description.ideal_ = ideal;
-  description.inverse_hooke_ = inverse_hooke;
-  if (!description.is_sane ())
-    {
-      programming_error ("insane spring found, setting to unit");
-
-      description.inverse_hooke_ = 1.0;
-      description.ideal_ = 1.0;
-    }
-
-  description.block_force_ = -description.ideal_ / description.inverse_hooke_;
-  // block at distance 0
-
-  springs_.push_back (description);
+  force_ = max (force_, sp.blocking_force ());
+  springs_.push_back (sp);
 }
 
 vector<Real>
@@ -266,45 +265,6 @@ Simple_spacer::force_penalty (bool ragged) const
 
 /****************************************************************/
 
-Spring_description::Spring_description ()
-{
-  ideal_ = 0.0;
-  inverse_hooke_ = 0.0;
-  block_force_ = 0.0;
-}
-
-bool
-Spring_description::is_sane () const
-{
-  return (inverse_hooke_ >= 0)
-    && ideal_ >= 0
-    && !isinf (ideal_) && !isnan (ideal_)
-    && (inverse_hooke_ == 0.0 || fabs (inverse_hooke_) > 1e-8)
-    ;
-}
-
-Real
-Spring_description::length (Real f) const
-{
-  return ideal_ + max (f, block_force_) * inverse_hooke_;
-}
-
-/****************************************************************/
-
-/*
-  TODO: should a add penalty for widely varying spring forces (caused
-  by constraints, eg.
-
-
-  .     =====
-  .     |   |
-  .o|o|x ##x
-  .
-
-  The ## forces the notes apart; we shouldn't allow the O's to touch
-  this closely.
-*/
-
 struct Rod_description
 {
   vsize r_;
@@ -332,19 +292,14 @@ struct Column_description
 {
   vector<Rod_description> rods_;
   vector<Rod_description> end_rods_;   /* use these if they end at the last column of the line */
-  Real ideal_;
-  Real inverse_hooke_;
-  Real end_ideal_;
-  Real end_inverse_hooke_;
+  Spring spring_;
+  Spring end_spring_;
+
   SCM break_permission_;
   Interval keep_inside_line_;
 
   Column_description ()
   {
-    ideal_ = 0;
-    inverse_hooke_ = 0;
-    end_ideal_ = 0;
-    end_inverse_hooke_ = 0;
     break_permission_ = SCM_EOL;
   }
 };
@@ -383,10 +338,11 @@ get_column_description (vector<Grob*> const &cols, vsize col_index, bool line_st
   Column_description description;
   Grob *next_col = next_spaceable_column (cols, col_index);
   if (next_col)
-    Spaceable_grob::get_spring (col, next_col, &description.ideal_, &description.inverse_hooke_);
+    description.spring_ = Spaceable_grob::get_spring (col, next_col);
+
   Grob *end_col = dynamic_cast<Item*> (cols[col_index+1])->find_prebroken_piece (LEFT);
   if (end_col)
-    Spaceable_grob::get_spring (col, end_col, &description.end_ideal_, &description.end_inverse_hooke_);
+    description.end_spring_ = Spaceable_grob::get_spring (col, end_col);
 
   for (SCM s = Spaceable_grob::get_minimum_distances (col);
        scm_is_pair (s); s = scm_cdr (s))
@@ -447,8 +403,8 @@ get_line_forces (vector<Grob*> const &columns,
          Simple_spacer spacer;
 
          for (vsize i = breaks[b]; i < end - 1; i++)
-           spacer.add_spring (cols[i].ideal_, cols[i].inverse_hooke_);
-         spacer.add_spring (cols[end-1].end_ideal_, cols[end-1].end_inverse_hooke_);
+           spacer.add_spring (cols[i].spring_);
+         spacer.add_spring (cols[end-1].end_spring_);
 
 
          for (vsize i = breaks[b]; i < end; i++)
@@ -508,7 +464,7 @@ get_line_configuration (vector<Grob*> const &columns,
   for (vsize i = 0; i + 1 < ret.cols_.size (); i++)
     {
       cols.push_back (get_column_description (ret.cols_, i, i == 0));
-      spacer.add_spring (cols[i].ideal_, cols[i].inverse_hooke_);
+      spacer.add_spring (cols[i].spring_);
     }
   for (vsize i = 0; i < cols.size (); i++)
     {
index c935660c6ed33b400cdf2b002fc0a79f886474ab..de6f7d078bb706dfd35a3b1d4b71b501b41d8797 100644 (file)
@@ -530,7 +530,8 @@ Skyline::to_points (Axis horizon_axis) const
 bool
 Skyline::is_empty () const
 {
-  return buildings_.empty ();
+  Building b = buildings_.front ();
+  return b.end_ == infinity_f && b.y_intercept_ == -infinity_f;
 }
 
 Skyline_pair::Skyline_pair ()
index 9900ba713b48d086afdcdde7ba252232247a202b..57068e6225945da903f2a264840bc7124ded6f2a 100644 (file)
@@ -194,7 +194,7 @@ Slur_engraver::process_music ()
 void
 Slur_engraver::stop_translation_timestep ()
 {
-  if (Grob *g = unsmob_grob (get_property ("breakableSeparationItem")))
+  if (Grob *g = unsmob_grob (get_property ("currentCommandColumn")))
     {
       for (vsize i = 0; i < end_slurs_.size (); i++)
        Slur::add_extra_encompass (end_slurs_[i], g);
index 806e300cfa5ff714b4ffb9c38192ccae35aec3e4..87d30397e3ae48e4bf40976584eae0c0d1f16862 100644 (file)
@@ -56,69 +56,34 @@ Spaceable_grob::add_rod (Grob *me, Grob *p, Real d)
 }
 
 void
-Spaceable_grob::add_spring (Grob *me, Grob *other,
-                           Real distance, Real inverse_strength)
+Spaceable_grob::add_spring (Grob *me, Grob *other, Spring sp)
 {
-  if (distance < 0.0 || inverse_strength < 0.0)
-    {
-      programming_error ("adding reverse spring, setting to unit");
-      distance = 1.0;
-      inverse_strength = 1.0;
-    }
-
-  if (isinf (distance) || isnan (distance)
-      || isnan (inverse_strength))
-    {
-      /* strength == INF is possible. It means fixed distance.  */
-      programming_error ("insane distance found");
-      distance = 1.0;
-      inverse_strength = 1.0;
-    }
-
-#ifndef NDEBUG
-  SCM mins = me->get_object ("ideal-distances");
-  for (SCM s = mins; scm_is_pair (s); s = scm_cdr (s))
-    {
-      Spring_smob *sp = unsmob_spring (scm_car (s));
-      if (sp->other_ == other)
-       {
-         programming_error ("already have that spring");
-         return;
-       }
-    }
-#endif
-
-  Spring_smob spring;
-  spring.inverse_strength_ = inverse_strength;
-  spring.distance_ = distance;
-  spring.other_ = other;
-
   SCM ideal = me->get_object ("ideal-distances");
-  ideal = scm_cons (spring.smobbed_copy (), ideal);
+
+  ideal = scm_cons (scm_cons (sp.smobbed_copy (), other->self_scm ()), ideal);
   me->set_object ("ideal-distances", ideal);
 }
 
-void
-Spaceable_grob::get_spring (Grob *this_col, Grob *next_col, Real *dist, Real *inv_strength)
+Spring
+Spaceable_grob::get_spring (Grob *this_col, Grob *next_col)
 {
-  Spring_smob *spring = 0;
+  Spring *spring = 0;
 
   for (SCM s = this_col->get_object ("ideal-distances");
        !spring && scm_is_pair (s);
        s = scm_cdr (s))
     {
-      Spring_smob *sp = unsmob_spring (scm_car (s));
-
-      if (sp && sp->other_ == next_col)
-       spring = sp;
+      if (scm_is_pair (scm_car (s))
+         && unsmob_grob (scm_cdar (s)) == next_col
+         && unsmob_spring (scm_caar (s)))
+       spring = unsmob_spring (scm_caar (s));
     }
 
   if (!spring)
     programming_error (_f ("No spring between column %d and next one",
                           Paper_column::get_rank (this_col)));
 
-  *dist = (spring) ? spring->distance_ : 5.0;
-  *inv_strength = (spring) ? spring->inverse_strength_ : 1.0;
+  return spring ? *spring : Spring ();
 }
 
 
index e0d9daaa00d7365b928b40885c014d7fd8d6d2e8..bed086a72cefab0672589b0042cfb0e5f3bb1f14 100644 (file)
@@ -14,6 +14,8 @@
 #include "warn.hh"
 #include "pointer-group-interface.hh"
 #include "system.hh"
+#include "spacing-interface.hh"
+#include "spring.hh"
 
 /*
   LilyPond spaces by taking a simple-minded spacing algorithm, and
   The one-size-fits all spacing. It doesn't take into account
   different spacing wishes from one to the next column.
 */
-void
-Spacing_spanner::standard_breakable_column_spacing (Grob *me, Item *l, Item *r,
-                                                   Real *fixed, Real *space,
-                                                   Spacing_options const *options)
+Spring
+Spacing_spanner::standard_breakable_column_spacing (Grob *me, Item *l, Item *r, Spacing_options const *options)
 {
-  *fixed = 0.0;
-  Direction d = LEFT;
-  Drul_array<Item *> cols (l, r);
-
-  do
-    {
-      /*
-       TODO: this is fishy, the extent gets distorted due to wide
-       \marks, so better not do this.
-       */
-      if (!Paper_column::is_musical (cols[d]))
-       {
-         /*
-           Tied accidentals over barlines cause problems, so lets see
-           what happens if we do this for non musical columns only.
-         */
-         Interval lext = cols[d]->extent (cols [d], X_AXIS);
-         if (!lext.is_empty ())
-           *fixed += -d * lext[-d];
-       }
-    }
-  while (flip (&d) != LEFT);
+  Real min_dist = max (0.0, Paper_column::minimum_distance (l, r));
+  Real ideal;
 
   if (Paper_column::is_breakable (l) && Paper_column::is_breakable (r))
     {
@@ -61,7 +41,7 @@ Spacing_spanner::standard_breakable_column_spacing (Grob *me, Item *l, Item *r,
 
       Real incr = robust_scm2double (me->get_property ("spacing-increment"), 1);
 
-      *space = *fixed + incr * double (mlen.main_part_ / options->global_shortest_) * 0.8;
+      ideal = min_dist + incr * double (mlen.main_part_ / options->global_shortest_) * 0.8;
     }
   else
     {
@@ -73,14 +53,12 @@ Spacing_spanner::standard_breakable_column_spacing (Grob *me, Item *l, Item *r,
            In this case, Staff_spacing should handle the job,
            using dt when it is 0 is silly.
          */
-         *space = *fixed + 0.5;
+         ideal = min_dist + 0.5;
        }
       else
-       {
-         bool dummy;
-         *space = *fixed + options->get_duration_space (dt.main_part_, &dummy);
-       }
+       ideal = min_dist + options->get_duration_space (dt.main_part_);
     }
+  return Spring (ideal, min_dist);
 }
 
 Moment *
@@ -106,8 +84,7 @@ get_measure_length (Grob *column)
 
 Real
 Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc,
-                              Spacing_options const *options,
-                              bool *expand_only)
+                              Spacing_options const *options)
 {
   (void) me;
   
@@ -151,8 +128,7 @@ Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc,
   Real dist = 0.0;
   if (delta_t.main_part_ && !lwhen.grace_part_)
     {
-      dist = options->get_duration_space (shortest_playing_len.main_part_,
-                                         expand_only);
+      dist = options->get_duration_space (shortest_playing_len.main_part_);
       dist *= double (delta_t.main_part_ / shortest_playing_len.main_part_);
     }
   else if (delta_t.grace_part_)
@@ -162,14 +138,13 @@ Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc,
        available (namely the space for the global shortest note), and
        multiply that by grace-space-factor
       */
-      dist = options->get_duration_space (options->global_shortest_, expand_only) / 2.0;
+      dist = options->get_duration_space (options->global_shortest_) / 2.0;
       Grob *grace_spacing = unsmob_grob (lc->get_object ("grace-spacing"));
       if (grace_spacing)
        {
          Spacing_options grace_opts;
          grace_opts.init_from_grob (grace_spacing);
-         bool bla;
-         dist = grace_opts.get_duration_space (delta_t.grace_part_, &bla);
+         dist = grace_opts.get_duration_space (delta_t.grace_part_);
        }
       
     }
index 920e66bd03a04eada7338482014d4e5d5b166d12..5b13c82264362ded0f7f8717ee82bae0b77e824f 100644 (file)
@@ -14,6 +14,7 @@
 #include "paper-column.hh"
 #include "column-x-positions.hh"
 #include "pointer-group-interface.hh"
+#include "spacing-interface.hh"
 #include "spacing-spanner.hh"
 #include "note-spacing.hh"
 #include "moment.hh"
@@ -86,7 +87,7 @@ is_loose_column (Grob *l, Grob *col, Grob *r, Spacing_options const *options)
     return false;
 
   l_neighbor = l_neighbor->get_column ();
-  r_neighbor = dynamic_cast<Item *> (Note_spacing::right_column (r_neighbor));
+  r_neighbor = dynamic_cast<Item *> (Spacing_interface::right_column (r_neighbor));
 
   if (l == l_neighbor && r == r_neighbor)
     return false;
@@ -143,8 +144,8 @@ Spacing_spanner::set_distances_for_loose_col (Grob *me, Grob *c,
       for (vsize k = wishes.size (); k--;)
        {
          Grob *sp = wishes[k];
-         if (Note_spacing::left_column (sp) != lc
-             || Note_spacing::right_column (sp) != rc)
+         if (Spacing_interface::left_column (sp) != lc
+             || Spacing_interface::right_column (sp) != rc)
            continue;
 
          if (Note_spacing::has_interface (sp))
@@ -153,26 +154,16 @@ Spacing_spanner::set_distances_for_loose_col (Grob *me, Grob *c,
                The note spacing should be taken from the musical
                columns.
              */
-             Real space = 0.0;
-             Real fixed = 0.0;
-             bool dummy = false;
-                 
-             Real base = note_spacing (me, lc, rc, options, &dummy);
-             Note_spacing::get_spacing (sp, rc, base, options->increment_,
-                                        &space, &fixed);
+             Real base = note_spacing (me, lc, rc, options);
+             Spring spring = Note_spacing::get_spacing (sp, rc, base, options->increment_);
 
-             space -= options->increment_;
-
-             dists[d] = max (dists[d], space);
+             dists[d] = max (dists[d], spring.distance () - options->increment_);
            }
          else if (Staff_spacing::has_interface (sp))
            {
-             Real space = 0;
-             Real fixed_space = 0;
-             Staff_spacing::get_spacing_params (sp,
-                                                &space, &fixed_space);
+             Spring spring = Staff_spacing::get_spacing (sp, rc);
 
-             dists[d] = max (dists[d], fixed_space);
+             dists[d] = max (dists[d], spring.min_distance ());
            }
          else
            programming_error ("Subversive spacing wish");
@@ -279,7 +270,7 @@ Spacing_spanner::set_explicit_neighbor_columns (vector<Grob*> const &cols)
          Item *wish = dynamic_cast<Item *> (wishes[k]);
 
          Item *lc = wish->get_column ();
-         Grob *right = Note_spacing::right_column (wish);
+         Grob *right = Spacing_interface::right_column (wish);
 
          if (!right)
            continue;
diff --git a/lily/spacing-interface.cc b/lily/spacing-interface.cc
new file mode 100644 (file)
index 0000000..dbfe4e4
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+  spacing-interface.cc -- functionality that is shared between Note_spacing
+  and Staff_spacing
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2007 Joe Neeman <joeneeman@gmail.com>
+*/
+
+#include "spacing-interface.hh"
+
+#include "grob.hh"
+#include "grob-array.hh"
+#include "item.hh"
+#include "note-column.hh"
+#include "pointer-group-interface.hh"
+#include "paper-column.hh"
+#include "separation-item.hh"
+#include "skyline.hh"
+
+/* return the right-pointing skyline of the left-items and the left-pointing
+   skyline of the right-items (with the skyline of the left-items in
+   ret[LEFT]) */
+Drul_array<Skyline>
+Spacing_interface::skylines (Grob *me, Grob *right_col)
+{
+  /* the logic here is a little convoluted.
+     A {Staff,Note}_spacing doesn't copy left-items when it clones,
+     so in order to find the separation items, we need to use the original
+     spacing grob. But once we find the separation items, we need to get back
+     the broken piece.
+  */
+
+  Grob *orig = me->original () ? me->original () : me;
+  Drul_array<Direction> break_dirs (dynamic_cast<Item*> (me)->break_status_dir (),
+                                   dynamic_cast<Item*> (right_col)->break_status_dir ());
+  Drul_array<Skyline> skylines = Drul_array<Skyline> (Skyline (RIGHT), Skyline (LEFT));
+  Drul_array<vector<Grob*> > items (ly_scm2link_array (orig->get_object ("left-items")),
+                                   ly_scm2link_array (orig->get_object ("right-items")));
+
+  Direction d = LEFT;
+  do
+    {
+      skylines[d].set_minimum_height (0.0);
+
+      for (vsize i = 0; i < items[d].size (); i++)
+       {
+         Grob *g = items[d][i];
+         if (Item *it = dynamic_cast<Item*> (g))
+           if (Grob *piece = it->find_prebroken_piece (break_dirs[d]))
+             g = piece;
+
+         if (Separation_item::has_interface (g))
+           {
+             SCM sky_scm = g->get_property ("horizontal-skylines");
+             Skyline_pair *sky = Skyline_pair::unsmob (sky_scm);
+             if (sky)
+               skylines[d].merge ((*sky)[-d]);
+             else
+               programming_error ("separation item has no skyline");
+           
+             if (d == RIGHT && items[LEFT].size ())
+               skylines[d].merge (Separation_item::conditional_skyline (items[d][i], items[LEFT][0]));
+           }
+       }
+    }
+  while (flip (&d) != LEFT);
+
+  return skylines;
+}
+
+Real
+Spacing_interface::minimum_distance (Grob *me, Grob *right)
+{
+  Drul_array<Skyline> skylines = Spacing_interface::skylines (me, right);
+
+  return max (0.0, skylines[LEFT].distance (skylines[RIGHT]));
+}
+
+/*
+  Compute the column of the right-items.  This is a big function,
+  since RIGHT-ITEMS may span more columns (eg. if a clef is inserted,
+  this will add a new column to RIGHT-ITEMS. Here we look at the
+  columns, and return the left-most. If there are multiple columns, we
+  prune RIGHT-ITEMS.
+*/
+Item *
+Spacing_interface::right_column (Grob *me)
+{
+  if (!me->is_live ())
+    return 0;
+
+  Grob_array *a = unsmob_grob_array (me->get_object ("right-items"));
+  Item *mincol = 0;
+  int min_rank = INT_MAX;
+  bool prune = false;
+  for (vsize i = 0; a && i < a->size (); i++)
+    {
+      Item *ri = a->item (i);
+      Item *col = ri->get_column ();
+
+      int rank = Paper_column::get_rank (col);
+
+      if (rank < min_rank)
+       {
+         min_rank = rank;
+         if (mincol)
+           prune = true;
+
+         mincol = col;
+       }
+    }
+
+  if (prune && a)
+    {
+      vector<Grob*> &right = a->array_reference ();
+      for (vsize i = right.size (); i--;)
+       {
+         if (dynamic_cast<Item *> (right[i])->get_column () != mincol)
+           right.erase (right.begin () + i);
+       }
+    }
+
+  return mincol;
+}
+
+Item *
+Spacing_interface::left_column (Grob *me)
+{
+  if (!me->is_live ())
+    return 0;
+
+  return dynamic_cast<Item *> (me)->get_column ();
+}
+
+static vector<Item*>
+get_note_columns (vector<Grob*> const &elts)
+{
+  vector<Item*> ret;
+
+  for (vsize i = 0; i < elts.size (); i++)
+    {
+      if (Note_column::has_interface (elts[i]))
+       ret.push_back (dynamic_cast<Item*> (elts[i]));
+      else if (Separation_item::has_interface (elts[i]))
+       {
+         extract_grob_set (elts[i], "elements", more_elts);
+         vector<Item*> ncs = get_note_columns (more_elts);
+
+         ret.insert (ret.end (), ncs.begin (), ncs.end ());
+       }
+    }
+
+  return ret;
+}
+
+vector<Item*>
+Spacing_interface::right_note_columns (Grob *me)
+{
+  extract_grob_set (me, "right-items", elts);
+  return get_note_columns (elts);
+}
+
+vector<Item*>
+Spacing_interface::left_note_columns (Grob *me)
+{
+  extract_grob_set (me, "left-items", elts);
+  return get_note_columns (elts);
+}
+
+ADD_INTERFACE (Spacing_interface,
+              "This object calculates the desired and minimum distances between two columns.",
+
+              "left-items "
+              "right-items "
+              );
index 3a69e26802aa46cd42ad2e78bd58df58efd3beed..a59fa7d0f9350734baa6717ab25017ed25ec59cf 100644 (file)
@@ -119,23 +119,19 @@ set_loose_columns (System *which, Column_x_positions const *posns)
          else
            programming_error ("Column without spacing object");
 
-         bool expand_only = false;
          Real base_note_space = 0.0;
 
          if (Paper_column::is_musical (next_col)
              && Paper_column::is_musical (loose_col))
-           base_note_space = Spacing_spanner::note_spacing (spacing, loose_col, next_col, 
-                                                            &options, &expand_only);
+           base_note_space = Spacing_spanner::note_spacing (spacing, loose_col, next_col,
+                                                            &options);
          else
            {
-             Real fixed, space;
-             
-             Spacing_spanner::standard_breakable_column_spacing (spacing, 
-                                                                 loose_col, next_col,
-                                                                 &fixed, &space,
-                                                                 &options);
-
-             base_note_space = space;
+             Spring spring = Spacing_spanner::standard_breakable_column_spacing (spacing,
+                                                                                 loose_col, next_col,
+                                                                                 &options);
+
+             base_note_space = spring.distance ();
            }
 
          base_note_space = max (base_note_space,
index 8c7b7c3ca5191002cc1477be2d0e666552eb71d7..a3e512525b5c8352a825e08f81f2fc95cfbedcf5 100644 (file)
@@ -56,8 +56,7 @@ Spacing_options::Spacing_options ()
   Get the measure wide ant for arithmetic spacing.
 */
 Real
-Spacing_options::get_duration_space (Rational d,
-                                    bool *expand_only) const
+Spacing_options::get_duration_space (Rational d) const
 {
   Real k = shortest_duration_space_;
 
@@ -92,7 +91,6 @@ Spacing_options::get_duration_space (Rational d,
       */
       Real log = log_2 (global_shortest_);
       k -= log;
-      *expand_only = false;
 
       return (log_2 (d) + k) * increment_;
     }
index a61bffb98a3aa41d7a417ee493a17e7412e127b0..d878c58b7f83e2dfaae14d8b2f2fb99125f7515c 100644 (file)
@@ -11,8 +11,6 @@
 #include <math.h>
 #include <cstdio>
 
-using namespace std;
-
 #include "spacing-options.hh"
 #include "international.hh"
 #include "main.hh"
@@ -22,6 +20,7 @@ using namespace std;
 #include "paper-column.hh"
 #include "paper-score.hh"
 #include "pointer-group-interface.hh"
+#include "separation-item.hh"
 #include "spaceable-grob.hh"
 #include "spacing-interface.hh"
 #include "staff-spacing.hh"
@@ -167,15 +166,10 @@ Spacing_spanner::generate_pair_spacing (Grob *me,
 {
   if (Paper_column::is_musical (left_col))
     {
-      bool skip_unbroken_right = false;
-
       if (!Paper_column::is_musical (right_col)
          && options->float_nonmusical_columns_
          && after_right_col
          && Paper_column::is_musical (after_right_col))
-       skip_unbroken_right = true;
-
-      if (skip_unbroken_right)
        {
          /*
            TODO: should generate rods to prevent collisions.
@@ -214,6 +208,49 @@ Spacing_spanner::generate_pair_spacing (Grob *me,
     }
 }
 
+static void
+set_column_rods (vector<Grob*> const &cols, vsize idx, Real padding)
+{
+
+  /*
+    This is an inner loop: look for the first normal (unbroken) Left
+    grob.  This looks like an inner loop (ie. quadratic total), but in
+    most cases, the interesting L will just be the first entry of
+    NEXT, making it linear in most of the cases.
+  */
+  Item *r = dynamic_cast<Item*> (cols[idx]);
+
+  if (Separation_item::is_empty (r))
+    return;
+
+  while (idx--)
+    {
+      Item *l = dynamic_cast<Item*> (cols[idx]);
+      Item *lb = l->find_prebroken_piece (RIGHT);
+
+      if (Separation_item::is_empty (l) && (!lb || Separation_item::is_empty (lb)))
+       continue;
+
+      Separation_item::set_distance (Drul_array<Item *> (l, r), padding);
+      if (lb)
+       Separation_item::set_distance (Drul_array<Item*> (lb, r), padding);
+
+
+      /*
+       This check is because grace notes are set very tight, and
+       the accidentals of main note may stick out so far to cover
+       a barline preceding the grace note.
+      */
+      if (spanned_time_interval (l, r).length ().main_part_ > Rational (0))
+       break;
+
+      /*
+       this grob doesn't cause a constraint. We look further until we
+       find one that does.
+      */
+    }
+}
+
 void
 Spacing_spanner::generate_springs (Grob *me,
                                   vector<Grob*> const &cols,
@@ -226,15 +263,17 @@ Spacing_spanner::generate_springs (Grob *me,
       Paper_column *next = (i + 1 < cols.size ()) ? dynamic_cast<Paper_column *> (cols[i+1]) : 0;
       
       if (i > 0)
-       generate_pair_spacing (me, prev, col, next, options);
+       {
+         generate_pair_spacing (me, prev, col, next, options);
+         set_column_rods (cols, i, 0.1); // FIXME
+       }
 
       prev = col;
     }
 }
 
 /*
-  Generate the space between two musical columns LEFT_COL and RIGHT_COL, given
-  spacing parameters INCR and SHORTEST.
+  Generate the space between two musical columns LEFT_COL and RIGHT_COL.
 */
 void
 Spacing_spanner::musical_column_spacing (Grob *me,
@@ -242,45 +281,22 @@ Spacing_spanner::musical_column_spacing (Grob *me,
                                         Item *right_col,
                                         Spacing_options const *options)
 {
-  bool expand_only = false;
-  Real base_note_space = note_spacing (me, left_col, right_col, options, &expand_only);
-
-  Real max_fixed = 0;
-  Real max_space = 0;
-  Real compound_note_space = 0.0;
-  Real compound_fixed_note_space = 0.0;
+  Real base_note_space = note_spacing (me, left_col, right_col, options);
+  Spring spring;
 
   if (options->stretch_uniformly_)
-    {
-      compound_note_space = base_note_space;
-            
-      if (!Paper_column::is_musical (right_col))
-       {
-         /*
-           Crude fix for notes that lead up to barlines and time sigs.
-         */
-         Interval lext = right_col->extent (right_col, X_AXIS);
-         if (!lext.is_empty ())
-           compound_note_space += -lext[LEFT];
-       }
-    }
+    spring = Spring (base_note_space, 0.0);
   else
     {
-      int wish_count = 0;
-      
+      vector<Spring> springs;
       extract_grob_set (left_col, "right-neighbors", neighbors);
 
-      /*
-       We adjust the space following a note only if the next note
-       happens after the current note (this is set in the grob
-       property SPACING-SEQUENCE.
-      */
       for (vsize i = 0; i < neighbors.size (); i++)
        {
          Grob *wish = neighbors[i];
 
-         Item *wish_rcol = Note_spacing::right_column (wish);
-         if (Note_spacing::left_column (wish) != left_col
+         Item *wish_rcol = Spacing_interface::right_column (wish);
+         if (Spacing_interface::left_column (wish) != left_col
              || (wish_rcol != right_col && wish_rcol != right_col->original ()))
            continue;
 
@@ -288,32 +304,10 @@ Spacing_spanner::musical_column_spacing (Grob *me,
            This is probably a waste of time in the case of polyphonic
            music.  */
          if (Note_spacing::has_interface (wish))
-           {
-             Real space = 0.0;
-             Real fixed = 0.0;
-
-             Note_spacing::get_spacing (wish, right_col, base_note_space, options->increment_, &space, &fixed);
-
-
-             max_space = max (max_space, space);
-             max_fixed = max (max_fixed, fixed);
-             
-             compound_note_space += space;
-             compound_fixed_note_space += fixed;
-             wish_count++;
-           }
+           springs.push_back (Note_spacing::get_spacing (wish, right_col, base_note_space, options->increment_));
        }
 
-      if (Paper_column::when_mom (right_col).grace_part_
-         && !Paper_column::when_mom (left_col).grace_part_)
-       {
-         /*
-           Ugh. 0.8 is arbitrary.
-         */
-         compound_note_space *= 0.8;
-       }
-
-      if (compound_note_space < 0 || wish_count == 0)
+      if (springs.empty ())
        {
 
          if (!Paper_column::is_musical (right_col))
@@ -324,9 +318,8 @@ Spacing_spanner::musical_column_spacing (Grob *me,
                spacing, because the width of s^"text" output is also
                taken into account here.
               */
-             compound_fixed_note_space = options->increment_;
-             compound_note_space = max (base_note_space,
-                                        options->increment_);
+             spring = Spring (max (base_note_space, options->increment_),
+                              options->increment_);
            }
          else
            {
@@ -334,44 +327,30 @@ Spacing_spanner::musical_column_spacing (Grob *me,
                Fixed should be 0.0. If there are no spacing wishes, we're
                likely dealing with polyphonic spacing of hemiolas.
            
-               We used to have compound_fixed_note_space = options->increment_
+               We used to have min_distance_ = options->increment_
 
                but this can lead to numeric instability problems when we
                do
            
-               inverse_strength = (compound_note_space - compound_fixed_note_space)
+               inverse_strength = (distance_ - min_distance_)
       
              */
-
-             compound_note_space = base_note_space;
-             compound_fixed_note_space = 0.0;
+             spring = Spring (base_note_space, 0.0);
            }
        }
-      else if (to_boolean (me->get_property ("average-spacing-wishes")))
-       {
-         compound_note_space /= wish_count;
-         compound_fixed_note_space /= wish_count;
-       }
       else
-       {
-         compound_fixed_note_space = max_fixed;
-         compound_note_space = max_space;
-       }
+       spring = merge_springs (springs);
+    }
 
+  if (Paper_column::when_mom (right_col).grace_part_
+      && !Paper_column::when_mom (left_col).grace_part_)
+    {
       /*
-       Whatever we do, the fixed space is smaller than the real
-       space.
-
-       TODO: this criterion is discontinuous in the derivative.
-       Maybe it should be continuous?
+       Ugh. 0.8 is arbitrary.
       */
-      compound_fixed_note_space = min (compound_fixed_note_space,
-                                      compound_note_space);
+      spring *= 0.8;
     }
 
-  Real inverse_strength = 1.0;
-  Real distance = 1.0;
-
   /*
     TODO: make sure that the space doesn't exceed the right margin.
   */
@@ -386,16 +365,11 @@ Spacing_spanner::musical_column_spacing (Grob *me,
        pack as much bars of music as possible into a line, but the
        line will then be stretched to fill the whole linewidth.
       */
-      inverse_strength = 1.0;
-      distance = compound_fixed_note_space;
-    }
-  else
-    {
-      inverse_strength = (compound_note_space - compound_fixed_note_space);
-      distance = compound_note_space;
+      spring.set_distance (spring.min_distance ());
+      spring.set_inverse_stretch_strength (1.0);
     }
 
-  Spaceable_grob::add_spring (left_col, right_col, distance, inverse_strength);
+  Spaceable_grob::add_spring (left_col, right_col, spring);
 }
 
 /*
@@ -441,12 +415,8 @@ void
 Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r,
                                           Spacing_options const *options)
 {
-  Real compound_fixed = 0.0;
-  Real compound_space = 0.0;
-  Real max_fixed = 0.0;
-  Real max_space = 0.0;
-  
-  int wish_count = 0;
+  vector<Spring> springs;
+  Spring spring;
 
   Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l);
 
@@ -461,74 +431,46 @@ Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r,
          if (!spacing_grob || !Staff_spacing::has_interface (spacing_grob))
            continue;
 
-         Real space = 0.;
-         Real fixed_space = 0.;
-
          /*
            column for the left one settings should be ok due automatic
            pointer munging.
          */
          assert (spacing_grob->get_column () == l);
 
-         Staff_spacing::get_spacing_params (spacing_grob,
-                                            &space, &fixed_space);
-
-         if (Paper_column::when_mom (r).grace_part_)
-           {
-             /*
-               Correct for grace notes.
-
-               Ugh. The 0.8 is arbitrary.
-             */
-             space *= 0.8;
-           }
-
-         max_space = max (max_space, space);
-         max_fixed = max (max_fixed, fixed_space);
-         
-         compound_space += space;
-         compound_fixed += fixed_space;
-         wish_count++;
+         springs.push_back (Staff_spacing::get_spacing (spacing_grob, r));
        }
     }
 
-  if (compound_space <= 0.0 || !wish_count)
-    {
-      standard_breakable_column_spacing (me, l, r, &compound_fixed, &compound_space,
-                                        options);
-      wish_count = 1;
-    }
+  if (springs.empty ())
+    spring = standard_breakable_column_spacing (me, l, r, options);
   else
+    spring = merge_springs (springs);
+
+  if (Paper_column::when_mom (r).grace_part_)
     {
-      if (to_boolean (me->get_property ("average-spacing-wishes")))
-       {
-         compound_space /= wish_count;
-         compound_fixed /= wish_count;
-       }
-      else
-       {
-         compound_fixed = max_fixed;
-         compound_space = max_space;
-       }
-      
+      /*
+       Correct for grace notes.
+       
+       Ugh. The 0.8 is arbitrary.
+      */
+      spring *= 0.8;
     }
 
   if (Paper_column::is_musical (r)
       && l->break_status_dir () == CENTER
       && fills_measure (me, l, r))
     {
-      compound_space += 1.0; 
+      spring.set_distance (spring.distance () + 1.0);
+      spring.set_default_strength ();
     }
   
   if (options->stretch_uniformly_ && l->break_status_dir () != RIGHT)
-    compound_fixed = 0.0;
-
-  assert (!isinf (compound_space));
-  compound_space = max (compound_space, compound_fixed);
+    {
+      spring.set_min_distance (0.0);
+      spring.set_default_strength ();
+    }
 
-  Real inverse_strength = (compound_space - compound_fixed);
-  Real distance = compound_space;
-  Spaceable_grob::add_spring (l, r, distance, inverse_strength);
+  Spaceable_grob::add_spring (l, r, spring);
 }
 
 ADD_INTERFACE (Spacing_spanner,
index a57f5029f2d2eef8c160f6173a67ea8761164361..5639a1cd0737446b8318f3c3a12b9712acc69007 100644 (file)
 #include "warn.hh"
 #include "ly-smobs.icc"
 
-Spring_smob::Spring_smob ()
-{
-  distance_ = 0.;
-  inverse_strength_ = 1.0;
-  expand_only_b_ = false;
-  other_ = 0;
-}
-
-IMPLEMENT_SIMPLE_SMOBS (Spring_smob);
+IMPLEMENT_SIMPLE_SMOBS (Spring);
 
 SCM
-Spring_smob::mark_smob (SCM x)
+Spring::mark_smob (SCM x)
 {
   (void)x;
 
@@ -29,14 +21,14 @@ Spring_smob::mark_smob (SCM x)
 }
 
 int
-Spring_smob::print_smob (SCM, SCM p, scm_print_state *)
+Spring::print_smob (SCM, SCM p, scm_print_state *)
 {
   scm_puts ("#<Spring smob>", p);
   return 1;
 }
 
 SCM
-Spring_smob::equal_p (SCM a, SCM b)
+Spring::equal_p (SCM a, SCM b)
 {
   return a == b? SCM_BOOL_T : SCM_BOOL_F;
 }
diff --git a/lily/spring.cc b/lily/spring.cc
new file mode 100644 (file)
index 0000000..679ccfa
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+  spring.cc -- declare Spring
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2007 Joe Neeman <joeneeman@gmail.com>
+*/
+
+#include "spring.hh"
+
+Spring::Spring ()
+{
+  distance_ = 1.0;
+  min_distance_ = 1.0;
+  inverse_stretch_strength_ = 1.0;
+  inverse_compress_strength_ = 1.0;
+
+  update_blocking_force ();
+}
+
+Spring::Spring (Real dist, Real min_dist)
+{
+  distance_ = 1.0;
+  min_distance_ = 1.0;
+
+  set_distance (dist);
+  set_min_distance (min_dist);
+  set_default_strength ();
+  update_blocking_force ();
+}
+
+void
+Spring::update_blocking_force ()
+{
+  if (distance_ == min_distance_)
+    blocking_force_ = 0.0;
+  else
+    blocking_force_ = (min_distance_ - distance_) / inverse_compress_strength_;
+}
+
+/* scale a spring, but in a way that doesn't violate min_distance */
+void
+Spring::operator*= (Real r)
+{
+  distance_ = max (min_distance_, distance_ * r);
+  inverse_compress_strength_ = distance_ - min_distance_;
+  inverse_stretch_strength_ *= 0.8;
+}
+
+bool
+Spring::operator> (Spring const &other) const
+{
+  return blocking_force_ > other.blocking_force_;
+}
+
+/* merge springs, basically by averaging them, but leave a little headroom
+   above the largest minimum distance so that things don't get too cramped */
+Spring
+merge_springs (vector<Spring> const &springs)
+{
+  Real avg_distance = 0;
+  Real min_distance = 0;
+  Real avg_stretch = 0;
+
+  for (vsize i = 0; i < springs.size (); i++)
+    {
+      avg_distance += springs[i].distance ();
+      avg_stretch += springs[i].inverse_stretch_strength ();
+      min_distance = max (springs[i].min_distance (), min_distance);
+    }
+
+  avg_stretch /= springs.size ();
+  avg_distance /= springs.size ();
+  avg_distance = max (min_distance + 0.3, avg_distance);
+
+  Spring ret = Spring (avg_distance, min_distance);
+  ret.set_inverse_stretch_strength (avg_stretch);
+
+  return ret;
+}
+
+void
+Spring::set_distance (Real d)
+{
+  if (d < 0 || isinf (d) || isnan (d))
+    programming_error ("insane spring distance requested, ignoring it");
+  else
+    {
+      min_distance_ = min (min_distance_, d);
+      distance_ = d;
+      update_blocking_force ();
+    }
+}
+
+void
+Spring::set_min_distance (Real d)
+{
+  if (d < 0 || isinf (d) || isnan (d))
+    programming_error ("insane spring min_distance requested, ignoring it");
+  else
+    {
+      min_distance_ = d;
+      distance_ = max (distance_, min_distance_);
+      update_blocking_force ();
+    }
+}
+
+void
+Spring::set_inverse_stretch_strength (Real f)
+{
+  if (isinf (f) || isnan (f) || f < 0)
+    programming_error ("insane spring constant");
+  else
+    inverse_stretch_strength_ = f;
+}
+
+void
+Spring::set_inverse_compress_strength (Real f)
+{
+  if (isinf (f) || isnan (f) || f < 0)
+    programming_error ("insane spring constant");
+  else
+    inverse_compress_strength_ = f;
+
+  update_blocking_force ();
+}
+
+void
+Spring::set_blocking_force (Real f)
+{
+  if (isinf (f) || isnan (f))
+    {
+      programming_error ("insane blocking force");
+      return;
+    }
+
+  blocking_force_ = -infinity_f;
+  min_distance_ = length (f);
+  distance_ = max (distance_, min_distance_);
+  update_blocking_force ();
+}
+
+void
+Spring::set_default_strength ()
+{
+  inverse_compress_strength_ = distance_ - min_distance_;
+  inverse_stretch_strength_ = distance_ - min_distance_;
+}
+
+Real
+Spring::length (Real f) const
+{
+  Real force = max (f, blocking_force_);
+  Real inv_k = force < 0.0 ? inverse_compress_strength_ : inverse_stretch_strength_;
+  return distance_ + force * inv_k;
+}
index 79e70286445b3844169be78dea600fa7261defe7..8a8822a803ad16cd51237eab3f6b754ef553e2f8 100644 (file)
@@ -11,6 +11,7 @@
 #include <cstdio>
 using namespace std;
 
+#include "international.hh"
 #include "paper-column.hh"
 #include "separation-item.hh"
 #include "warn.hh"
@@ -18,74 +19,28 @@ using namespace std;
 #include "staff-symbol-referencer.hh"
 #include "note-column.hh"
 #include "stem.hh"
+#include "spacing-interface.hh"
 #include "accidental-placement.hh"
 #include "pointer-group-interface.hh"
 #include "directional-element-interface.hh"
 
-/*
-  Insert some more space for the next note, in case it has a stem in
-  the wrong direction
+/* A stem following a bar-line creates an optical illusion similar to the
+   one mentioned in note-spacing.cc. We correct for it here.
+
+   TODO: should we still correct if there are accidentals/arpeggios before
+   the stem?
 */
-void
-Staff_spacing::next_note_correction (Grob *me,
-                                    Grob *g,
-                                    Interval bar_size,
-                                    Real current_space, Real current_fixed,
-                                    Real *space,
-                                    Real *fix,
-                                    int *wish_count)
+
+Real
+Staff_spacing::optical_correction (Grob *me, Grob *g, Interval bar_height)
 {
-  (void) current_fixed; 
   if (!g || !Note_column::has_interface (g))
-    return ;
+    return 0;
 
-  Item *col = dynamic_cast<Item *> (g)->get_column ();
-  Real left_stickout_correction = max (0., (- g->extent (col, X_AXIS)[LEFT]));
-
-  /* staff space -> positions */
-  bar_size *= 2;
-
-  /*
-    Duh. If this gets out of hand, we should invent something more generic.
-  */
-  Grob *accs = Note_column::accidentals (g);
-  if (accs)
-    {
-      Interval v;
-      if (Accidental_placement::has_interface (accs))
-       v = Accidental_placement::get_relevant_accidental_extent (accs, col, me);
-      else
-       v = accs->extent (col, X_AXIS);
-      
-      left_stickout_correction = max (left_stickout_correction, (- v[LEFT]));
-    }
-  Grob *arpeggio = unsmob_grob (g->get_object ("arpeggio"));
-  if (arpeggio)
-    left_stickout_correction = max (left_stickout_correction, - arpeggio->extent (col, X_AXIS)[LEFT]);
-
-  
-  /*
-    Let's decrease the space a little if the problem is not located
-    after a barline.
-  */
-  if (bar_size.is_empty ())
-    left_stickout_correction *= 0.75;
-
-  /*
-    We want 0.3 ss before the sticking-out object.
-    
-    current_fixed/2 is our guess at (right side of left object + 0.3)
-   */
-  left_stickout_correction += current_fixed/2 - current_space;
-  left_stickout_correction = max (left_stickout_correction, 0.0);
-
-  
-  Real optical_corr = 0.0;
   Grob *stem = Note_column::get_stem (g);
-  if (!bar_size.is_empty ()
-      && !arpeggio
-      && !accs
-      && stem)
+  Real ret = 0.0;
+
+  if (!bar_height.is_empty () && stem)
     {
       Direction d = get_grob_direction (stem);
       if (Stem::is_normal_stem (stem) && d == DOWN)
@@ -102,28 +57,15 @@ Staff_spacing::next_note_correction (Grob *me,
          Interval stem_posns (min (stem_start, stem_end),
                               max (stem_end, stem_start));
 
-         stem_posns.intersect (bar_size);
+         stem_posns.intersect (bar_height);
 
-         optical_corr = min (abs (stem_posns.length () / 7.0), 1.0);
-         optical_corr *= robust_scm2double (me->get_property ("stem-spacing-correction"), 1);
+         ret = min (abs (stem_posns.length () / 7.0), 1.0);
+         ret *= robust_scm2double (me->get_property ("stem-spacing-correction"), 1);
        }
     }
-
-
-  Real correction = optical_corr + left_stickout_correction;
-  if (correction)
-    {
-      (*wish_count) ++; 
-
-      /*
-       This minute adjustments don't make sense for widely spaced scores.
-       Hence, we need to keep the stretchable (that is, space - fix)
-       distance equal.
-      */
-      *space += correction;
-      *fix += correction;
-    }
+  return ret;
 }
+
 /*
   Y-positions that are covered by BAR_GROB, in the case that it is a
   barline.  */
@@ -149,95 +91,35 @@ Staff_spacing::bar_y_positions (Grob *bar_grob)
   return bar_size;
 }
 
-/*
-  Do corrections for the following notes.
-
-  This is slightly convoluted, since the staffspacing grob gets
-  pointers to the separation-items, not the note-columns or
-  note-spacings.
-*/
-
-void
-Staff_spacing::next_notes_correction (Grob *me, Grob *last_grob,
-                                     Real current_space, Real current_fixed,
-                                     Real *compound_space, Real *compound_fixed
-                                     )
+Real
+Staff_spacing::next_notes_correction (Grob *me,
+                                     Grob *last_grob)
 {
   Interval bar_size = bar_y_positions (last_grob);
+  Grob *orig = me->original () ? me->original () : me;
+  vector<Item*> note_columns = Spacing_interface::right_note_columns (orig);
 
-  extract_grob_set (me, "right-items", right_items);
+  Real max_optical = 0.0;
 
-  *compound_fixed = 0.0;
-  *compound_space = 0.0;
-  int wish_count = 0;
+  for (vsize i = 0; i < note_columns.size (); i++)
+    max_optical = max (max_optical, optical_correction (me, note_columns[i], bar_size));
 
-  for (vsize i = right_items.size (); i--;)
-    {
-      Grob *g = right_items[i];
-      if (Note_column::has_interface (right_items[i]))
-       {
-         Grob *g = right_items[i];
-
-         Real space = 0.0;
-         Real fixed = 0.0;
-      
-         next_note_correction (me, g, bar_size,
-                               current_space, current_fixed,
-                               &space, &fixed, &wish_count);
-      
-         *compound_space += space;
-         *compound_fixed += fixed; 
-       }
-      else
-       {
-         extract_grob_set (g, "elements", elts);
-         for (vsize j = elts.size (); j--;)
-           {
-             Real space = 0.0;
-             Real fixed = 0.0;
-             next_note_correction (me, elts[j], bar_size,
-                                   current_space, current_fixed,
-                                   &space, &fixed,
-                                   &wish_count);
-             *compound_fixed += fixed;
-             *compound_space += space;
-           }
-       }
-    }
-  
-  if (wish_count > 1)
-    {
-      *compound_space /= wish_count;
-      *compound_fixed /= wish_count;
-    }
+  return max_optical;
 }
 
-void
-Staff_spacing::get_spacing_params (Grob *me, Real *space, Real *fixed)
+/* We calculate three things here: the ideal distance, the minimum distance
+   (which is the distance at which collisions will occure) and the "fixed"
+   distance, which is the distance at which things start to look really bad.
+   We arrange things so that the fixed distance will be attained when the
+   line is compressed with a force of 1.0 */
+Spring
+Staff_spacing::get_spacing (Grob *me, Grob *right_col)
 {
-  *space = 1.0;
-  *fixed = 1.0;
-
-  Grob *separation_item = 0;
   Item *me_item = dynamic_cast<Item *> (me);
-
-  extract_grob_set (me, "left-items", items);
-  for (vsize i = items.size (); i--;)
-    {
-      Grob *cand = items[i];
-      if (cand && Separation_item::has_interface (cand))
-       separation_item = cand;
-    }
-
-  //  printf ("doing col %d\n" , Paper_column::get_rank (left_col));
-  if (!separation_item)
-    {
-      programming_error ("no sep item");
-      return;
-    }
+  Grob *left_col = me_item->get_column ();
 
   Interval last_ext;
-  Grob *last_grob = Separation_item::extremal_break_aligned_grob (separation_item, RIGHT,
+  Grob *last_grob = Separation_item::extremal_break_aligned_grob (left_col, RIGHT,
                                                                  &last_ext);
   if (!last_grob)
     {
@@ -252,15 +134,12 @@ Staff_spacing::get_spacing_params (Grob *me, Real *space, Real *fixed)
        we used to have a warning here, but it generates a lot of
        spurious error messages.
       */
-      return;
+      return Spring ();
     }
 
-  *fixed = last_ext[RIGHT];
-  *space = *fixed + 1.0;
-
   SCM alist = last_grob->get_property ("space-alist");
   if (!scm_list_p (alist))
-    return;
+    return Spring ();
 
   SCM space_def = scm_sloppy_assq (ly_symbol2scm ("first-note"), alist);
   if (me_item->break_status_dir () == CENTER)
@@ -273,41 +152,50 @@ Staff_spacing::get_spacing_params (Grob *me, Real *space, Real *fixed)
   if (!scm_is_pair (space_def))
     {
       programming_error ("unknown prefatory spacing");
-      return;
+      return Spring ();
     }
 
   space_def = scm_cdr (space_def);
   Real distance = scm_to_double (scm_cdr (space_def));
   SCM type = scm_car (space_def);
 
-  *fixed = last_ext[RIGHT];
+  Real fixed = last_ext[RIGHT];
+  Real ideal = fixed + 1.0;
+
   if (type == ly_symbol2scm ("fixed-space"))
     {
-      *fixed += distance;
-      *space = *fixed;
+      fixed += distance;
+      ideal = fixed;
     }
   else if (type == ly_symbol2scm ("extra-space"))
-    *space = *fixed + distance;
+    ideal = fixed + distance;
   else if (type == ly_symbol2scm ("semi-fixed-space"))
     {
-      *fixed += distance / 2;
-      *space = *fixed + distance / 2;
+      fixed += distance / 2;
+      ideal = fixed + distance / 2;
     }
   else if (type == ly_symbol2scm ("minimum-space"))
-    *space = last_ext[LEFT] + max (last_ext.length (), distance);
+    ideal = last_ext[LEFT] + max (last_ext.length (), distance);
   else if (type == ly_symbol2scm ("minimum-fixed-space"))
     {
-      *space = last_ext[LEFT] + max (last_ext.length (), distance);
-      *fixed = *space;
+      fixed = last_ext[LEFT] + max (last_ext.length (), distance);
+      ideal = fixed;
     }
 
-  Real correction_fixed = 0.0;
-  Real correction_space = 0.0;
-  next_notes_correction (me, last_grob,
-                        *space, *fixed,
-                        &correction_space, &correction_fixed );
-  *space += correction_space;
-  *fixed += correction_fixed;
+
+  Real optical_correction = next_notes_correction (me, last_grob);
+  Real min_dist = Paper_column::minimum_distance (left_col, right_col);
+
+  /* ensure that the "fixed" distance will leave a gap of at least 0.3 ss. */
+  Real min_dist_correction = max (0.0, 0.3 + min_dist - fixed);
+  Real correction = max (optical_correction, min_dist_correction);
+
+  fixed += correction;
+  ideal += correction;
+
+  Spring ret (ideal, min_dist);
+  ret.set_inverse_stretch_strength (ideal - fixed);
+  return ret;
 }
 
 ADD_INTERFACE (Staff_spacing,
@@ -317,6 +205,4 @@ ADD_INTERFACE (Staff_spacing,
 
               /* properties */
               "stem-spacing-correction "
-              "left-items "
-              "right-items "
               );
index eb6d05a8810f1b8662a8739615aac685a23e62d5..e8af537be179b4c3c607de37972aaa004800344c 100644 (file)
@@ -19,7 +19,6 @@
 #include "paper-score.hh"
 #include "paper-system.hh"
 #include "pointer-group-interface.hh"
-#include "spacing-interface.hh"
 #include "staff-symbol-referencer.hh"
 #include "warn.hh"
 #include "lookup.hh"
index bdcd3dbb365040465e5aefe238e8a92178dcca06..cf525dc7b967c57d50c562b94b19c87c677e4c4b 100644 (file)
@@ -179,14 +179,9 @@ Tie_engraver::stop_translation_timestep ()
       if (!wait)
        heads_to_tie_.clear ();
 
-      Grob *sep = unsmob_grob (get_property ("breakableSeparationItem"));
       for (vsize i = 0; i < ties_.size (); i++)
-       {
-         if (sep)
-           ties_[i]->set_object  ("separation-item", sep->self_scm ());
-         
          typeset_tie (ties_[i]);
-       }
+
       ties_.clear ();
       tie_column_ = 0;
     }
index 3105d784f1615a8e9ec459bfeb99289fa6bb3e1c..3a8ed37a6248150dc2893d81548a8229f17e8b77 100644 (file)
@@ -316,18 +316,9 @@ Tie_formatting_problem::from_ties (vector<Grob*> const &ties)
        {
          Item *it = dynamic_cast<Spanner*> (ties[i])->get_bound (d);
          if (it->break_status_dir ())
-           {
-             Item *sep
-               = dynamic_cast<Item*> (unsmob_grob (ties[i]->get_object ("separation-item")));
-             if (sep && sep->get_column () == it->get_column ())
-               it = sep;
+             it = it->get_column ();
 
-             bounds.push_back (it);
-           }
-         else 
-           {
-             bounds.push_back (it);
-           }
+         bounds.push_back (it);
        }
       
       set_chord_outline (bounds, d);
index 7e8383b7f7db06835e441f0af65f1a6839ec9e44..b564ad14454cf871fdae7a5bf30a4b15f0173941 100644 (file)
@@ -416,7 +416,6 @@ printing of a single line of lyrics."
 %  \consists "Note_spacing_engraver"
   voltaOnThisStaff = ##f
   \override VerticalAxisGroup #'minimum-Y-extent = #'(0 . 2)
-  \override SeparatingGroupSpanner #'padding = #0.8
   \override VerticalAxisGroup #'remove-first = ##t
   \override VerticalAxisGroup #'remove-empty = ##t
 }
index 1d0b28cf6ca3a295de73bbf82b08076e0dfc0d78..05127f86d1414474fbe2cddace54435e040a6995 100644 (file)
@@ -536,6 +536,8 @@ event types that should be duplicated for @code{\\quote} commands.")
      (instrumentSupport ,grob-list? "list of grobs to attach instrument name
 to.")
      (tieMelismaBusy ,boolean? "Signal whether a tie is present.")
+     (hasStaffSpacing ,boolean? "True if the currentCommandColumn contains items that will
+affect spacing")
      )))
 
 (define-public all-translation-properties
index c4dc73d095125861e600f140a470681898f5c0da..0cdcf8f825739bc423b3ca00501d6364a6a44573 100644 (file)
@@ -637,6 +637,7 @@ where this is set in.")
      (normal-stems ,ly:grob-array? "Array of visible stems.") 
      (note-heads ,ly:grob-array? "List of note head grobs")
      (note-head ,ly:grob? "A single note head")
+     (pure-Y-offset-in-progress ,boolean? "A debugging aid for catching cyclic dependencies.")
      (right-items ,ly:grob-array? "")
      (right-neighbors ,ly:grob-array? "see left-neighbors")
      (separation-item ,ly:grob? "A separation item.")
index c3315a3b42c77d830d9b858ca5a1d0f21f35688f..6159e81f94e38d684ee43f299a8c31146e3d046c 100644 (file)
        (direction . ,UP)
        (self-alignment-X . ,CENTER)
        (meta . ((class . Item)
-                (interfaces . (system-start-text-interface
-                               side-position-interface
+                (interfaces . (side-position-interface
                                font-interface))))))
     
     (KeyCancellation
        (axes . (0))
        (before-line-breaking . ,ly:paper-column::before-line-breaking)
        (X-extent . ,ly:axis-group-interface::width)
+       (horizontal-skylines . ,ly:separation-item::calc-skylines)
        ;;                    (stencil . ,ly:paper-column::print)
        
        (non-musical . #t)
        (meta . ((class . Paper_column)
                 (interfaces . (paper-column-interface
                                axis-group-interface
+                               separation-item-interface
                                spaceable-grob-interface))))))
     
     (NoteCollision
        (axes . (0 1))
        (X-extent . ,ly:axis-group-interface::width)
        (Y-extent . ,ly:axis-group-interface::height)
+       (horizontal-skylines . ,ly:separation-item::calc-skylines)
        (meta . ((class . Item)
                 (interfaces . (axis-group-interface
+                               separation-item-interface
                                note-column-interface))))))
 
     (NoteHead
        ;; If you ever change this back, please document! --hwn
        (knee-spacing-correction . 1.0)
        (meta . ((class . Item)
-                (interfaces . (
+                (interfaces . (spacing-interface
                                note-spacing-interface))))))
 
     (NoteName
        (axes . (0))
        (allow-loose-spacing . #t)
        (before-line-breaking . ,ly:paper-column::before-line-breaking)
+       (horizontal-skylines . ,ly:separation-item::calc-skylines)
        ;; (stencil . ,ly:paper-column::print)
        (X-extent . ,ly:axis-group-interface::width)
        
        ;;                       (font-size . -6) (font-name . "sans") (Y-extent . #f)
        (meta . ((class . Paper_column)
                 (interfaces . (paper-column-interface
+                               separation-item-interface
                                axis-group-interface
                                spaceable-grob-interface))))))
 
                          (list ly:self-alignment-interface::x-aligned-on-self)))))
 
        (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (extra-spacing-width . (+inf.0 . -inf.0))
        (self-alignment-X . 0)
        (direction . ,UP)
        (non-musical . #t)
                 (interfaces . (
                                separation-item-interface))))))
 
-    (SeparatingGroupSpanner
-     . (
-       (springs-and-rods . ,ly:separating-group-spanner::set-spacing-rods)
-       (meta . ((class . Spanner)
-                (interfaces . (only-prebreak-interface
-                               
-                               separating-group-spanner-interface))))))
-
     (Slur
      . ((details . ,default-slur-details)
        (control-points . ,ly:slur::calc-control-points)
        (non-musical . #t)
        (stem-spacing-correction . 0.4)
        (meta . ((class . Item)
-                (interfaces . (staff-spacing-interface))))))
+                (interfaces . (spacing-interface
+                               staff-spacing-interface))))))
 
    
     (StaffSymbol
index 12657af88a2974aac5d5c18f7ba4f8c673578c7b..8309ec390f52bbedc80bca10d979c6b5ea7a72d6 100644 (file)
    ly:piano-pedal-bracket::print
    ly:rest::print
    ly:script-interface::print
-   ly:separating-group-spanner::set-spacing-rods
    ly:slur::height
    ly:slur::print
    ly:spacing-spanner::set-springs