]> git.donarmstrong.com Git - lilypond.git/commitdiff
use springs instead of fixed/distance pairs
authorJoe Neeman <joeneeman@gmail.com>
Tue, 19 Jun 2007 00:38:23 +0000 (10:38 +1000)
committerJoe Neeman <joeneeman@gmail.com>
Tue, 26 Jun 2007 12:40:30 +0000 (15:40 +0300)
12 files changed:
lily/include/note-spacing.hh
lily/include/spaceable-grob.hh
lily/include/spring.hh
lily/include/staff-spacing.hh
lily/note-spacing.cc
lily/paper-column.cc
lily/spaceable-grob.cc
lily/spacing-determine-loose-columns.cc
lily/spacing-interface.cc
lily/spacing-spanner.cc
lily/spring-smob.cc
lily/staff-spacing.cc

index dcc9b2fe5a4ba68866ccf77af8482533c35d10f9..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 *);
 };
index 5625bfd61e7e66d2d7319aba512b79eef813c999..98d4def1bc9c1c72a2f8ab9381c9aacd175e2f08 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 add_spring (Grob *me, Grob *to, Spring sp);
   static void get_spring (Grob *me, Grob *other, Real *dist, Real *inv_strength);
 
   DECLARE_GROB_INTERFACE();
index b49d3de1f47843918b0244eb37505e1de1ddc2f3..d9b40cca4654b3c02ef3ad2c9c1c2f0ca49ee041 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  spring.hh -- declare Spring, Column_spring
+  spring.hh -- declare Spring
 
   source file of the GNU LilyPond music typesetter
 
@@ -12,9 +12,8 @@
 #include "lily-proto.hh"
 #include "smobs.hh"
 
-struct Spring
+class Spring
 {
-  Grob *other_;
   Real distance_;
   Real min_distance_;
 
@@ -24,8 +23,24 @@ struct Spring
   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_;}
+
+  void set_distance (Real);
+  void set_min_distance (Real);
+  void set_inverse_stretch_strength (Real);
+  void set_inverse_compress_strength (Real);
+
+  void operator*= (Real);
+  Grob *other_;
 };
 DECLARE_UNSMOB (Spring, spring);
 
+Spring merge_springs (vector<Spring> const &springs);
+
 #endif /* SPRING_HH */
 
index 1553129b575a0b44faa37bc3840a1563fe7ee4c2..12472cc065d727ccb3a663981d7d8348ae78bb31 100644 (file)
@@ -20,7 +20,7 @@ class Staff_spacing
 
 public:
   DECLARE_GROB_INTERFACE();
-  static Spring get_spacing_params (Grob *);
+  static Spring get_spacing (Grob *);
   static Interval bar_y_positions (Grob *);
 };
 
index a886c31a417f0d15f3a60c8d3a0d0dc09be118a8..1274fe98c4b8c8a8150cd6b86602173f348c9846 100644 (file)
@@ -27,9 +27,9 @@
   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)
 {
   vector<Item*> note_columns = Spacing_interface::left_note_columns (me);
   Real left_head_end = 0;
@@ -65,19 +65,15 @@ Note_spacing::get_spacing (Grob *me, Item *right_col,
     the full amount of space.
   */
   Real min_dist = Spacing_interface::minimum_distance (me);
+  Real min_desired_space = max (left_head_end + (min_dist - left_head_end) / 2,
+                               min_dist - (base_space - increment) / 2);
+  Real ideal = base_space - increment + min_desired_space;
 
-  *fixed = max (left_head_end + (min_dist - left_head_end) / 2,
-               min_dist - (base_space - increment) / 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;
+  stem_dir_correction (me, right_col, increment, &ideal, &min_desired_space);
 
-  stem_dir_correction (me, right_col, increment, space, fixed);
+  Spring ret (ideal, min_dist);
+  ret.set_inverse_compress_strength (ideal - max (min_dist, min_desired_space));
+  return ret;
 }
 
 
index 62f68b105e26f4b7dd8925c8a8e238179cba9cb6..e3f462894acae72e750eb702083073e59922af83 100644 (file)
@@ -184,7 +184,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 +192,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 77793e5492fddb322b6e17c21c04c58ff4aedaae..464e0d3b1c1ddc50b6ec591c82110fa403cfda69 100644 (file)
@@ -59,22 +59,6 @@ void
 Spaceable_grob::add_spring (Grob *me, Grob *other,
                            Real distance, Real inverse_strength)
 {
-  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))
@@ -89,9 +73,9 @@ Spaceable_grob::add_spring (Grob *me, Grob *other,
 #endif
 
   Spring spring;
-  spring.inverse_stretch_strength_ = inverse_strength;
-  spring.inverse_compress_strength_ = inverse_strength;
-  spring.distance_ = distance;
+  spring.set_inverse_stretch_strength (inverse_strength);
+  spring.set_inverse_compress_strength (inverse_strength);
+  spring.set_distance (distance);
   spring.other_ = other;
 
   SCM ideal = me->get_object ("ideal-distances");
@@ -99,6 +83,15 @@ Spaceable_grob::add_spring (Grob *me, Grob *other,
   me->set_object ("ideal-distances", ideal);
 }
 
+void
+Spaceable_grob::add_spring (Grob *me, Grob *other, Spring sp)
+{
+  SCM ideal = me->get_object ("ideal-distances");
+  sp.other_ = other;
+  ideal = scm_cons (sp.smobbed_copy (), ideal);
+  me->set_object ("ideal-distances", ideal);
+}
+
 void
 Spaceable_grob::get_spring (Grob *this_col, Grob *next_col, Real *dist, Real *inv_strength)
 {
@@ -118,8 +111,8 @@ Spaceable_grob::get_spring (Grob *this_col, Grob *next_col, Real *dist, Real *in
     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_stretch_strength_ : 1.0;
+  *dist = (spring) ? spring->distance () : 5.0;
+  *inv_strength = (spring) ? spring->inverse_stretch_strength () : 1.0;
 }
 
 
index 7274ef1363b4fdeaf504aec7157dea257be97cf8..ef5e8c71de866b0179192ef8706b2723ee8a6a88 100644 (file)
@@ -154,23 +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;
-                 
              Real base = note_spacing (me, lc, rc, options);
-             Note_spacing::get_spacing (sp, rc, base, options->increment_,
-                                        &space, &fixed);
+             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))
            {
-             Spring spring = Staff_spacing::get_spacing_params (sp);
-             Real fixed = spring.distance_ - spring.inverse_compress_strength_;
+             Spring spring = Staff_spacing::get_spacing (sp);
 
-             dists[d] = max (dists[d], fixed);
+             dists[d] = max (dists[d], spring.min_distance ());
            }
          else
            programming_error ("Subversive spacing wish");
index 82f6fccdb763c6a610cbdf514a99997f8daef23d..33a4e14d399c1d679fe2e4cbf99b091759f52299 100644 (file)
@@ -66,7 +66,7 @@ Spacing_interface::minimum_distance (Grob *me)
     }
   while (flip (&d) != LEFT);
 
