]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/rest-collision.cc
*** empty log message ***
[lilypond.git] / lily / rest-collision.cc
index 591d90b3868998dc9cd58be9e715bd74139f5ec7..c50cff5b19f70defea42b21f28d282beae1b2d96 100644 (file)
@@ -3,12 +3,12 @@
 
   source file of the GNU LilyPond music typesetter
 
-  (c)  1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c)  1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
 */
 
 #include <math.h>              // ceil.
 
-#include "debug.hh"
+#include "warn.hh"
 #include "rest-collision.hh"
 #include "note-column.hh"
 #include "stem.hh"
@@ -29,15 +29,11 @@ Rest_collision::force_shift_callback (SCM element_smob, SCM axis)
 
   Grob * rc = unsmob_grob (them->get_grob_property ("rest-collision"));
 
-  if (rc)
+  if (rc && !to_boolean (rc->get_grob_property ("rest-collision-done")))
     {
-      /*
-       Done: destruct pointers, so we do the shift only once.
-      */
-      SCM elts = rc->get_grob_property ("elements");
-      rc->set_grob_property ("elements", SCM_EOL);
+      rc->set_grob_property ("rest-collision-done", SCM_BOOL_T);
 
-      do_shift (rc, elts);
+      do_shift (rc);
     }
   
   return gh_double2scm (0.0);
@@ -47,10 +43,11 @@ void
 Rest_collision::add_column (Grob*me,Grob *p)
 {
   me->add_dependency (p);
-  Pointer_group_interface::add_element (me, "elements", p);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), p);
 
   /*
-    only add callback for the rests, since we don't move anything else.
+    only add callback for the rests, since we don't move anything
+    else.
 
  (not?)
   */
@@ -79,29 +76,18 @@ head_characteristic (Grob * col)
 
   TODO: look at horizontal-shift to determine ordering between rests
   for more than two voices.
-  
  */
 SCM
-Rest_collision::do_shift (Grob *me, SCM elts)
+Rest_collision::do_shift (Grob *me)
 {
-  /*
-    ugh. -> score  elt type
-   */
+  SCM elts = me->get_grob_property ("elements");
+
   Link_array<Grob> rests;
   Link_array<Grob> notes;
-  Grob * commony = 0;
-  for (SCM s = elts; gh_pair_p (s); s = gh_cdr (s))
+
+  for (SCM s = elts; gh_pair_p (s); s = ly_cdr (s))
     {
-      
-      Grob * e = unsmob_grob (gh_car (s));
-      if (!e)
-       continue;
-      
-      if (!commony)
-       commony = e;
-      else
-       commony= commony->common_refpoint (e, Y_AXIS);
-      
+      Grob * e = unsmob_grob (ly_car (s));
       if (unsmob_grob (e->get_grob_property ("rest")))
        rests.push (e);
       else
@@ -152,9 +138,25 @@ Rest_collision::do_shift (Grob *me, SCM elts)
          for (; i > display_count; i--)
            {
              Grob* r = unsmob_grob (rests[i-1]->get_grob_property ("rest"));
+#if 1
              if (r)
-               r->suicide ();
+               {
+                 Grob * d = unsmob_grob (r->get_grob_property ("dot"));
+                 if (d)
+                   d->suicide();
+                 r->suicide ();
+               }
              rests[i-1]->suicide ();
+#else
+             if (r)
+               {
+                 
+                 r->set_grob_property ("transparent", gh_bool2scm(1));
+                 r = unsmob_grob (r->get_grob_property ("dot"));
+                 if (r)
+                   r->set_grob_property ("transparent", gh_bool2scm(1));
+               }
+#endif
            }
        }
       else
@@ -193,35 +195,31 @@ Rest_collision::do_shift (Grob *me, SCM elts)
        {
          warning (_ ("too many colliding rests"));
        }
-      if (notes.size () > 1)
-       {
-         warning (_ ("too many notes for rest collision"));
-       }
       Grob * rcol = rests[0];
+      Direction dir = Note_column::dir (rests[0]);
 
-      // try to be opposite of noteheads. 
-      Direction dir = - Note_column::dir (notes[0]);
-
+      if (!dir)
+       {
+         dir = - Note_column::dir (notes[0]);
+       }
       Grob * r = unsmob_grob (rcol->get_grob_property ("rest"));
       Interval restdim = r->extent (r, Y_AXIS);        // ??
 
       if (restdim.empty_b ())
        return SCM_UNSPECIFIED;
       
-      // FIXME: staff ref'd?
-      Real staff_space = 1.0;
+
+      Real staff_space = Staff_symbol_referencer::staff_space (rcol);
 
       Real minimum_dist = gh_scm2double (me->get_grob_property ("minimum-distance")) * staff_space;
-      
-      /*
-       assumption: ref points are the same. 
-       */
+
+
+      Grob *common = common_refpoint_of_array (notes, rcol, Y_AXIS);
+
       Interval notedim;
       for (int i = 0; i < notes.size (); i++) 
        {
-         Grob * stem = Note_column::stem_l (notes[i]);
-         Grob * head = Stem::first_head (stem);
-         notedim.unite (head->extent (commony, Y_AXIS));
+         notedim.unite (notes[i]->extent (common, Y_AXIS));
        }
 
       Interval inter (notedim);
@@ -230,12 +228,12 @@ Rest_collision::do_shift (Grob *me, SCM elts)
       Real dist =
        minimum_dist +  dir * (notedim[dir] - restdim[-dir]) >? 0;
 
-
-      // FIXME
-      //int stafflines = 5; // rcol->rests[0]->line_count;
       int stafflines = Staff_symbol_referencer::line_count (me);
-      // hurg?
-      stafflines = stafflines != 0 ? stafflines : 5;
+      if (!stafflines)
+       {
+         programming_error ("No staff line count ? ");
+         stafflines =5;
+       }
       
       // move discretely by half spaces.
       int discrete_dist = int (ceil (dist / (0.5 *staff_space)));
@@ -249,10 +247,9 @@ Rest_collision::do_shift (Grob *me, SCM elts)
   return SCM_UNSPECIFIED;
 }
 
-void
-Rest_collision::set_interface (Grob*me)
-{
-  me->set_extent_callback (SCM_EOL, X_AXIS);
-  me->set_extent_callback (SCM_EOL, Y_AXIS);
-}
+
+ADD_INTERFACE (Rest_collision,"rest-collision-interface",
+  "Move around ordinary rests (not multi-measure-rests) to avoid "
+"conflicts.",
+  "maximum-rest-count minimum-distance rest-collision-done elements");