]> git.donarmstrong.com Git - lilypond.git/commitdiff
Clean up spring stuff.
authorJoe Neeman <joeneeman@gmail.com>
Sat, 2 Jun 2007 10:41:51 +0000 (20:41 +1000)
committerJoe Neeman <joeneeman@gmail.com>
Sun, 17 Jun 2007 02:20:36 +0000 (12:20 +1000)
lily/include/spring.hh
lily/include/staff-spacing.hh
lily/paper-column.cc
lily/spaceable-grob.cc
lily/spacing-determine-loose-columns.cc
lily/spacing-spanner.cc
lily/spring-smob.cc
lily/staff-spacing.cc

index 11989b3ad03c6735fdf21e26afb4fb29a3f76578..b49d3de1f47843918b0244eb37505e1de1ddc2f3 100644 (file)
 #include "lily-proto.hh"
 #include "smobs.hh"
 
-struct Spring_smob
+struct 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 ();
+  DECLARE_SIMPLE_SMOBS (Spring);
+public:
   Spring ();
 };
+DECLARE_UNSMOB (Spring, spring);
 
 #endif /* SPRING_HH */
 
index b4241f2800b323363efc57cd57cc7d0a44b8dae4..6180e102026aa4f86902a10c9cf633deeb3f6059 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 left_stickout (Grob *, Grob *);
+  static Real next_notes_correction (Grob *, Grob *, Real, Real);
+
 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_params (Grob *);
   static Interval bar_y_positions (Grob *);
 };
 
index 1578688925befd5e7eb9de5f68ab3fbfb3954529..62f68b105e26f4b7dd8925c8a8e238179cba9cb6 100644 (file)
@@ -175,7 +175,7 @@ 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));
+      Spring *sp = unsmob_spring (scm_car (s));
       if (!sp->other_->get_system ())
        continue;
       
index 806e300cfa5ff714b4ffb9c38192ccae35aec3e4..77793e5492fddb322b6e17c21c04c58ff4aedaae 100644 (file)
@@ -79,7 +79,7 @@ Spaceable_grob::add_spring (Grob *me, Grob *other,
   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));
+      Spring *sp = unsmob_spring (scm_car (s));
       if (sp->other_ == other)
        {
          programming_error ("already have that spring");
@@ -88,8 +88,9 @@ Spaceable_grob::add_spring (Grob *me, Grob *other,
     }
 #endif
 
-  Spring_smob spring;
-  spring.inverse_strength_ = inverse_strength;
+  Spring spring;
+  spring.inverse_stretch_strength_ = inverse_strength;
+  spring.inverse_compress_strength_ = inverse_strength;
   spring.distance_ = distance;
   spring.other_ = other;
 
@@ -101,13 +102,13 @@ Spaceable_grob::add_spring (Grob *me, Grob *other,
 void
 Spaceable_grob::get_spring (Grob *this_col, Grob *next_col, Real *dist, Real *inv_strength)
 {
-  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));
+      Spring *sp = unsmob_spring (scm_car (s));
 
       if (sp && sp->other_ == next_col)
        spring = sp;
@@ -118,7 +119,7 @@ Spaceable_grob::get_spring (Grob *this_col, Grob *next_col, Real *dist, Real *in
                           Paper_column::get_rank (this_col)));
 
   *dist = (spring) ? spring->distance_ : 5.0;
-  *inv_strength = (spring) ? spring->inverse_strength_ : 1.0;
+  *inv_strength = (spring) ? spring->inverse_stretch_strength_ : 1.0;
 }
 
 
index e491730869194be0ea929912f6231701285a6917..45f2f0ae7ce56f2dace4a5112810c584baec426a 100644 (file)
@@ -166,12 +166,10 @@ Spacing_spanner::set_distances_for_loose_col (Grob *me, Grob *c,
            }
          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_params (sp);
+             Real fixed = spring.distance_ - spring.inverse_compress_strength_;
 
-             dists[d] = max (dists[d], fixed_space);
+             dists[d] = max (dists[d], fixed);
            }
          else
            programming_error ("Subversive spacing wish");
index 13c2964edba19d063947005f41e6935892a143d0..568283846d345b99065c56f3c0d922e0922f9804 100644 (file)
@@ -454,17 +454,15 @@ 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);
+         Spring sp = Staff_spacing::get_spacing_params (spacing_grob);
+         Real space = sp.distance_;
+         Real fixed = sp.distance_ - sp.inverse_compress_strength_;
 
          if (Paper_column::when_mom (r).grace_part_)
            {
@@ -477,10 +475,10 @@ Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r,
            }
 
          max_space = max (max_space, space);
-         max_fixed = max (max_fixed, fixed_space);
+         max_fixed = max (max_fixed, fixed);
          
          compound_space += space;
-         compound_fixed += fixed_space;
+         compound_fixed += fixed;
          wish_count++;
        }
     }
