CVSROOT:        /cvsroot/lilypond
Module name:    lilypond
Branch:         
Changes by:     Han-Wen Nienhuys <[EMAIL PROTECTED]>    05/08/22 14:03:11

Modified files:
        .              : ChangeLog 
        Documentation/topdocs: NEWS.tely 
        flower/include : interval.hh interval.tcc 
        lily           : skyline.cc tie-column.cc tie.cc 
        lily/include   : skyline.hh tie-column.hh tie.hh 
        python         : convertrules.py 
        scm            : define-grob-properties.scm 
Added files:
        lily           : tie-helper.cc 

Log message:
        * flower/include/interval.hh (struct Interval_t):
        
        * lily/tie.cc (distance): new function
        (height): new function.
        (init): new function
        (Tie_details): new struct.
        
        * lily/skyline.cc (skyline_height): new function.
        
        * lily/tie-column.cc (set_chord_outlines): new function.
        (new_directions): read tie-configuration
        
        * lily/skyline.cc: fix ASCII art.

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/ChangeLog.diff?tr1=1.4057&tr2=1.4058&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/Documentation/topdocs/NEWS.tely.diff?tr1=1.74&tr2=1.75&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/flower/include/interval.hh.diff?tr1=1.51&tr2=1.52&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/flower/include/interval.tcc.diff?tr1=1.40&tr2=1.41&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/lily/tie-helper.cc?rev=1.1
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/lily/skyline.cc.diff?tr1=1.15&tr2=1.16&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/lily/tie-column.cc.diff?tr1=1.51&tr2=1.52&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/lily/tie.cc.diff?tr1=1.150&tr2=1.151&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/lily/include/skyline.hh.diff?tr1=1.7&tr2=1.8&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/lily/include/tie-column.hh.diff?tr1=1.23&tr2=1.24&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/lily/include/tie.hh.diff?tr1=1.55&tr2=1.56&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/python/convertrules.py.diff?tr1=1.12&tr2=1.13&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/lilypond/lilypond/scm/define-grob-properties.scm.diff?tr1=1.117&tr2=1.118&r1=text&r2=text

Patches:
Index: lilypond/ChangeLog
diff -u lilypond/ChangeLog:1.4057 lilypond/ChangeLog:1.4058
--- lilypond/ChangeLog:1.4057   Mon Aug 22 12:12:37 2005
+++ lilypond/ChangeLog  Mon Aug 22 14:03:10 2005
@@ -1,9 +1,25 @@
+2005-08-22  Han-Wen Nienhuys  <[EMAIL PROTECTED]>
+
+       * flower/include/interval.hh (struct Interval_t): 
+
+       * lily/tie.cc (distance): new function 
+       (height): new function.
+       (init): new function
+       (Tie_details): new struct.
+
+       * lily/skyline.cc (skyline_height): new function.
+
+       * lily/tie-column.cc (set_chord_outlines): new function.
+       (new_directions): read tie-configuration
+
+       * lily/skyline.cc: fix ASCII art.
+       
 2005-08-22  Mats Bengtsson  <[EMAIL PROTECTED]>
 
        * python/convertrules.py (string_or_scheme): Fix spelling error
 
 2005-08-22  Han-Wen Nienhuys  <[EMAIL PROTECTED]>
-
+       
        * lily/tie-column.cc (set_directions): set directions only once.
        (add_configuration): new function.
 
Index: lilypond/Documentation/topdocs/NEWS.tely
diff -u lilypond/Documentation/topdocs/NEWS.tely:1.74 
lilypond/Documentation/topdocs/NEWS.tely:1.75
--- lilypond/Documentation/topdocs/NEWS.tely:1.74       Sun Aug 21 21:47:15 2005
+++ lilypond/Documentation/topdocs/NEWS.tely    Mon Aug 22 14:03:11 2005
@@ -37,6 +37,23 @@
 
 @itemize @bullet
 @item
+Formatting of ties in chords has been improved. Ties no longer collide
+with note heads and stems. In addition, it is possible to manually
+specify tie formatting
+
[EMAIL PROTECTED], fragment,raggedright]
+  <a c d f> ~ <a c d f>
+  
+  \override TieColumn #'tie-configuration =
+  #'((0 . -1)  (2 . -1) (5.5 . 1) (7 . 1))
+  <b d f g> ~ <b d f g>
[EMAIL PROTECTED] lilypond
+
+This improvement has been sponsored by Bertalan Fodor, Jay Hamilton,
+Kieren MacMillan, Steve Doonan, by Trevor Baca, and 
+Vicente Solsona Dellá.
+
[EMAIL PROTECTED]
 Formatting of isolated, single ties has been improved. Now, ties avoid
 staff lines, flags and dots, without compromising their shape.
 
@@ -49,7 +66,8 @@
 @end lilypond
 
 This improvement has been sponsored by Bertalan Fodor, Jay Hamilton,
