]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/tie.cc
release: 1.3.131
[lilypond.git] / lily / tie.cc
index d40b0c33694dfcbb9a23f4dc6429820759a113aa..6a762fc3e0be5f66142a99375fa2fb57e121701c 100644 (file)
@@ -3,10 +3,11 @@
 
   source file of the GNU LilyPond music typesetter
 
-  (c)  1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c)  1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
 */
 #include <math.h>
 
+
 #include "spanner.hh"
 #include "lookup.hh"
 #include "paper-def.hh"
 
 
 void
-Tie::set_head (Score_element*me,Direction d, Item * head_l)
+Tie::set_head (Grob*me,Direction d, Item * head_l)
 {
   assert (!head (me,d));
-  index_set_cell (me->get_elt_property ("heads"), d, head_l->self_scm ());
+  index_set_cell (me->get_grob_property ("heads"), d, head_l->self_scm ());
   
   dynamic_cast<Spanner*> (me)->set_bound (d, head_l);
   me->add_dependency (head_l);
 }
 
 void
-Tie::set_interface (Score_element*me)
+Tie::set_interface (Grob*me)
 {
-  me->set_elt_property ("heads", gh_cons (SCM_EOL, SCM_EOL));
+  me->set_grob_property ("heads", gh_cons (SCM_EOL, SCM_EOL));
   me->set_interface (ly_symbol2scm ("tie-interface"));
 }
 
 bool
-Tie::has_interface (Score_element*me)
+Tie::has_interface (Grob*me)
 {
   return me->has_interface (ly_symbol2scm ("tie-interface"));
 }
 
-Score_element*
-Tie::head (Score_element*me, Direction d) 
+Grob*
+Tie::head (Grob*me, Direction d) 
 {
-  SCM c = me->get_elt_property ("heads");
+  SCM c = me->get_grob_property ("heads");
   c = index_cell (c, d);
 
-  return unsmob_element (c);
+  return unsmob_grob (c);
 }
 
 Real
-Tie::position_f (Score_element*me) 
+Tie::position_f (Grob*me) 
 {
   Direction d = head (me,LEFT) ? LEFT:RIGHT;
   return Staff_symbol_referencer::position_f (head (me,d));
@@ -84,7 +85,7 @@ Tie::position_f (Score_element*me)
   further).
 */
 Direction