@@ -521,6 +519,7 @@ Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r,
 
   Real inverse_strength = (compound_space - compound_fixed);
   Real distance = compound_space;
+  message (_f ("adding spring of length %f", distance));
   Spaceable_grob::add_spring (l, r, distance, inverse_strength);
 }
 
index a57f5029f2d2eef8c160f6173a67ea8761164361..a466fb44bb44d242aa7cb9da08c81d15a191946d 100644 (file)
 #include "warn.hh"
 #include "ly-smobs.icc"
 
-Spring_smob::Spring_smob ()
+Spring::Spring ()
 {
-  distance_ = 0.;
-  inverse_strength_ = 1.0;
-  expand_only_b_ = false;
+  distance_ = 1.0;
+  min_distance_ = 1.0;
+  inverse_stretch_strength_ = 1.0;
+  inverse_compress_strength_ = 1.0;
   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 +30,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;
 }
index e688d60cfbcbcbb300de09907c4179f05d067a61..b93a4ee6b00bdd514c203ef7536ffc00730b395f 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"
@@ -22,28 +23,14 @@ using namespace std;
 #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
-*/
-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::left_stickout (Grob *me, Grob *g)
 {
-  (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;
+  Real ret = max (0., (- g->extent (col, X_AXIS)[LEFT]));
 
   /*
     Duh. If this gets out of hand, we should invent something more generic.
@@ -57,26 +44,25 @@ Staff_spacing::next_note_correction (Grob *me,
       else
        v = accs->extent (col, X_AXIS);
       
-      left_stickout_correction = max (left_stickout_correction, (- v[LEFT]));
+      ret = max (ret, (- 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]);
+    ret = max (ret, - 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;
+  return ret;
+}
+
+Real
+Staff_spacing::optical_correction (Grob *me, Grob *g, Interval bar_height)
+{
+  if (!g || !Note_column::has_interface (g))
+    return 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)
@@ -93,28 +79,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.  */
@@ -148,68 +121,54 @@ Staff_spacing::bar_y_positions (Grob *bar_grob)
   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,
+                                     Real current_fixed,
+                                     Real right_stickout)
 {
   Interval bar_size = bar_y_positions (last_grob);
   Grob *orig = me->original () ? me->original () : me;
 
   extract_grob_set (orig, "right-items", right_items);
 
-  *compound_fixed = 0.0;
-  *compound_space = 0.0;
-  int wish_count = 0;
+  Real max_left_stickout = 0.0;
+  Real max_optical = 0.0;
 
   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; 
+         max_left_stickout = max (max_left_stickout, left_stickout (me, g));
+         max_optical = max (max_optical, optical_correction (me, g, bar_size));
        }
       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;
+             max_left_stickout = max (max_left_stickout, left_stickout (me, elts[j]));
+             max_optical = max (max_optical, optical_correction (me, g, bar_size));
            }
        }
     }
-  
-  if (wish_count > 1)
-    {
-      *compound_space /= wish_count;
-      *compound_fixed /= wish_count;
-    }
+
+  /* we put a minimum distance of 0.3 between the right edge of the left grob and
+     the left edge of the right grob */
+  max_left_stickout = max (0.0, max_left_stickout + right_stickout + 0.3 - current_fixed);
+  return max (max_left_stickout, max_optical);
 }
 
-void
-Staff_spacing::get_spacing_params (Grob *me, Real *space, Real *fixed)
+/* This routine does not impose any minimum distances between columns; it only
+   affects springs. As such, the FIXED variable does not refer to a minimum
+   distance between columns, but instead to a minimum desired distance between
+   columns -- this ends up affecting the stiffness of a spring. In fact, FIXED
+   will be the distance between columns if there is a compression force of 1.0
+   applied to the line. */
+Spring
+Staff_spacing::get_spacing_params (Grob *me)
 {
-  *space = 1.0;
-  *fixed = 1.0;
-
   Grob *separation_item = 0;
   Item *me_item = dynamic_cast<Item *> (me);
 
@@ -225,7 +184,7 @@ Staff_spacing::get_spacing_params (Grob *me, Real *space, Real *fixed)
   if (!separation_item)
     {
       programming_error ("no sep item");
-      return;
+      return Spring ();
     }
 
   Interval last_ext;
@@ -244,15 +203,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)
@@ -265,41 +221,45 @@ 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 correction = next_notes_correction (me, last_grob, fixed, last_ext[RIGHT]);
+  fixed += correction;
+  ideal += correction;
+
+  Spring ret;
+  ret.min_distance_ = 0.0;
+  ret.distance_ = ideal;
+  ret.inverse_stretch_strength_ = ret.inverse_compress_strength_ = ideal - fixed;
+  return ret;
 }
 
 ADD_INTERFACE (Staff_spacing,