]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/side-position-interface.cc
''
[lilypond.git] / lily / side-position-interface.cc
index f19e5471ccc8c5d317a26a37301b79e634cc14e6..4ce9df6761ae4118309790159514c86e2d3fb6fc 100644 (file)
@@ -3,7 +3,7 @@
   
   source file of the GNU LilyPond music typesetter
   
   
   source file of the GNU LilyPond music typesetter
   
-  (c) 1998--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c) 1998--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
   
  */
 #include <math.h>              // ceil.
   
  */
 #include <math.h>              // ceil.
 #include "dimensions.hh"
 #include "staff-symbol-referencer.hh"
 #include "group-interface.hh"
 #include "dimensions.hh"
 #include "staff-symbol-referencer.hh"
 #include "group-interface.hh"
+#include "directional-element-interface.hh"
 
 void
 
 void
-Side_position::add_support (Grob*me, Grob*e)
+Side_position_interface::add_support (Grob*me, Grob*e)
 {
 {
-  Pointer_group_interface::add_element (me, "side-support-elements",e);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("side-support-elements"), e);
 }
 
 
 
 Direction
 }
 
 
 
 Direction
-Side_position::get_direction (Grob*me)
+Side_position_interface::get_direction (Grob*me)
 {
   SCM d = me->get_grob_property ("direction");
 {
   SCM d = me->get_grob_property ("direction");
-  if (isdir_b (d) && to_dir (d))
+  if (ly_dir_p (d) && to_dir (d))
     return to_dir (d);
 
   Direction relative_dir = Direction (1);
   SCM reldir = me->get_grob_property ("side-relative-direction");      // should use a lambda.
     return to_dir (d);
 
   Direction relative_dir = Direction (1);
   SCM reldir = me->get_grob_property ("side-relative-direction");      // should use a lambda.
-  if (isdir_b (reldir))
+  if (ly_dir_p (reldir))
     {
       relative_dir = to_dir (reldir);
     }
   
   SCM other_elt = me->get_grob_property ("direction-source");
     {
       relative_dir = to_dir (reldir);
     }
   
   SCM other_elt = me->get_grob_property ("direction-source");
-  Grob * e = unsmob_grob(other_elt);
+  Grob * e = unsmob_grob (other_elt);
   if (e)
     {
   if (e)
     {
-      return (Direction)(relative_dir * Side_position::get_direction (e));
+      return (Direction) (relative_dir * Directional_element_interface::get (e));
     }
   
     }
   
-  return DOWN;
+  return CENTER;
 }
   
 }
   
-/*
-   Callback that does the aligning. Puts the element next to the support
- */
 
 
-MAKE_SCHEME_CALLBACK(Side_position,side_position,2);
+MAKE_SCHEME_CALLBACK (Side_position_interface,aligned_on_support_extents, 2);
 SCM
 SCM