-Tie::get_default_dir (Score_element*me) 
+Tie::get_default_dir (Grob*me) 
 {
   Item * sl =  head(me,LEFT) ? Rhythmic_head::stem_l (head (me,LEFT)) :0;
   Item * sr =  head(me,RIGHT) ? Rhythmic_head::stem_l (head (me,RIGHT)) :0;  
@@ -109,7 +110,7 @@ Tie::get_default_dir (Score_element*me)
 SCM
 Tie::get_control_points (SCM smob)
 {  
-  Spanner*me = dynamic_cast<Spanner*> (unsmob_element (smob));
+  Spanner*me = dynamic_cast<Spanner*> (unsmob_grob (smob));
   Direction headdir = CENTER; 
   if (head (me,LEFT))
     headdir = LEFT;
@@ -127,56 +128,68 @@ Tie::get_control_points (SCM smob)
   
   Real staff_space = Staff_symbol_referencer::staff_space (me);
 
-  Real x_gap_f = me->paper_l ()->get_var ("tie_x_gap");
+  Real x_gap_f = gh_scm2double (me->get_grob_property ("x-gap"));
 
-  Score_element* commonx = me->common_refpoint (me->get_bound (LEFT), X_AXIS);
-  commonx = me->common_refpoint (me->get_bound (RIGHT), X_AXIS);
-  
-  Score_element* l = me->get_bound (LEFT);
-  Score_element* r = me->get_bound (RIGHT);  
+  Grob* l = me->get_bound (LEFT);
+  Grob* r = me->get_bound (RIGHT);  
 
+  Grob* commonx = me->common_refpoint (l, X_AXIS);
+  commonx = me->common_refpoint (r, X_AXIS);
+  
   Real left_x;
+
+  /*
+    this is a kludge: the tie has to be long enough to be
+    visible, but should not go through key sigs.
+
+    (please fixme)
+   */
+  Real lambda = 0.5;           
+  
   if (Note_head::has_interface (me->get_bound (LEFT)))
-    left_x = l->extent (X_AXIS)[RIGHT] + x_gap_f;
+    left_x = l->extent (l, X_AXIS)[RIGHT] + x_gap_f;
   else
-    left_x = l->extent (X_AXIS).length () / 2;
+    left_x = l->extent (l, X_AXIS).linear_combination (lambda);
+  
 
   Real width;
   if (Note_head::has_interface (me->get_bound (LEFT))
       && Note_head::has_interface (me->get_bound (RIGHT)))
     {
-      width = r->relative_coordinate (commonx, X_AXIS)
-       + r->extent (X_AXIS)[LEFT]
-       - l->relative_coordinate (commonx, X_AXIS)
-       - l->extent (X_AXIS)[RIGHT]
+      width = 
+       + r->extent (commonx,X_AXIS)[LEFT]
+       - l->extent (commonx, X_AXIS)[RIGHT]
        -2 * x_gap_f;
     }
   else
     {
       if (Note_head::has_interface (me->get_bound (LEFT)))
        width = r->relative_coordinate (commonx, X_AXIS)
-         - l->relative_coordinate (commonx, X_AXIS)
-         - l->extent (X_AXIS)[RIGHT]
+         - l->extent (commonx, X_AXIS)[RIGHT]
          - 2 * x_gap_f;
       else
-       width = r->relative_coordinate (commonx, X_AXIS)
-         - l->extent (X_AXIS).length () / 2
-         + r->extent (X_AXIS)[LEFT]
-         - l->relative_coordinate (commonx, X_AXIS)
+       width =
+         - l->extent (commonx, X_AXIS).linear_combination (lambda)  
+         + r->extent (commonx, X_AXIS)[LEFT]
          - 2 * x_gap_f;
     }
   
   Direction dir = Directional_element_interface::get(me);
-  
-  Real h_inf = me->paper_l ()->get_var ("tie_height_limit_factor") * staff_space;
-  Real r_0 = me->paper_l ()->get_var ("tie_ratio");
 
+  SCM details = me->get_grob_property ("details");
+
+  SCM lim // groetjes aan de chirurgendochter.
+    = scm_assq (ly_symbol2scm ("height-limit"),details);
+  
+  Real h_inf = gh_scm2double (gh_cdr (lim)) *  staff_space;
+  Real r_0 = gh_scm2double (gh_cdr (scm_assq (ly_symbol2scm ("ratio"),details)));
 
   Bezier b  = slur_shape (width, h_inf, r_0);
   
   Offset leave_dir = b.control_[1] - b.control_[0];
 
-  Real dx = (head (me, headdir)->extent (X_AXIS).length () + x_gap_f)/2.0;
+  Grob *hed =head (me, headdir);
+  Real dx = (hed->extent (hed, X_AXIS).length () + x_gap_f)/2.0;
   Real max_gap = leave_dir[Y_AXIS] * dx / leave_dir[X_AXIS];
 
   /*
@@ -209,9 +222,12 @@ Tie::get_control_points (SCM smob)
 
   /*
     Avoid colliding of the horizontal part with stafflines.
+
     
-    should do me for slurs as well.
+    TODO: redo this, heuristic is half-baken, and ties often look ugly
+    as a result.
 
+    TODO: doesn't work when on staff with even number of lines.
    */
   Array<Real> horizontal (b.solve_derivative (Offset (1,0)));
   if (horizontal.size ())
@@ -224,10 +240,26 @@ Tie::get_control_points (SCM smob)
       Real ry = rint (y/staff_space) * staff_space;
       Real diff = ry - y;
       Real newy = y;
-      if (fabs (y) <= Staff_symbol_referencer::staff_radius (me)
-         && fabs (diff) < me->paper_l ()->get_var ("tie_staffline_clearance"))
+
+      Real clear = staff_space * gh_scm2double (me->get_grob_property ("staffline-clearance"));
+
+       if (fabs (y) <= Staff_symbol_referencer::staff_radius (me)
+         && fabs (diff) < clear)
        {
-         newy = ry - 0.5 * staff_space * sign (diff) ;
+         Real y1 = ry + clear;
+         Real y2 = ry - clear;
+         
+         newy =  (fabs (y1 - y) < fabs (y2 - y)) ? y1 : y2;
+         
+         //      newy = ry - 0.5 * staff_space * sign (diff) ;
+
+         /*
+           we don't want horizontal ties
+          */
+         if (fabs (newy - b.control_[0][Y_AXIS]) < 1e-2)
+           {
+             newy = newy + dir * staff_space; 
+           }
        }
 
       Real y0 = b.control_ [0][Y_AXIS];
@@ -246,7 +278,7 @@ Tie::get_control_points (SCM smob)
   return controls;
 }
 
-MAKE_SCHEME_CALLBACK(Tie,set_spacing_rods);
+MAKE_SCHEME_CALLBACK(Tie,set_spacing_rods,1);
 
 /*
   TODO: set minimum distances for begin/end of line
@@ -254,7 +286,7 @@ MAKE_SCHEME_CALLBACK(Tie,set_spacing_rods);
 SCM
 Tie::set_spacing_rods (SCM smob)  
 {
-  Score_element*me = unsmob_element (smob);
+  Grob*me = unsmob_grob (smob);
   Spanner*sp = dynamic_cast<Spanner*> (me);
   Rod r;
 
@@ -262,27 +294,27 @@ Tie::set_spacing_rods (SCM smob)
   r.item_l_drul_ [RIGHT]=sp->get_bound (RIGHT);  
   
   r.distance_f_
-    = gh_scm2double (me->get_elt_property ("minimum-length"))
-    * me->paper_l ()->get_var ("staffspace");
+    = gh_scm2double (me->get_grob_property ("minimum-length"))
+    * 1.0;
   r.add_to_cols ();
   return SCM_UNSPECIFIED;
 }
 
-MAKE_SCHEME_CALLBACK(Tie,brew_molecule);
+MAKE_SCHEME_CALLBACK(Tie,brew_molecule,1);
 SCM
 Tie::brew_molecule (SCM smob) 
 {
-  Score_element*me = unsmob_element (smob);
+  Grob*me = unsmob_grob (smob);
 
-  SCM cp = me->get_elt_property ("control-points");
+  SCM cp = me->get_grob_property ("control-points");
   if (cp == SCM_EOL)
     {
       cp = get_control_points (smob);
-      me->set_elt_property ("control-points", cp);
+      me->set_grob_property ("control-points", cp);
     }
   
   Real thick =
-    gh_scm2double (me->get_elt_property ("thickness"))
+    gh_scm2double (me->get_grob_property ("thickness"))
     * me->paper_l ()->get_var ("stafflinethickness");
 
   Bezier b;
@@ -293,9 +325,9 @@ Tie::brew_molecule (SCM smob)
       i++;
     }
   
-   Molecule a = me->lookup_l ()->slur (b, Directional_element_interface::get (me) * thick, thick);
+   Molecule a = Lookup::slur (b, Directional_element_interface::get (me) * thick, thick);
    
-   return a.create_scheme ();
+   return a.smobbed_copy ();
 }