]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/side-position-interface.cc
* Documentation/user/music-glossary.itely: add Finnish author.
[lilypond.git] / lily / side-position-interface.cc
index 701e415feef054c06d0f821cde6341706f90860d..a974a4495844c270bd6a41c0437ff1216ff1f781 100644 (file)
@@ -3,53 +3,52 @@
   
   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--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
   
  */
 #include <math.h>              // ceil.
 
 #include "side-position-interface.hh"
   
  */
 #include <math.h>              // ceil.
 
 #include "side-position-interface.hh"
-#include "debug.hh"
+#include "warn.hh"
 #include "warn.hh"
 #include "dimensions.hh"
 #include "staff-symbol-referencer.hh"
 #include "group-interface.hh"
 #include "directional-element-interface.hh"
 #include "warn.hh"
 #include "dimensions.hh"
 #include "staff-symbol-referencer.hh"
 #include "group-interface.hh"
 #include "directional-element-interface.hh"
+#include "staff-symbol-referencer.hh"
 
 void
 Side_position_interface::add_support (Grob*me, Grob*e)
 {
 
 void
 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
 Side_position_interface::get_direction (Grob*me)
 {
   SCM d = me->get_grob_property ("direction");
 Direction
 Side_position_interface::get_direction (Grob*me)
 {
   SCM d = me->get_grob_property ("direction");
-  if (isdir_b (d) && to_dir (d))
+  if (is_direction (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 (is_direction (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 * Directional_element_interface::get (e));
+      return (Direction) (relative_dir * get_grob_direction (e));
     }
   
   return CENTER;
 }
   
 
     }
   
   return CENTER;
 }
   
 
-MAKE_SCHEME_CALLBACK(Side_position_interface,aligned_on_support_extents, 2);
+MAKE_SCHEME_CALLBACK (Side_position_interface,aligned_on_support_extents, 2);
 SCM
 Side_position_interface::aligned_on_support_extents (SCM element_smob, SCM axis)
 {
 SCM
 Side_position_interface::aligned_on_support_extents (SCM element_smob, SCM axis)
 {
@@ -67,19 +66,24 @@ Side_position_interface::aligned_on_support_extents (SCM element_smob, SCM axis)
 SCM
 Side_position_interface::general_side_position (Grob * me, Axis a, bool use_extents)
 {
 SCM
 Side_position_interface::general_side_position (Grob * me, Axis a, bool use_extents)
 {
-  Grob *common = me->parent_l (a);
+  Real ss = Staff_symbol_referencer::staff_space (me);
   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))
+  Grob *common = common_refpoint_of_list (support, me->get_parent (a), a);
+  Grob * st = Staff_symbol_referencer::get_staff_symbol (me);
+  bool include_staff = (st
+                       && a == Y_AXIS
+                       && gh_number_p (me->get_grob_property ("staff-padding")));
+
+  Interval dim;
+  if (include_staff)
     {
     {
-      Grob * e  = unsmob_grob (gh_car (s));
-      if (e)
-       common = common->common_refpoint (e, a);
+      common = st->common_refpoint (common, Y_AXIS);
+      dim = st->extent (common, Y_AXIS);
     }
     }
-  
-  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 (use_extents)
          dim.unite (e->extent (common, a));
       if (e)
        if (use_extents)
          dim.unite (e->extent (common, a));
@@ -90,85 +94,49 @@ Side_position_interface::general_side_position (Grob * me, Axis a, bool use_exte
          }
     }
 
          }
     }
 
-  if (dim.empty_b ())
+  if (dim.is_empty ())
     {
     {
-      dim = Interval(0,0);
+      dim = Interval (0,0);
     }
 
   Direction dir = Side_position_interface::get_direction (me);
     
     }
 
   Direction dir = Side_position_interface::get_direction (me);
     
-  Real off =  me->parent_l (a)->relative_coordinate (common, a);
-  SCM minimum = me->remove_grob_property ("minimum-space");
+  Real off =  me->get_parent (a)->relative_coordinate (common, a);
+  Real  minimum_space = ss * robust_scm2double (me->get_grob_property ("minimum-space"),  -1);
 
 
-  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;
-    }
+  Real total_off = dim.linear_combination (dir) - off;
+  total_off += dir * ss * robust_scm2double (me->get_grob_property ("padding"), 0);
 
 
-  if (gh_number_p (minimum) 
+  if (minimum_space >= 0
       && dir
       && dir
-      && total_off * dir < gh_scm2double (minimum))
+      && total_off * dir < minimum_space)
     {
     {
-      total_off = gh_scm2double (minimum) * dir;
+      total_off = minimum_space * dir;
     }
 
   if (fabs (total_off) > 100 CM)
     programming_error ("Huh ? Improbable staff side dim.");
 
     }
 
   if (fabs (total_off) > 100 CM)
     programming_error ("Huh ? Improbable staff side dim.");
 