-Kieren MacMillan, Steve Doonan, by Trevor Baca, and Vincent SD.
+Kieren MacMillan, Steve Doonan, by Trevor Baca, and Vicente Solsona
+Dellá.
  
 
 @item
Index: lilypond/flower/include/interval.hh
diff -u lilypond/flower/include/interval.hh:1.51 
lilypond/flower/include/interval.hh:1.52
--- lilypond/flower/include/interval.hh:1.51    Fri Aug 12 00:04:47 2005
+++ lilypond/flower/include/interval.hh Mon Aug 22 14:03:11 2005
@@ -109,7 +109,7 @@
   }
   String to_string () const;
 
-  bool contains (T r);
+  bool contains (T r) const;
   void negate ()
   {
     T r = -elem (LEFT);
Index: lilypond/flower/include/interval.tcc
diff -u lilypond/flower/include/interval.tcc:1.40 
lilypond/flower/include/interval.tcc:1.41
--- lilypond/flower/include/interval.tcc:1.40   Sat Aug 13 21:35:23 2005
+++ lilypond/flower/include/interval.tcc        Mon Aug 22 14:03:11 2005
@@ -115,7 +115,7 @@
 
 template<class T>
 bool
-Interval_t<T>::contains (T r)
+Interval_t<T>::contains (T r) const
 {
   return r >= elem (LEFT) && r <= elem (RIGHT);
 }
Index: lilypond/lily/include/skyline.hh
diff -u lilypond/lily/include/skyline.hh:1.7 
lilypond/lily/include/skyline.hh:1.8
--- lilypond/lily/include/skyline.hh:1.7        Thu Mar 10 14:36:12 2005
+++ lilypond/lily/include/skyline.hh    Mon Aug 22 14:03:11 2005
@@ -33,5 +33,9 @@
 skyline_meshing_distance (Array<Skyline_entry> const &buildings,
                          Array<Skyline_entry> const &clouds);
 
+Real
+skyline_height (Array<Skyline_entry> const &buildings,
+               Real airplane, Direction sky_dir);
+
 #endif /* SKYLINE_HH */
 
Index: lilypond/lily/include/tie-column.hh
diff -u lilypond/lily/include/tie-column.hh:1.23 
lilypond/lily/include/tie-column.hh:1.24
--- lilypond/lily/include/tie-column.hh:1.23    Mon Aug 22 00:58:02 2005
+++ lilypond/lily/include/tie-column.hh Mon Aug 22 14:03:11 2005
@@ -20,7 +20,6 @@
   DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM));
   DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM));
   static void set_directions (Grob *me);
-  static void werner_directions (Grob *me);
   static void new_directions (Grob *me);
 };
 
Index: lilypond/lily/include/tie.hh
diff -u lilypond/lily/include/tie.hh:1.55 lilypond/lily/include/tie.hh:1.56
--- lilypond/lily/include/tie.hh:1.55   Mon Aug 22 00:58:02 2005
+++ lilypond/lily/include/tie.hh        Mon Aug 22 14:03:11 2005
@@ -11,20 +11,42 @@
 
 #include "lily-guile.hh"
 #include "lily-proto.hh"
+#include "skyline.hh"
 
 
+
+Interval
+get_skyline_attachment (Drul_array< Array < Skyline_entry > > const &skylines,
+                       Real y1);
+
+struct Tie_details
+{
+  Real height_limit_;
+  Real ratio_;
+  Real staff_space_;
+  
+  Tie_details ();
+  void init (Grob *);
+};
+  
 struct Tie_configuration
 {
-  int position_;
+  Real position_;
   Direction dir_;
   Interval attachment_x_;
   Real delta_y_;
   
   Tie_configuration ();
+  void center_tie_vertically (Tie_details const &);
+  Bezier get_bezier (Tie_details const &) const;
+  Real height (Tie_details const&) const;
   
   static int compare (Tie_configuration const &a,
                      Tie_configuration const &b);
+  static Real distance (Tie_configuration const &a,
+                      Tie_configuration const &b);
 };
+
 INSTANTIATE_COMPARE (Tie_configuration, Tie_configuration::compare);
 
 class Tie
@@ -35,15 +57,21 @@
   static void set_direction (Grob *);
   static Grob *head (Grob *, Direction);
   static int get_column_rank (Grob *, Direction);
-  static Real get_position (Grob *);
+  static int get_position (Grob *);
   static Direction get_default_dir (Grob *);
-  static void get_configuration (Grob *, Grob **, Tie_configuration *);
-  static void set_control_points (Grob *, Grob **,Tie_configuration const&);
+  static void get_configuration (Grob *, Grob *, Tie_configuration *,
+                                Drul_array< Array<Skyline_entry> > const *,
+                                Tie_details const & 
+                                );
+  static void set_control_points (Grob *, Grob *,Tie_configuration const&,
+                                 Tie_details const&
+                                 );
   static void set_default_control_points (Grob *);
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (set_spacing_rods, (SCM));
   static int compare (Grob *const &s1,
                      Grob *const &s2);
