]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fixes Issue 1301 (colliding note and clef).
authorMike Solomon <mike@apollinemike.com>
Thu, 22 Sep 2011 07:05:58 +0000 (09:05 +0200)
committerMike Solomon <mike@apollinemike.com>
Thu, 22 Sep 2011 07:05:58 +0000 (09:05 +0200)
Loose columns are now:

-) better spaced between their fixed counterpoints
   see spacing-loose-columns.cc
-) spaced with respect to the left column against which they collide,
   not the column directly to the left.
   see spacing-determine-loose-columns.cc

input/regression/spacing-loose-polyphony.ly [new file with mode: 0644]
lily/spacing-determine-loose-columns.cc
lily/spacing-loose-columns.cc

diff --git a/input/regression/spacing-loose-polyphony.ly b/input/regression/spacing-loose-polyphony.ly
new file mode 100644 (file)
index 0000000..cb53987
--- /dev/null
@@ -0,0 +1,17 @@
+\version "2.15.13"
+
+\header {
+  texidoc = "Loose columns (here, the treble clef) are spaced
+correctly in polyphonic music.
+"
+}
+
+\new PianoStaff <<
+  \new Staff \relative c' {
+    \times 2/3 { g'4 a2 }
+  }
+  \new Staff \relative c' {
+    \clef bass fis,,8 cis'
+    \clef treble g'' fis,
+  }
+>>
index 99d9e596af48f0a6a8136c685dd0eded457292b8..a195495529d25046fcc088b7b8f0a60c81aefcd2 100644 (file)
@@ -191,7 +191,6 @@ Spacing_spanner::prune_loose_columns (Grob *me,
                                       Spacing_options *options)
 {
   vector<Grob *> newcols;
-
   for (vsize i = 0; i < cols->size (); i++)
     {
       Grob *c = cols->at (i);
@@ -243,14 +242,14 @@ Spacing_spanner::prune_loose_columns (Grob *me,
               /*
                 Set distance constraints for loose columns
               */
-              Drul_array<Item *> next_door (dynamic_cast<Item *> (cols->at (i - 1)),
-                                            dynamic_cast<Item *> (cols->at (i + 1)));
+              Drul_array<Item *> next_door (dynamic_cast<Item *> (left_neighbor),
+                                            dynamic_cast<Item *> (right_neighbor));
 
               set_distances_for_loose_col (me, c, next_door, options);
             }
         }
 
-      if (!loose)
+      else
         newcols.push_back (c);
     }
 
index fb5e326369e5caaf79c6e19a4d5ff95ca793126b..cc706fb6b0b9f5944753649e254672802333e84c 100644 (file)
@@ -112,8 +112,21 @@ set_loose_columns (System *which, Column_x_positions const *posns)
 
       clique.push_back (right);
 
+      /*
+        We use two vectors to keep track of loose column spacing:
+          clique_spacing keeps track of ideal spaces.
+          clique_tight_spacing keeps track of minimum spaces.
+        Below, a scale factor is applied to the shifting of loose columns that
+        aims to preserve clique_spacing but gets closer to clique_tight_spacing as the
+        space becomes smaller.  This is used because the rods placed for loose columns
+        are tight (meaning they use minimum distances - see set_distances_for_loose_columns).
+        However, other rods may widen this distance, in which case we don't want a crammed score.
+        Thus, we aim for non-crammed, and fall back on crammed as needed.
+      */
       vector<Real> clique_spacing;
+      vector<Real> clique_tight_spacing;
       clique_spacing.push_back (0.0);
+      clique_tight_spacing.push_back (0.0);
       for (vsize j = 1; j + 1 < clique.size (); j++)
         {
           Grob *clique_col = clique[j];
@@ -134,11 +147,25 @@ set_loose_columns (System *which, Column_x_positions const *posns)
             programming_error ("Column without spacing object");
 
           Real base_note_space = 0.0;
+          Real tight_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);
+            {
+              Real base = Spacing_spanner::note_spacing (spacing, loose_col, next_col,
+                                                         &options);
+              if (Note_spacing::has_interface (spacing))
+                {
+                  Spring spring = Note_spacing::get_spacing (spacing, next_col, base, options.increment_);;
+                  base_note_space = spring.distance ();
+                  tight_note_space = spring.min_distance ();
+                }
+              else
+                {
+                  base_note_space = base;
+                  tight_note_space = base;
+                }
+            }
           else
             {
               Spring spring = Spacing_spanner::standard_breakable_column_spacing (spacing,
@@ -146,29 +173,34 @@ set_loose_columns (System *which, Column_x_positions const *posns)
                               &options);
 
               base_note_space = spring.distance ();
+              tight_note_space = spring.min_distance ();
             }
 
-          base_note_space = max (base_note_space,
-                                 robust_relative_extent (loose_col, loose_col, X_AXIS)[RIGHT]
-                                 - robust_relative_extent (next_col, next_col, X_AXIS)[LEFT]);
-
           clique_spacing.push_back (base_note_space);
+          clique_tight_spacing.push_back (tight_note_space);
         }
 
-      Real default_padding = 1.0;
-      clique_spacing.push_back (default_padding);
-
+      Real permissible_distance = clique.back ()->relative_coordinate (common, X_AXIS) - robust_relative_extent (clique[0], common, X_AXIS)[RIGHT];
       Real right_point = robust_relative_extent (clique.back (), common, X_AXIS)[LEFT];
-
       Grob *finished_right_column = clique.back ();
 
+      Real sum_tight_spacing = 0;
+      Real sum_spacing = 0;
+      // currently a magic number - what would be a good grob to hold this property?
+      Real left_padding = 0.15;
+      for (vsize j = 0; j  < clique_spacing.size (); j++)
+        {
+          sum_tight_spacing += clique_tight_spacing[j];
+          sum_spacing += clique_spacing[j];
+        }
+      Real scale_factor = max (0.0, min (1.0, (permissible_distance - left_padding - sum_tight_spacing) / (sum_spacing - sum_tight_spacing)));
       for (vsize j = clique.size () - 2; j > 0; j--)
         {
           Paper_column *clique_col = dynamic_cast<Paper_column *> (clique[j]);
 
           right_point = finished_right_column->relative_coordinate (common, X_AXIS);
 
-          Real distance_to_next = clique_spacing[j];
+          Real distance_to_next = clique_tight_spacing[j] + (clique_spacing[j] - clique_tight_spacing[j]) * scale_factor;
 
           Real my_offset = right_point - distance_to_next;