+
+  
+  
   return gh_double2scm (total_off);
 }
 
 /*
   Cut & paste (ugh.)
  */
   return gh_double2scm (total_off);
 }
 
 /*
   Cut & paste (ugh.)
  */
-MAKE_SCHEME_CALLBACK(Side_position_interface,aligned_on_support_refpoints,2);
+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);
 
 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); 
+  return general_side_position (me, a, false); 
 }
 
 
 }
 
 
-/**
-  callback that centers the element on itself
- */
-MAKE_SCHEME_CALLBACK(Side_position_interface,aligned_on_self,2);
-SCM
-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-");
-
-  s +=  (a == X_AXIS) ? "X" : "Y";
-
-  SCM align (me->get_grob_property (s.ch_C()));
-  if (gh_number_p (align))
-    {
-      Interval ext(me->extent (me,a));
-
-      if (ext.empty_b ())
-       {
-         programming_error ("I'm empty. Can't align on self");
-         return gh_double2scm (0.0);
-       }
-      else
-       {
-         return gh_double2scm (- ext.linear_combination (gh_scm2double (align)));
-       }
-    }
-  else if (unsmob_grob (align))
-    {
-      return gh_double2scm (- unsmob_grob (align)->relative_coordinate (me,  a));
-    }
-    return gh_double2scm (0.0);
-}
-
 
 
 Real
 
 
 Real
@@ -185,22 +153,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_interface,quantised_position,2);
+  Staff_symbol_referencer::staff_radius () */
+MAKE_SCHEME_CALLBACK (Side_position_interface,quantised_position,2);
 SCM
 SCM
-Side_position_interface::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_interface::get_direction (me);
 
   Direction d = Side_position_interface::get_direction (me);
 