+
   
 };
 
Index: lilypond/lily/skyline.cc
diff -u lilypond/lily/skyline.cc:1.15 lilypond/lily/skyline.cc:1.16
--- lilypond/lily/skyline.cc:1.15       Fri Aug 12 00:04:45 2005
+++ lilypond/lily/skyline.cc    Mon Aug 22 14:03:11 2005
@@ -12,20 +12,18 @@
   A skyline is a shape of the form:
 
 
-  ----
-  |  |
-  ---------|  |
-  |          |
-  |          |
-  |          |______
-  --------|                 |___
-
-
+  *                  ----
+  *                  |  |
+  *         ---------|  |
+  *         |           |
+  *         |           |
+  *         |          |______
+  * --------|                |___
+  *
 
   This file deals with building such skyline structure, and computing
   the minimum distance between two opposing skylines.
 
-
   Invariants for a skyline:
 
   skyline[...].width_ forms a partition of the real interval, where
@@ -183,3 +181,22 @@
   for (int i = 0; i < buildings->size (); i++)
     buildings->elem_ref (i).height_ += ground;
 }
+
+Real
+skyline_height (Array<Skyline_entry> const &buildings,
+               Real airplane,
+               Direction sky_dir)
+{
+  Real h = - sky_dir * infinity_f;
+
+  /*
+    Ugh! linear, should be O(log n).
+   */
+  for (int i = 0; i < buildings.size (); i++)
+    if (buildings[i].width_.contains (airplane))
+      h = sky_dir * max (sky_dir * h,
+                        sky_dir * buildings[i].height_);
+  
+  return h;
+}
+
Index: lilypond/lily/tie-column.cc
diff -u lilypond/lily/tie-column.cc:1.51 lilypond/lily/tie-column.cc:1.52
--- lilypond/lily/tie-column.cc:1.51    Mon Aug 22 00:58:01 2005
+++ lilypond/lily/tie-column.cc Mon Aug 22 14:03:11 2005
@@ -6,10 +6,13 @@
   (c) 2000--2005 Han-Wen Nienhuys <[EMAIL PROTECTED]>
 */
 
-
 #include <math.h>
+
 #include <map>
+#include <set>
 
+#include "stem.hh"
+#include "skyline.hh"
 #include "staff-symbol-referencer.hh"
 #include "warn.hh"
 #include "tie-column.hh"
@@ -55,89 +58,6 @@
   return sign (Tie::get_position (s1) - Tie::get_position (s2));
 }
 
-/*
-  Werner:
-
-  . The algorithm to choose the direction of the ties doesn't work
-  properly.  I suggest the following for applying ties sequentially
-  from top to bottom:
-
-  + The topmost tie is always `up'.
-
-  + If there is a vertical gap to the last note above larger than
-  or equal to a fifth (or sixth?), the tie is `up', otherwise it
-  is `down'.
-
-  + The bottommost tie is always `down'.
-*/
-void
-Tie_column::werner_directions (Grob *me)
-{
-  extract_grob_set (me, "ties", ro_ties);
-  Link_array<Grob> ties (ro_ties);
-  if (!ties.size ())
-    return;
-
-  ties.sort (&Tie::compare);
-
-  Direction d = get_grob_direction (me);
-  if (d)
-    {
-      for (int i = ties.size (); i--;)
-       {
-         Grob *t = ties[i];
-         if (!get_grob_direction (t))
-           set_grob_direction (t, d);
-       }
-      return;
-    }
-
-  if (ties.size () == 1)
-    {
-      Grob *t = ties[0];
-      if (t->is_live ()
-         && !get_grob_direction (t))
-       set_grob_direction (t, Tie::get_default_dir (t));
-      return;
-    }
-
-  Real last_down_pos = 10000;
-  if (!get_grob_direction (ties[0]))
-    set_grob_direction (ties[0], DOWN);
-
-  /*
-    Go downward.
-  */
-  Grob *last_tie = 0;
-  for (int i = ties.size (); i--;)
-    {
-      Grob *t = ties[i];
-
-      Direction d = get_grob_direction (t);
-      Real p = Tie::get_position (t);
-      if (!d)
-       {
-         if (last_tie
-             && Tie::get_column_rank (t, LEFT)
-             < Tie::get_column_rank (last_tie, LEFT))
-           d = DOWN;
-         else if (last_down_pos - p > 5)
-           d = UP;
-         else
-           d = DOWN;
-
-         set_grob_direction (t, d);
-       }
-
-      if (d == DOWN)
-       last_down_pos = p;
-
-      last_tie = t;
-    }
-
-  return;
-}
-
 MAKE_SCHEME_CALLBACK (Tie_column, after_line_breaking, 1);
 SCM
 Tie_column::after_line_breaking (SCM smob)
@@ -169,68 +89,86 @@
   return SCM_UNSPECIFIED;
 }
 