-  return skylines[LEFT].distance (skylines[RIGHT]);
+  return max (0.0, skylines[LEFT].distance (skylines[RIGHT]));
 }
 
 /*
index 69b0de980bd635c840d6625c4d8bb41de03ce550..d158883dadf40a9c9ef5ee63e07bda5e9cf9dc2f 100644 (file)
@@ -237,37 +237,15 @@ Spacing_spanner::musical_column_spacing (Grob *me,
                                         Spacing_options const *options)
 {
   Real base_note_space = note_spacing (me, left_col, right_col, options);
-
-  Real max_fixed = 0;
-  Real max_space = 0;
-  Real compound_note_space = 0.0;
-  Real compound_fixed_note_space = 0.0;
+  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];
@@ -281,32 +259,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++;
-           }
-       }
-
-      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;
+           springs.push_back (Note_spacing::get_spacing (wish, right_col, base_note_space, options->increment_));
        }
 
-      if (compound_note_space < 0 || wish_count == 0)
+      if (springs.empty ())
        {
 
          if (!Paper_column::is_musical (right_col))
@@ -317,9 +273,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
            {
@@ -327,44 +282,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.
   */
@@ -379,16 +320,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);
 }
 
 /*
@@ -460,9 +396,9 @@ Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r,
          */
          assert (spacing_grob->get_column () == l);
 
-         Spring sp = Staff_spacing::get_spacing_params (spacing_grob);
-         Real space = sp.distance_;
-         Real fixed = sp.distance_ - sp.inverse_compress_strength_;
+         Spring sp = Staff_spacing::get_spacing (spacing_grob);
+         Real space = sp.distance ();
+         Real fixed = sp.min_distance ();
 
          if (Paper_column::when_mom (r).grace_part_)
            {
index a466fb44bb44d242aa7cb9da08c81d15a191946d..5639a1cd0737446b8318f3c3a12b9712acc69007 100644 (file)
 #include "warn.hh"
 #include "ly-smobs.icc"
 
-Spring::Spring ()
-{
-  distance_ = 1.0;
-  min_distance_ = 1.0;
-  inverse_stretch_strength_ = 1.0;
-  inverse_compress_strength_ = 1.0;
-  other_ = 0;
-}
-
 IMPLEMENT_SIMPLE_SMOBS (Spring);
 
 SCM
index 08ef57839909c230502e61cbe2ab4b87a1754ecb..b9fd874b9e9aba08e11cd6223ef701961e6fd19a 100644 (file)
@@ -107,7 +107,7 @@ Staff_spacing::next_notes_correction (Grob *me,
    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)
+Staff_spacing::get_spacing (Grob *me)
 {
   Grob *separation_item = 0;
   Item *me_item = dynamic_cast<Item *> (me);
@@ -199,10 +199,8 @@ Staff_spacing::get_spacing_params (Grob *me)
   fixed += correction;
   ideal += correction;
 
-  Spring ret;
-  ret.min_distance_ = max (min_dist, fixed);
-  ret.distance_ = ideal;
-  ret.inverse_stretch_strength_ = ret.inverse_compress_strength_ = ideal - fixed;
+  Spring ret (ideal, min_dist);
+  ret.set_inverse_stretch_strength (ideal - fixed);
   return ret;
 }