-Side_position::side_position (SCM element_smob, SCM axis)
+Side_position_interface::aligned_on_support_extents (SCM element_smob, SCM axis)
 {
   Grob *me = unsmob_grob (element_smob);
   Axis a = (Axis) gh_scm2int (axis);
 
 {
   Grob *me = unsmob_grob (element_smob);
   Axis a = (Axis) gh_scm2int (axis);
 
-  Grob *common = me->parent_l (a);
+  return general_side_position (me, a, true);
+}
+
+
+/*
+ Puts the element next to the support, optionally taking in
+ account the extent of the support.
+*/
+SCM
+Side_position_interface::general_side_position (Grob * me, Axis a, bool use_extents)
+{
+  Grob *common = me->get_parent (a);
+
+  /*
+    As this is only used as a callback, this is called only once. We
+    could wipe SIDE-SUPPORT-ELEMENTS after we retrieve it to conserve
+    memory; however -- we should look more into benefits of such actions?
+
+    The benefit is small, it seems: total GC times taken don't
+    differ. Would this also hamper Generational GC ?
+    
+  */
   SCM support = me->get_grob_property ("side-support-elements");
   SCM support = me->get_grob_property ("side-support-elements");
-  for (SCM s = support; s != SCM_EOL; s = gh_cdr (s))
+    // me->remove_grob_property ("side-support-elements");
+  for (SCM s = support; s != SCM_EOL; s = ly_cdr (s))
     {
     {
-      Grob * e  = unsmob_grob (gh_car (s));
+      Grob * e  = unsmob_grob (ly_car (s));
       if (e)
        common = common->common_refpoint (e, a);
     }
   
   Interval dim;
       if (e)
        common = common->common_refpoint (e, a);
     }
   
   Interval dim;
-  for (SCM s = support; s != SCM_EOL; s = gh_cdr (s))
+  for (SCM s = support; s != SCM_EOL; s = ly_cdr (s))
     {
     {
-
-      Grob * e  = unsmob_grob ( gh_car (s));
+      Grob * e  = unsmob_grob (ly_car (s));
       if (e)
       if (e)
-       {
+       if (use_extents)
          dim.unite (e->extent (common, a));
          dim.unite (e->extent (common, a));
-       }
+       else
+         {
+           Real x = e->relative_coordinate (common, a);
+           dim.unite (Interval (x,x));
+         }
     }
 
   if (dim.empty_b ())
     {
     }
 
   if (dim.empty_b ())
     {
-      dim = Interval(0,0);
+      dim = Interval (0,0);
     }
 
     }
 
-  Direction dir = Side_position::get_direction (me);
+  Direction dir = Side_position_interface::get_direction (me);
     
     
-  Real off =  me->parent_l (a)->relative_coordinate (common, a);
+  Real off =  me->get_parent (a)->relative_coordinate (common, a);
   SCM minimum = me->remove_grob_property ("minimum-space");
 
   SCM minimum = me->remove_grob_property ("minimum-space");
 
-  Real total_off = dim[dir] + off;
+  Real total_off = dim.linear_combination (dir) + off;
   SCM padding = me->remove_grob_property ("padding");
   if (gh_number_p (padding))
     {
       total_off += gh_scm2double (padding) * dir;
     }
   SCM padding = me->remove_grob_property ("padding");
   if (gh_number_p (padding))
     {
       total_off += gh_scm2double (padding) * dir;
     }
-  if (gh_number_p (minimum) && total_off * dir < gh_scm2double (minimum))
+
+  if (gh_number_p (minimum) 
+      && dir
+      && total_off * dir < gh_scm2double (minimum))
     {
       total_off = gh_scm2double (minimum) * dir;
     }
     {
       total_off = gh_scm2double (minimum) * dir;
     }
+
   if (fabs (total_off) > 100 CM)
     programming_error ("Huh ? Improbable staff side dim.");
 
   return gh_double2scm (total_off);
 }
 
   if (fabs (total_off) > 100 CM)
     programming_error ("Huh ? Improbable staff side dim.");
 
   return gh_double2scm (total_off);
 }
 
+/*
+  Cut & paste (ugh.)
+ */
+MAKE_SCHEME_CALLBACK (Side_position_interface,aligned_on_support_refpoints,2);
+SCM
+Side_position_interface::aligned_on_support_refpoints (SCM smob, SCM axis)
+{
+  Grob *me = unsmob_grob (smob);
+  Axis a = (Axis) gh_scm2int (axis);
+
+  return  general_side_position (me, a, false); 
+}
+
+
 /**
   callback that centers the element on itself
 /**
   callback that centers the element on itself
+
+  Requires that self-alignment-{X,Y} be set.
  */
  */
-MAKE_SCHEME_CALLBACK(Side_position,aligned_on_self,2);
+MAKE_SCHEME_CALLBACK (Side_position_interface,aligned_on_self,2);
 SCM
 SCM