-ADD_INTERFACE (Tie_column, "tie-column-interface",
-              "Object that sets directions of multiple ties in a tied chord",
-              "direction "
-              "positioning-done "
-              );
-
 
 
-
-bool
-config_allowed (map<Tie_configuration, bool> const &allowed,
-               Tie_configuration conf)
-{
-  return allowed.find (conf) == allowed.end ();
-}
-
 void
-add_configuration (map<Tie_configuration, bool> *allowed,
-                  Grob *tie_column,
-                  Tie_configuration new_conf)
+set_chord_outlines (Drul_array< Array<Skyline_entry> > *skyline_drul,
+                   Link_array<Grob> ties,
+                   Grob *common)
 {
-  bool on_line = Staff_symbol_referencer::on_staffline (tie_column, 
new_conf.position_);
-  
-  if (allowed->find (new_conf) != allowed->end ()
-      && !(*allowed)[new_conf])
-    {
-      programming_error ("Tie configuration not allowed");
-    }
-        
+  Direction d = LEFT;
 
-  if (on_line)
+  Real staff_space = Staff_symbol_referencer::staff_space (ties[0]);
+  do
     {
-      Tie_configuration forbidden;
+      Array<Box> boxes;
+      Interval x_union;
 
-      forbidden.dir_ = -new_conf.dir_ ;
-      forbidden.position_ = new_conf.position_;
-      (*allowed)[forbidden] = false;
+      Grob *stem = 0; 
+      for (int i = 0; i < ties.size (); i++)
+       {
+         Spanner *tie = dynamic_cast<Spanner*> (ties[i]);
 
-      forbidden.position_ += new_conf.dir_;
-      (*allowed)[forbidden] = false;
-      forbidden.position_ += new_conf.dir_;
-      (*allowed)[forbidden] = false;
+         Grob *head = Tie::head (tie, d);
+         if (!head)
+           continue;
+
+         if (!stem)
+           stem = unsmob_grob (head->get_object ("stem"));
+         
+         Real p = Tie::get_position (tie);
+         Interval y ((p-1) * 0.5 * staff_space,
+                     (p+1) * 0.5 * staff_space);
+
+         Interval x = head->extent (common, X_AXIS);
+         boxes.push (Box (x, y));
+         x_union.unite (x);
+       }
 
-      forbidden.dir_ = new_conf.dir_;
-      forbidden.position_ = new_conf.position_ + new_conf.dir_;
-      (*allowed)[forbidden] = false;
-    }
-  else
-    {
-      Tie_configuration forbidden;
-      forbidden.dir_ = - new_conf.dir_;
-      forbidden.position_ = new_conf.position_;
+      (*skyline_drul)[d] = empty_skyline (-d);
+      for (int i = 0; i < boxes.size (); i++)
+       insert_extent_into_skyline (&skyline_drul->elem_ref (d),
+                                   boxes[i], Y_AXIS, -d);
 
-      
-      (*allowed)[forbidden] = false;
-      forbidden.position_ -= new_conf.dir_;
-      forbidden.dir_ = new_conf.dir_;
-      (*allowed)[forbidden] = false;
+      Direction updowndir = DOWN;
+      do
+       {
+         Box b = boxes.boundary (updowndir, 0);
+         Interval x = b[X_AXIS];
+         x[-d] =  b[X_AXIS].linear_combination (-d / 2);
+         if (stem
+             && !Stem::is_invisible (stem)
+             && updowndir == get_grob_direction (stem))
+           x.unite (robust_relative_extent (stem, common, X_AXIS));
+
+         (*skyline_drul)[d].boundary (updowndir, 0).height_ = x[-d]; 
+       }
+      while (flip (&updowndir) != DOWN);
 
-      forbidden.position_ += 2* new_conf.dir_; 
-      (*allowed)[forbidden] = false;
+      for (int i = 0; i < ties.size (); i++)
+       {
+         Spanner *tie = dynamic_cast<Spanner*> (ties[i]);
+         Grob *head = Tie::head (tie, d);
+         if (!head)
+           continue;
+
+         Grob *dots = unsmob_grob (head->get_object ("dot"));
+         if (dots)
+           {
+             Interval x = dots->extent (common, X_AXIS);
+             Real p = Staff_symbol_referencer::get_position (dots);
+             
+             Interval y (-1,1);
+             y *= (staff_space /4);
+             y.translate ( p * staff_space * .5);
+
+             insert_extent_into_skyline (&skyline_drul->elem_ref (d),
+                                         Box (x,y), Y_AXIS, -d);
+           }
+       }
+      
     }
+  while (flip (&d) != LEFT);
 }
 
 
@@ -249,22 +187,37 @@
     }
   
   ties.sort (&Tie::compare);
+
   Array<Tie_configuration> tie_configs;
   for (int i = 0; i < ties.size (); i++)
     {
       Tie_configuration conf;
       conf.dir_ = get_grob_direction (ties[i]);
-      conf.position_ = (int) rint (Tie::get_position (ties[i]));
+      conf.position_ = Tie::get_position (ties[i]);
       tie_configs.push (conf);
     }
 
