]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/accidental-placement.cc
* Documentation/user/refman.itely: Compile fix for \mark #'(music ...).
[lilypond.git] / lily / accidental-placement.cc
index acac43671a645e77b5b13979c30cd036e5fbd827..9a0ab1fec317539dbc79556be67644ce3f892c02 100644 (file)
@@ -15,7 +15,9 @@ source file of the GNU LilyPond music typesetter
 #include "pitch.hh"
 #include "warn.hh"
 #include "accidental-placement.hh"
-
+#include "note-column.hh"
+#include "group-interface.hh"
+#include "note-collision.hh"
 
 MAKE_SCHEME_CALLBACK(Accidental_placement,extent_callback, 2);
 SCM
@@ -99,11 +101,27 @@ struct Accidental_placement_entry
   }
 };
 
+static Interval all_accidental_vertical_extent;
+Real ape_priority (Accidental_placement_entry const * a)
+{
+  Real c = a->vertical_extent_.center();
+
+  /*
+    far from center means we can fold more. Hopefully.
+   */
+  Real center_distance =
+    fabs(c - all_accidental_vertical_extent[LEFT]) >?
+    fabs(c - all_accidental_vertical_extent[RIGHT]);
+  
+  return 20 * a->vertical_extent_.length  ()  + center_distance;
+}
+
+  
 
 int ape_compare (Accidental_placement_entry *const &a,
                 Accidental_placement_entry *const &b)
 {
-  return sign (a->vertical_extent_.length () - b->vertical_extent_.length());
+  return sign (ape_priority (a) - ape_priority(b));
 }
 
 /*
@@ -157,15 +175,63 @@ Accidental_placement::position_accidentals (Grob * me)
 
 
   Grob *commony =0 ;
+
+  /*
+    First we must extract *all* pointers. We can only determine
+    extents if we're sure that we've found the right common refpoint
+   */
+  Link_array<Grob> note_cols, heads;
   for (int i= apes.size (); i--;)
-    commony = common_refpoint_of_array  (apes[i]->grobs_, commony, Y_AXIS);
+    { 
+      Accidental_placement_entry * ape = apes[i];
+      for (int j = ape->grobs_.size(); j--;)
+       {
+         Grob * a = ape->grobs_[j];
+         
+         commony = commony->common_refpoint (a, Y_AXIS);
+         Grob *head = a->get_parent (Y_AXIS);
+
+         Grob * col = head->get_parent (X_AXIS);
+         if (Note_column::has_interface (col))
+           note_cols.push (col);
+         else
+           heads.push (head);
+       }
+    }
+
+  /*
+    This is a little kludgy: to get all notes, we look if there are
+    collisions as well.
+   */
+  for (int i = note_cols.size() ; i--;)
+    {
+      Grob *c = note_cols[i]->get_parent (X_AXIS);
+      if (Note_collision_interface::has_interface (c))
+       {
+         Link_array<Grob> gs =
+           Pointer_group_interface__extract_grobs (c, (Grob*)0, "elements");
+      
+         note_cols.concat (gs);
+       }
+    }
+  
+  for (int i = note_cols.size() ; i--;)
+    {
+      heads.concat (Pointer_group_interface__extract_grobs (note_cols[i],
+                                                           (Grob*)0,
+                                                           "note-heads"));
+      
+    }
+  heads.default_sort();
+  heads.uniq();
+  commony = common_refpoint_of_array (heads, commony, Y_AXIS);
 
-  Link_array<Grob> heads;
+  
   for (int i= apes.size (); i--;)
     {
       Accidental_placement_entry * ape = apes[i];
-      ape->left_skyline_ = empty_skyline ( LEFT);
-      ape->right_skyline_ = empty_skyline ( RIGHT);
+      ape->left_skyline_ = empty_skyline (LEFT);
+      ape->right_skyline_ = empty_skyline (RIGHT);
    
       for (int j = apes[i]->grobs_.size(); j--;)
        {
@@ -174,12 +240,7 @@ Accidental_placement::position_accidentals (Grob * me)
          b[X_AXIS] = a->extent (me, X_AXIS);
          b[Y_AXIS] = a->extent (commony, Y_AXIS);
 
-         Grob *head = a->get_parent (Y_AXIS);
-         heads.push (head);
-         commony = commony->common_refpoint (head, Y_AXIS);
-         
          ape->extents_.push (b);
-
          
          /*
            TODO: replace the extents of a flat by combination of two
@@ -190,6 +251,8 @@ Accidental_placement::position_accidentals (Grob * me)
        }
     }
 
+
+  Interval total;
   for (int i = apes.size(); i--;)
     {
       Interval y ;
@@ -199,8 +262,9 @@ Accidental_placement::position_accidentals (Grob * me)
          y.unite (apes[i]->extents_[j][Y_AXIS]);
        }
       apes[i]->vertical_extent_ = y;
+      total.unite (y);
     }
-  
+  all_accidental_vertical_extent = total;
   apes.sort (&ape_compare);  
 
   Accidental_placement_entry * head_ape = new Accidental_placement_entry;
@@ -222,26 +286,21 @@ Accidental_placement::position_accidentals (Grob * me)
   if (gh_number_p (rs))
     head_ape->offset_ -= gh_scm2double (rs);
 
-  Real padding = 0.1;
+  
+  Real padding = 0.2;
+  SCM spad = me->get_grob_property ("padding");
+  if (gh_number_p (spad))
+    padding = gh_scm2double (spad);
+  
   apes.push (head_ape);
   for (int i= apes.size () -1 ; i-- > 0;)
     {
       Accidental_placement_entry *ape = apes[i];
       Real d = 0.0;
-      /*
-       confusing naming: left_skyline is a skyline pointing to the
-       left. It is on the right of the curent entry.
-       */
-
       int j = i+1;
       do {
-       Array<Skyline_entry> const *right_sky =
-         (j < apes.size())
-         ? &apes[j]->left_skyline_
-         : &head_skyline;
-
        d = - skyline_meshing_distance (ape->right_skyline_,
-                                            *right_sky);
+                                       apes[j]->left_skyline_);
 
        if (!isinf(d)
            || j + 1 == apes.size())
@@ -297,4 +356,4 @@ Accidental_placement::position_accidentals (Grob * me)
 ADD_INTERFACE(Accidental_placement,
              "accidental-placement-interface",
              "Take care of complex accidental collisions.",
-             "left-padding right-padding accidentals alignment-done")
+             "left-padding padding right-padding accidentals alignment-done")