-Side_position::aligned_on_self (SCM element_smob, SCM axis)
+Side_position_interface::aligned_on_self (SCM element_smob, SCM axis)
 {
   Grob *me = unsmob_grob (element_smob);
   Axis a = (Axis) gh_scm2int (axis);
   String s ("self-alignment-");
 
 {
   Grob *me = unsmob_grob (element_smob);
   Axis a = (Axis) gh_scm2int (axis);
   String s ("self-alignment-");
 
-  s +=  (a == X_AXIS) ? "X" : "Y";
+  s += (a == X_AXIS) ? "X" : "Y";
 
 
-  SCM align (me->get_grob_property (s.ch_C()));
+  SCM align (me->get_grob_property (s.ch_C ()));
   if (gh_number_p (align))
     {
   if (gh_number_p (align))
     {
-      Interval ext(me->extent (me,a));
+      Interval ext (me->extent (me,a));
 
       if (ext.empty_b ())
        {
 
       if (ext.empty_b ())
        {
@@ -136,7 +179,7 @@ Side_position::aligned_on_self (SCM element_smob, SCM axis)
     {
       return gh_double2scm (- unsmob_grob (align)->relative_coordinate (me,  a));
     }
     {
       return gh_double2scm (- unsmob_grob (align)->relative_coordinate (me,  a));
     }
-    return gh_double2scm (0.0);
+  return gh_double2scm (0.0);
 }
 
 
 }
 
 
@@ -155,22 +198,22 @@ directed_round (Real f, Direction d)
   of the elements "direction" elt property.
 
   Only rounds when we're inside the staff, as determined by
   of the elements "direction" elt property.
 
   Only rounds when we're inside the staff, as determined by
-  Staff_symbol_referencer::staff_radius() */
-MAKE_SCHEME_CALLBACK(Side_position,quantised_position,2);
+  Staff_symbol_referencer::staff_radius () */
+MAKE_SCHEME_CALLBACK (Side_position_interface,quantised_position,2);
 SCM
 SCM
-Side_position::quantised_position (SCM element_smob, SCM )
+Side_position_interface::quantised_position (SCM element_smob, SCM)
 {
   Grob *me = unsmob_grob (element_smob);
   
   
 {
   Grob *me = unsmob_grob (element_smob);
   
   
-  Direction d = Side_position::get_direction (me);
+  Direction d = Side_position_interface::get_direction (me);
 
   if (Staff_symbol_referencer::has_interface (me))
     {
       Real p = Staff_symbol_referencer::position_f (me);
       Real rp = directed_round (p, d);
       Real rad = Staff_symbol_referencer::staff_radius (me) *2 ;
 
   if (Staff_symbol_referencer::has_interface (me))
     {
       Real p = Staff_symbol_referencer::position_f (me);
       Real rp = directed_round (p, d);
       Real rad = Staff_symbol_referencer::staff_radius (me) *2 ;
-      int ip = int  (rp);
+      int ip = int (rp);
 
       if (abs (ip) <= rad && Staff_symbol_referencer::on_staffline (me,ip))
        {
 
       if (abs (ip) <= rad && Staff_symbol_referencer::on_staffline (me,ip))
        {
@@ -186,20 +229,26 @@ Side_position::quantised_position (SCM element_smob, SCM )
 /*
   Position next to support, taking into account my own dimensions and padding.
  */
 /*
   Position next to support, taking into account my own dimensions and padding.
  */
-MAKE_SCHEME_CALLBACK(Side_position,aligned_side,2);
+MAKE_SCHEME_CALLBACK (Side_position_interface,aligned_side,2);
 SCM
 SCM
-Side_position::aligned_side (SCM element_smob, SCM axis)
+Side_position_interface::aligned_side (SCM element_smob, SCM axis)
 {
   Grob *me = unsmob_grob (element_smob);
   Axis a = (Axis) gh_scm2int (axis);
   
 {
   Grob *me = unsmob_grob (element_smob);
   Axis a = (Axis) gh_scm2int (axis);
   
-  Direction d = Side_position::get_direction (me);
-  Real o = gh_scm2double (side_position (element_smob,axis));
+  Direction d = Side_position_interface::get_direction (me);
+  
+  Real o = gh_scm2double (aligned_on_support_extents (element_smob,axis));
 
   Interval iv =  me->extent (me, a);
 
   if (!iv.empty_b ())
     {
 
   Interval iv =  me->extent (me, a);
 
   if (!iv.empty_b ())
     {
+      if (!d)
+       {
+         programming_error ("Direction unknown, but aligned-side wanted.");
+         d = DOWN;
+       }
       o += - iv[-d];
 
       SCM pad = me->get_grob_property ("padding");
       o += - iv[-d];
 
       SCM pad = me->get_grob_property ("padding");
@@ -212,42 +261,42 @@ Side_position::aligned_side (SCM element_smob, SCM axis)
 /*
   Position centered on parent.
  */
 /*
   Position centered on parent.
  */
-MAKE_SCHEME_CALLBACK(Side_position,centered_on_parent,2);
+MAKE_SCHEME_CALLBACK (Side_position_interface,centered_on_parent,2);
 SCM
 SCM
-Side_position::centered_on_parent (SCM element_smob, SCM axis)
+Side_position_interface::centered_on_parent (SCM element_smob, SCM axis)
 {
   Grob *me = unsmob_grob (element_smob);
   Axis a = (Axis) gh_scm2int (axis);
 {
   Grob *me = unsmob_grob (element_smob);
   Axis a = (Axis) gh_scm2int (axis);
-  Grob *him = me->parent_l (a);
+  Grob *him = me->get_parent (a);
 
   return gh_double2scm (him->extent (him,a).center ());  
 }
 
 
 void
 
   return gh_double2scm (him->extent (him,a).center ());  
 }
 
 
 void
-Side_position::add_staff_support (Grob*me)
+Side_position_interface::add_staff_support (Grob*me)
 {
   Grob* st = Staff_symbol_referencer::staff_symbol_l (me);
 {
   Grob* st = Staff_symbol_referencer::staff_symbol_l (me);
-  if (st)
+  if (st && get_axis (me) == Y_AXIS)
     {
       add_support (me,st);
     }
 }
 
 void
     {
       add_support (me,st);
     }
 }
 
 void
-Side_position::set_axis (Grob*me, Axis a)
+Side_position_interface::set_axis (Grob*me, Axis a)
 {
 {
-  me->add_offset_callback (Side_position::aligned_side_proc, a);
+  me->add_offset_callback (Side_position_interface::aligned_side_proc, a);
 }
 
 
 
 // ugh. doesn't cactch all variants. 
 Axis
 }
 
 
 
 // ugh. doesn't cactch all variants. 
 Axis
-Side_position::get_axis (Grob*me)
+Side_position_interface::get_axis (Grob*me)
 {
 {
-  if (me->has_offset_callback_b (Side_position::aligned_side_proc, X_AXIS)
-      || me->has_offset_callback_b (Side_position::aligned_side_proc , X_AXIS))
+  if (me->has_offset_callback_b (Side_position_interface::aligned_side_proc, X_AXIS)
+      || me->has_offset_callback_b (Side_position_interface::aligned_side_proc , X_AXIS))
     return X_AXIS;
 
   
     return X_AXIS;
 
   
@@ -255,34 +304,41 @@ Side_position::get_axis (Grob*me)
 }
 
 void
 }
 
 void
-Side_position::set_direction (Grob*me, Direction d)
+Side_position_interface::set_direction (Grob*me, Direction d)
 {
   me->set_grob_property ("direction", gh_int2scm (d));
 }
 
 void
 {
   me->set_grob_property ("direction", gh_int2scm (d));
 }
 
 void
-Side_position::set_minimum_space (Grob*me, Real m)
+Side_position_interface::set_minimum_space (Grob*me, Real m)
 {
   me->set_grob_property ("minimum-space", gh_double2scm (m));
 }
 
 void
 {
   me->set_grob_property ("minimum-space", gh_double2scm (m));
 }
 
 void
-Side_position::set_padding (Grob*me, Real p)
+Side_position_interface::set_padding (Grob*me, Real p)
 {
   me->set_grob_property ("padding", gh_double2scm (p));
 }
 
 bool
 {
   me->set_grob_property ("padding", gh_double2scm (p));
 }
 
 bool
-Side_position::has_interface (Grob*me) 
+Side_position_interface::has_interface (Grob*me) 
 {
   return me->has_interface (ly_symbol2scm ("side-position-interface"));
 }
 
 bool
 {
   return me->has_interface (ly_symbol2scm ("side-position-interface"));
 }
 
 bool
-Side_position::supported_b (Grob*me) 
+Side_position_interface::supported_b (Grob*me) 
 {
 {
-  SCM s = me->get_grob_property  ("side-support-elements"); 
-  return gh_pair_p(s);
+  SCM s = me->get_grob_property ("side-support-elements"); 
+  return gh_pair_p (s);
 }
 
 
 }
 
 
+
+
+ADD_INTERFACE (Side_position_interface,"side-position-interface",
+  "Position a victim object (this one) next to other objects (the support).
+#'direction = where to put the victim object (left or right?)
+",
+  "side-support-elements direction-source direction side-relative-direction minimum-space padding self-alignment-X self-alignment-Y");