-    
+  SCM manual_configs = me->get_property ("tie-configuration");
+  bool manual_override = false;
+  int k = 0;
+  for (SCM s = manual_configs;
+       scm_is_pair (s) && k < tie_configs.size(); s = scm_cdr (s))
+    {
+      SCM entry = scm_car (s);
+      if (!scm_is_pair (entry))
+       continue;
+
+      manual_override = true;
+      tie_configs[k].position_ = robust_scm2double (scm_car (entry), 
tie_configs[k].position_);
+      tie_configs[k].dir_ = Direction (robust_scm2int (scm_cdr (entry), 
tie_configs[k].dir_));
+      k ++;
+    }
+
   if (!tie_configs[0].dir_)
     tie_configs[0].dir_ = DOWN;
   if (!tie_configs.top().dir_)
     tie_configs.top().dir_ = UP;
 
-
   /*
     Seconds
    */
@@ -287,66 +240,107 @@
       tie_configs[i].dir_ = (Direction) sign (tie_configs[i].position_);
     }
 
-  Grob *common[NO_AXES] = {
-    me, me
-  };
+  Grob *common = me;
   for (int i = 0; i < ties.size (); i++)
-    for (int a = X_AXIS; a < NO_AXES; a++)
-      {
-       Axis ax ((Axis) a);
-       
-       common[ax] = dynamic_cast<Spanner*> (ties[i])->get_bound 
(LEFT)->common_refpoint (common[a], ax); 
-       common[ax] = dynamic_cast<Spanner*> (ties[i])->get_bound 
(RIGHT)->common_refpoint (common[a], ax); 
-      }
-  
-  map<Tie_configuration, bool> allowed;
+    {
+      common = dynamic_cast<Spanner*> (ties[i])->get_bound 
(LEFT)->common_refpoint (common, X_AXIS); 
+      common = dynamic_cast<Spanner*> (ties[i])->get_bound 
(RIGHT)->common_refpoint (common, X_AXIS); 
+    }
 
-  Tie::get_configuration (ties[0], common, &tie_configs.elem_ref (0));
-  Tie::get_configuration (ties.top (), common,
-                         &tie_configs.elem_ref (tie_configs.size()-1));
+  Drul_array< Array<Skyline_entry> > skylines;
+  set_chord_outlines (&skylines, ties, common);
+  
+  Tie_details details;
+  details.init (ties[0]);
 
-  add_configuration (&allowed, me, tie_configs[0]);
-  add_configuration (&allowed, me, tie_configs.top());
+  /*
+    Let the ties flow out, according to our single-tie formatting.
+   */
+  if (!manual_override)
+    {
+      Tie::get_configuration (ties[0], common, &tie_configs.elem_ref (0),
+                             &skylines,
+                             details
+                             );
+      Tie::get_configuration (ties.top (), common,
+                             &tie_configs.elem_ref (tie_configs.size()-1),
+                             &skylines,
+                             details
+                             );
+    }
 