-  if (Staff_symbol_referencer::has_interface (me))
+  Grob * stsym = Staff_symbol_referencer::get_staff_symbol (me);
+  if (stsym)
     {
     {
-      Real p = Staff_symbol_referencer::position_f (me);
+      Real p = Staff_symbol_referencer::get_position (me);
       Real rp = directed_round (p, d);
       Real rad = Staff_symbol_referencer::staff_radius (me) *2 ;
       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))
        {
@@ -216,7 +184,7 @@ Side_position_interface::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_interface,aligned_side,2);
+MAKE_SCHEME_CALLBACK (Side_position_interface,aligned_side,2);
 SCM
 Side_position_interface::aligned_side (SCM element_smob, SCM axis)
 {
 SCM
 Side_position_interface::aligned_side (SCM element_smob, SCM axis)
 {
@@ -224,46 +192,46 @@ Side_position_interface::aligned_side (SCM element_smob, SCM axis)
   Axis a = (Axis) gh_scm2int (axis);
   
   Direction d = Side_position_interface::get_direction (me);
   Axis a = (Axis) gh_scm2int (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);
 
   Real o = gh_scm2double (aligned_on_support_extents (element_smob,axis));
 
   Interval iv =  me->extent (me, a);
 
-  if (!iv.empty_b ())
+  if (!iv.is_empty ())
     {
     {
+      if (!d)
+       {
+         programming_error ("Direction unknown, but aligned-side wanted.");
+         d = DOWN;
+       }
       o += - iv[-d];
       o += - iv[-d];
-
-      SCM pad = me->get_grob_property ("padding");
-      if (gh_number_p (pad))
-       o += d *gh_scm2double (pad) ; 
     }
     }
-  return gh_double2scm (o);
-}
 
 
-/*
-  Position centered on parent.
+  /*
+  Maintain a minimum distance to the staff. This is similar to side
+  position with padding, but it will put adjoining objects on a row if
+  stuff sticks out of the staff a little.
  */
  */
-MAKE_SCHEME_CALLBACK(Side_position_interface,centered_on_parent,2);
-SCM
-Side_position_interface::centered_on_parent (SCM element_smob, SCM axis)
-{
-  Grob *me = unsmob_grob (element_smob);
-  Axis a = (Axis) gh_scm2int (axis);
-  Grob *him = me->parent_l (a);
-
-  return gh_double2scm (him->extent (him,a).center ());  
-}
-
-
-void
-Side_position_interface::add_staff_support (Grob*me)
-{
-  Grob* st = Staff_symbol_referencer::staff_symbol_l (me);
-  if (st)
+  Grob * st = Staff_symbol_referencer::get_staff_symbol (me);
+  if (st && a == Y_AXIS
+      && gh_number_p (me->get_grob_property ("staff-padding")))
     {
     {
-      add_support (me,st);
+      Real padding=
+      Staff_symbol_referencer::staff_space (me)
+      * gh_scm2double (me->get_grob_property ("staff-padding"));
+  
+      Grob *common = me->common_refpoint (st, Y_AXIS);
+      
+      Interval staff_size = st->extent (common, Y_AXIS);
+      Interval me_ext = me->extent (common, a);
+      Real diff =  d*staff_size[d] + padding - d*(o + iv[-d]);
+      o += (d*  (diff >? 0));
     }
     }
+      
+  return gh_double2scm (o);
 }
 
 }
 
+
 void
 Side_position_interface::set_axis (Grob*me, Axis a)
 {
 void
 Side_position_interface::set_axis (Grob*me, Axis a)
 {
@@ -272,7 +240,7 @@ Side_position_interface::set_axis (Grob*me, Axis a)
 
 
 
 
 
 
-// ugh. doesn't cactch all variants. 
+// ugh. doesn't catch all variants. 
 Axis
 Side_position_interface::get_axis (Grob*me)
 {
 Axis
 Side_position_interface::get_axis (Grob*me)
 {
@@ -284,35 +252,15 @@ Side_position_interface::get_axis (Grob*me)
   return Y_AXIS;
 }
 
   return Y_AXIS;
 }
 
-void
-Side_position_interface::set_direction (Grob*me, Direction d)
-{
-  me->set_grob_property ("direction", gh_int2scm (d));
-}
 
 
-void
-Side_position_interface::set_minimum_space (Grob*me, Real m)
-{
-  me->set_grob_property ("minimum-space", gh_double2scm (m));
-}
-
-void
-Side_position_interface::set_padding (Grob*me, Real p)
-{
-  me->set_grob_property ("padding", gh_double2scm (p));
-}
-
-bool
-Side_position_interface::has_interface (Grob*me) 
-{
-  return me->has_interface (ly_symbol2scm ("side-position-interface"));
-}
-
-bool
-Side_position_interface::supported_b (Grob*me) 
-{
-  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).  In this case, the property @code{direction} signifies where to put the  "
+              "victim object relative to the support (left or right, up or down?)\n\n "
+              "The routine also takes the size the staff into account if "
+              "@code{staff-padding} is set. If undefined, the staff symbol is ignored." 
+              ,
+              "staff-padding side-support-elements direction-source "
+              "direction side-relative-direction minimum-space padding");