-  for (int i = 1; i < ties.size(); i++)
+  /*
+    Calculate final width and shape of the ties.
+   */
+  Real staff_space = Staff_symbol_referencer::staff_space (ties[0]);
+  Real gap = robust_scm2double (ties[0]->get_property ("x-gap"), 0.2);
+  for (int i = 0; i < ties.size(); i++)
     {
+      if (!manual_override
+         && (i == 0 || i == ties.size () -1))
+       continue;
+      
       Tie_configuration conf = tie_configs[i];
-      Tie::get_configuration (ties[i], common, &conf);
-      if (!config_allowed (allowed, conf))
-       {
-         conf = tie_configs[i];
+      conf = tie_configs[i];
+
+      Real line_dy = 0.0;
+      bool on_line = Staff_symbol_referencer::on_staffline (ties[0],
+                                                           int (rint 
(conf.position_)));
+      if (on_line)
+       line_dy = - sign (conf.height (details) - 0.6 * staff_space)
+         * 0.2 * staff_space * conf.dir_;
+
+      Real y = conf.position_ * staff_space * 0.5
+       + line_dy;
+      conf.attachment_x_
+       = get_skyline_attachment (skylines, y);
+      conf.attachment_x_.intersect (get_skyline_attachment (skylines,
+                                                           y + conf.dir_ * 
staff_space * .5));
+
+      conf.delta_y_ += line_dy;
+      conf.attachment_x_.widen (-gap);
+      if (!on_line
+         && Staff_symbol_referencer::staff_radius (ties[0]) * staff_space > y)
+       conf.center_tie_vertically (details);
+             
+      tie_configs[i] = conf;
+    }
 
-         Direction d = LEFT;
-         do
+  /*
+    Try to shift small ties into available spaces.
+   */
+  if (!manual_override)
+    {
+      set<int> positions_taken; 
+      for (int i = 0; i < tie_configs.size (); i++)
+       positions_taken.insert (int (rint (tie_configs[i].position_)));
+
+      for (int i = 0; i < tie_configs.size (); i++)
+       {
+         Tie_configuration * conf = &tie_configs.elem_ref (i);
+         if (Staff_symbol_referencer::on_staffline (ties[0], int (rint 
(conf->position_)))
+             && conf->height (details) < 0.4 * staff_space
+             && (positions_taken.find (int (rint (conf->position_ + 
conf->dir_)))
+                 == positions_taken.end ()))
            {
-             conf.attachment_x_[d] = d * 1e6; //  infty
-             for (int j = i - 1; j < i + 2; j++)
-               {
-                 if (j >= 0 && j < ties.size())
-                   {
-                     Spanner *t = dynamic_cast<Spanner*> (ties[j]);
-                     Interval ext
-                       = robust_relative_extent (t->get_bound (d),
-                                                 common[X_AXIS], X_AXIS);
-                     conf.attachment_x_[d]
-                       = d * min (d * conf.attachment_x_[d], d * ext[-d]);
-                   } 
-               }
+             positions_taken.insert (int (rint (conf->position_ + 
conf->dir_)));
+             conf->delta_y_ += 0.2 * staff_space * conf->dir_;
            }
-         while (flip (&d) != LEFT);
-         tie_configs[i] = conf;
        }
-      else
-       tie_configs[i] = conf;
-
-      add_configuration (&allowed, me, conf);
     }
-
+  
   for (int i = 0; i < ties.size(); i++)
     {
-      Tie::set_control_points (ties[i], common, tie_configs[i]);
+      Tie::set_control_points (ties[i], common, tie_configs[i],
+                              details
+                              );
       set_grob_direction (ties[i], tie_configs[i].dir_);
     }
 }
 
 
+ADD_INTERFACE (Tie_column, "tie-column-interface",
+              "Object that sets directions of multiple ties in a tied chord",
+              "positioning-done "
+              "tie-configuration "
+              );
Index: lilypond/lily/tie.cc
diff -u lilypond/lily/tie.cc:1.150 lilypond/lily/tie.cc:1.151
--- lilypond/lily/tie.cc:1.150  Mon Aug 22 00:58:01 2005
+++ lilypond/lily/tie.cc        Mon Aug 22 14:03:11 2005
@@ -65,11 +65,11 @@
   return Paper_column::get_rank (col);
 }
 
-Real
+int
 Tie::get_position (Grob *me)
 {
   Direction d = head (me, LEFT) ? LEFT : RIGHT;
-  return Staff_symbol_referencer::get_position (head (me, d));
+  return (int) Staff_symbol_referencer::get_position (head (me, d));
 }
 
 /*
@@ -114,10 +114,87 @@
     }
 }
 
+Interval
+get_default_attachments (Spanner *me, Grob *common, Real gap,
+                        int *staff_position,
+                        bool *in_between
+                        )
+{
+  Real staff_space = Staff_symbol_referencer::staff_space (me);
+  Direction dir = get_grob_direction (me);
+  Interval attachments;
+  Direction d = LEFT;
+  do
+    {
+      attachments[d]
+       = robust_relative_extent (me->get_bound (d),
+                                 common,
+                                 X_AXIS)[-d]
+       - gap * d;
+    }
+  while (flip (&d) != LEFT);
+
+  if (attachments.length () < 0.6 * staff_space)
+    {
+      /*
+       Let short ties start over note heads, instead of between.
+      */
+      Drul_array<bool> allow (true, true);
+
+      Direction d = LEFT;
+      do {
+       if (Note_head::has_interface (me->get_bound (d)))
+         {
+           Grob *stem = unsmob_grob (me->get_bound (d)->get_object ("stem"));
+           if (get_grob_direction (stem) == dir
+               && -d == dir)
+             allow[d] = false;
+         }
+      } while (flip (&d) != LEFT);
+
+      if (allow[LEFT] && allow[RIGHT])
+       {
+         *staff_position += dir;
+         do
+           {
+             if (Note_head::has_interface (me->get_bound (d)))
+               {
+                 Interval extent
+                   = robust_relative_extent (me->get_bound (d),
+                                             common, X_AXIS);
+
+                 attachments[d] = extent.linear_combination (- 0.5 * d);
+                 *in_between = false;
+               }
+           }
+         while (flip (&d) != LEFT);
+       }
+    }
 
+  return attachments;
+}  
+
+Interval
+get_skyline_attachment (Drul_array< Array < Skyline_entry > > const &skylines,
+                       Real y)
+{
+  Interval attachments;
+  Direction d = LEFT;
+  do
+    {
+      attachments[d] = skyline_height (skylines[d], y, -d);
+    }
+  while (flip (&d) != LEFT);
+  
+  return attachments;
+}
+                       
 void
-Tie::get_configuration (Grob *me_grob, Grob **common,
-                       Tie_configuration *conf)
+Tie::get_configuration (Grob *me_grob, Grob *common,
+                       Tie_configuration *conf,
+                       Drul_array< Array < Skyline_entry > > const *skylines,
+                       Tie_details const &details
+                       )
 {
   Spanner *me = dynamic_cast<Spanner*> (me_grob);
   if (!head (me, LEFT) && !head (me, RIGHT))
@@ -130,7 +207,7 @@
   Direction dir = CENTER;
   
   int tie_position = (int) Tie::get_position (me);
-  int staff_position = conf->position_;
+  int staff_position = (int) conf->position_;
 
   if (conf->dir_)
     {
@@ -143,72 +220,28 @@
        dir = get_default_dir (me);
     }
 
-  Real staff_space = Staff_symbol_referencer::staff_space (me);
+  Real staff_space = details.staff_space_;
 
   bool in_between = true;
   Interval attachments = conf->attachment_x_;
+  Real gap = robust_scm2double (me->get_property ("x-gap"), 0.2);
   if (attachments.is_empty())
     {
-      Direction d = LEFT;
-      Real gap = robust_scm2double (me->get_property ("x-gap"), 0.2);
-      do
+      if (!skylines)
+       attachments = get_default_attachments (me, common, gap,
+                                              &staff_position,
+                                              &in_between);
+      else
        {
-         attachments[d]
-           = robust_relative_extent (me->get_bound (d),
-                                     common[X_AXIS],
-                                     X_AXIS)[-d]
-           - gap * d;
-       }
-      while (flip (&d) != LEFT);
-  
-      if (attachments.length () < 0.6 * staff_space)
-       {
-         /*
-           Let short ties start over note heads, instead of between.
-         */
-         Drul_array<bool> allow (true, true);
-
-         Direction d = LEFT;
-         do {
-           if (Note_head::has_interface (me->get_bound (d)))
-             {
-               Grob *stem = unsmob_grob (me->get_bound (d)->get_object 
("stem"));
-               if (get_grob_direction (stem) == dir
-                   && -d == dir)
-                 allow[d] = false;
-             }
-         } while (flip (&d) != LEFT);
-
-         if (allow[LEFT] && allow[RIGHT])
-           {
-             staff_position += dir;
-             do
-               {
-                 if (Note_head::has_interface (me->get_bound (d)))
-                   {
-                     Interval extent
-                       = robust_relative_extent (me->get_bound (d),
-                                                 common[X_AXIS], X_AXIS);
-
-                     attachments[d] = extent.linear_combination (- 0.5 * d);
-                     in_between = false;
-                   }
-               }
-             while (flip (&d) != LEFT);
-           }
+         Real y = staff_space * 0.5 * staff_position;
+         attachments = get_skyline_attachment (*skylines, y);
+         attachments.widen (-gap);
        }
     }
-  SCM details = me->get_property ("details");
-
-  SCM limit
-    = scm_assq (ly_symbol2scm ("height-limit"), details);
-
-  Real h_inf = robust_scm2double (scm_cdr (limit), 0.75) * staff_space;
-  Real r_0 = robust_scm2double (scm_cdr (scm_assq (ly_symbol2scm ("ratio"), 
details)),
-                               .333);
 
   Bezier b = slur_shape (attachments.length(),
-                        h_inf, r_0);
+                        details.height_limit_,
+                        details.ratio_);
   b.scale (1, dir);
   
   Offset middle = b.curve_point (0.5);
@@ -282,17 +315,13 @@
   
   if (in_space)
     {
-      if (fabs (dy) < 0.4 * staff_space)
+      if (fabs (dy) < 0.45 * staff_space)
        {
          /*
            vertically center in space.
          */
-         Offset middle = b.curve_point (0.5);
-         Offset edge = b.curve_point (0.0);
-
-         Real center = (edge[Y_AXIS] + middle[Y_AXIS])/2.0;
-
-         conf->delta_y_ = - center;
+         conf->attachment_x_ = attachments;
+         conf->center_tie_vertically(details);
        }
       else
        {
@@ -314,6 +343,13 @@
 
   conf->dir_ = dir;
   conf->position_ = staff_position;
+
+  if (skylines)
+    {
+      Real y = staff_space * 0.5 * staff_position;
+      attachments = get_skyline_attachment (*skylines, y);
+      attachments.widen (-gap);
+    }
   conf->attachment_x_ = attachments;
 }
 
@@ -322,15 +358,9 @@
 Tie::set_default_control_points (Grob *me_grob)
 {
   Spanner *me = dynamic_cast<Spanner*> (me_grob);
-  Grob *common[NO_AXES] = {
-    0, 0
-  };
-  for (int a = X_AXIS; a < NO_AXES; a++)
-    {
-      Axis ax ((Axis) a); 
-      common[ax] = me->get_bound (LEFT)->common_refpoint (me, ax); 
-      common[ax] = me->get_bound (RIGHT)->common_refpoint (common[a], ax); 
-    }
+  Grob *common  = me;
+  common = me->get_bound (LEFT)->common_refpoint (common, X_AXIS); 
+  common = me->get_bound (RIGHT)->common_refpoint (common, X_AXIS); 
   
   Tie_configuration conf;
   if (!get_grob_direction (me))
@@ -338,33 +368,25 @@
 
   int tie_position = (int) Tie::get_position (me);
   conf.position_ = tie_position;
-
   
-  get_configuration (me, common, &conf);
-  set_control_points (me, common, conf);
+  Tie_details details;
+  details.init (me);
+  get_configuration (me, common, &conf, 0, details);
+  set_control_points (me, common, conf, details);
 }
 
 void
 Tie::set_control_points (Grob *me,
-                        Grob **common,
-                        Tie_configuration const &conf)
+                        Grob *common,
+                        Tie_configuration const &conf,
+                        Tie_details const &details
+                        )
 {
-  SCM details = me->get_property ("details");
-  SCM limit
-    = scm_assq (ly_symbol2scm ("height-limit"), details);
-
-  Real staff_space = Staff_symbol_referencer::staff_space (me);
-  Real h_inf = robust_scm2double (scm_cdr (limit), 0.75) * staff_space;
-  Real r_0 = robust_scm2double (scm_cdr (scm_assq (ly_symbol2scm ("ratio"),
-                                                  details)),
-                               .333);
-
-  Bezier b = slur_shape (conf.attachment_x_.length(),
-                        h_inf, r_0);
+  Bezier b = conf.get_bezier (details);
   b.scale (1, conf.dir_);
   b.translate (Offset (conf.attachment_x_[LEFT]
-                      - me->relative_coordinate (common[X_AXIS], X_AXIS),
-                      0.5 * conf.position_ * staff_space 
+                      - me->relative_coordinate (common, X_AXIS),
+                      0.5 * conf.position_ * details.staff_space_
                       + conf.delta_y_
                       ));
   
@@ -437,20 +459,3 @@
               "direction "
               "thickness "
               "x-gap ");
-
-int
-Tie_configuration::compare (Tie_configuration const &a,
-                           Tie_configuration const &b)
-{
-  if (a.position_ - b.position_)
-    return sign (a.position_ - b.position_);
-  return sign (a.dir_ - b.dir_);
-}
-                           
-
-Tie_configuration::Tie_configuration ()
-{
-  dir_ = CENTER;
-  position_ = 0;
-  delta_y_ = 0.0;
-}
Index: lilypond/python/convertrules.py
diff -u lilypond/python/convertrules.py:1.12 
lilypond/python/convertrules.py:1.13
--- lilypond/python/convertrules.py:1.12        Mon Aug 22 12:12:37 2005
+++ lilypond/python/convertrules.py     Mon Aug 22 14:03:11 2005
@@ -2543,13 +2543,6 @@
 def conv (str):
        str = re.sub('Performer_group_performer', 'Performer_group', str)
        str = re.sub('Engraver_group_engraver', 'Engraver_group', str)
-       return str
-
-conversions.append (((2, 7, 6), conv,
-                    '''Performer_group_performer -> Performer_group, 
Engraver_group_engraver -> Engraver_group'''))
-
-
-def conv (str):
        str = re.sub (r"#'inside-slur\s*=\s*##t *",
                      r"#'avoid-slur = #'inside ", str)
        str = re.sub (r"#'inside-slur\s*=\s*##f *",
@@ -2558,6 +2551,7 @@
                      r"#'avoid-slur", str)
        return str
 
-conversions.append (((2, 7, 7), conv,
-                    """inside-slur -> avoid-slur"""))
+conversions.append (((2, 7, 6), conv,
+                    '''Performer_group_performer -> Performer_group, 
Engraver_group_engraver -> Engraver_group
+inside-slur -> avoid-slur'''))
 
Index: lilypond/scm/define-grob-properties.scm
diff -u lilypond/scm/define-grob-properties.scm:1.117 
lilypond/scm/define-grob-properties.scm:1.118
--- lilypond/scm/define-grob-properties.scm:1.117       Mon Aug 22 00:58:02 2005
+++ lilypond/scm/define-grob-properties.scm     Mon Aug 22 14:03:11 2005
@@ -469,6 +469,8 @@
 
      (threshold ,number-pair? "(@var{min} . @var{max}), where
 @var{min} and @var{max} are dimensions in staff space.")
+     (tie-configuration ,list? "List of (@var{position} . @var{dir})
+pairs, indicating the desired tie configuration.")
      (transparent ,boolean? "This is almost the same as setting
 @code{print-function} to @code{#f}, but this retains the dimensions of
 this grob, which means that grobs can be erased individually.")


_______________________________________________
Lilypond-cvs mailing list
Lilypond-cvs@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-cvs

Reply via email to