From 01c20258b4692606d21dc84d20896869becffc0e Mon Sep 17 00:00:00 2001
From: hanwen <hanwen>
Date: Sun, 18 Jul 2004 20:26:33 +0000
Subject: [PATCH] new file.

---
 .../W.A.Mozart/mozart-hrn3-allegro.ily        |   2 +-
 lily/include/slur.hh                          |   2 +-
 lily/new-slur.cc                              | 944 +-----------------
 lily/phrasing-slur-engraver.cc                |   8 +-
 lily/slur-engraver.cc                         |  19 +-
 lily/slur-quanting.cc                         | 910 +++++++++++++++++
 lily/slur.cc                                  |  42 +-
 scm/define-grobs.scm                          |  38 +-
 8 files changed, 996 insertions(+), 969 deletions(-)
 create mode 100644 lily/slur-quanting.cc

diff --git a/input/mutopia/W.A.Mozart/mozart-hrn3-allegro.ily b/input/mutopia/W.A.Mozart/mozart-hrn3-allegro.ily
index b51ac1f0bb..16318c38a6 100644
--- a/input/mutopia/W.A.Mozart/mozart-hrn3-allegro.ily
+++ b/input/mutopia/W.A.Mozart/mozart-hrn3-allegro.ily
@@ -157,7 +157,7 @@ allegro =
   \revert Stem #'stroke-style }
   e8[)( d16  c)]
 
-	<< d1\trill (
+	<< d1\trill _(
 	  { s2 \grace {
   \override Stem   #'stroke-style = #"grace"
     c16[ d] 
diff --git a/lily/include/slur.hh b/lily/include/slur.hh
index 166c9f1631..4dc2450310 100644
--- a/lily/include/slur.hh
+++ b/lily/include/slur.hh
@@ -11,7 +11,7 @@
 #include "lily-proto.hh"
 #include "rod.hh"
 
-class Slur
+class Old_slur
 {
 public:
   static void add_column (Grob *me, Grob *col);
diff --git a/lily/new-slur.cc b/lily/new-slur.cc
index 6b9b8611e8..3ee7f8aec1 100644
--- a/lily/new-slur.cc
+++ b/lily/new-slur.cc
@@ -10,6 +10,7 @@
 
 #include <math.h>
 
+#include "new-slur.hh"
 #include "main.hh"
 #include "font-interface.hh"
 #include "text-item.hh"
@@ -30,906 +31,6 @@
 #include "warn.hh"
 #include "beam.hh"
 
-/*
-  TODO:
-
-  - curve around flag for y coordinate
-  - better scoring.
-  - short-cut: try a smaller region first.
-  - collisions with accidentals
-  - collisions with scripts (staccato!)
-  - 
-*/
-struct Encompass_info
-{
-  Real x_;
-  Real stem_;
-  Real head_;
-  Encompass_info ()
-  {
-    x_ = 0.0;
-    stem_ = 0.0;
-    head_ = 0.0;
-  }
-};
-
-struct Bound_info
-{
-  Box stem_extent_;
-  Direction stem_dir_;
-  Grob *bound_;
-  Grob *note_column_;
-  Grob *slur_head_;
-  Grob *staff_;
-  Grob *stem_;
-  Interval slur_head_extent_;
-  Real neighbor_y_;
-  Real staff_space_;
-  
-  Bound_info ()
-  {
-    stem_ = 0;
-    neighbor_y_ = 0;
-    staff_ = 0;
-    slur_head_ = 0;
-    stem_dir_ = CENTER;
-    note_column_ = 0;
-  }
-};
-
-/*
-  TODO: put in details property.
-*/
-struct Slur_score_parameters
-{
-  int SLUR_REGION_SIZE;
-  Real HEAD_ENCOMPASS_PENALTY;
-  Real STEM_ENCOMPASS_PENALTY;
-  Real CLOSENESS_FACTOR;
-  Real EDGE_ATTRACTION_FACTOR;
-  Real SAME_SLOPE_PENALTY;
-  Real STEEPER_SLOPE_FACTOR;
-  Real NON_HORIZONTAL_PENALTY;
-  Real HEAD_STRICT_FREE_SPACE;
-  Real MAX_SLOPE;
-  Real MAX_SLOPE_FACTOR;
-  Real FREE_HEAD_DISTANCE;
-  Slur_score_parameters ();
-};
-
-void
-init_score_param (Slur_score_parameters *score_param)
-{
-  score_param->SLUR_REGION_SIZE = 5;
-  score_param->HEAD_ENCOMPASS_PENALTY = 1000.0;
-  score_param->STEM_ENCOMPASS_PENALTY = 30.0;
-  score_param->CLOSENESS_FACTOR = 10;
-  score_param->EDGE_ATTRACTION_FACTOR = 4;
-  score_param->SAME_SLOPE_PENALTY = 20;
-  score_param->STEEPER_SLOPE_FACTOR = 50;
-  score_param->NON_HORIZONTAL_PENALTY = 15;
-  score_param->HEAD_STRICT_FREE_SPACE = 0.2;
-  score_param->MAX_SLOPE = 1.1;
-  score_param->MAX_SLOPE_FACTOR = 10;
-  score_param->FREE_HEAD_DISTANCE = 0.3;
-}
-
-Slur_score_parameters::Slur_score_parameters()
-{
-  init_score_param (this);
-}
-
-#define DEBUG_SLUR_QUANTING 1
-
-struct Slur_score
-{
-  Drul_array<Offset> attachment_;
-  Real score_;
-  Bezier curve_;
-
-#if DEBUG_SLUR_QUANTING
-  String score_card_;
-#endif
-
-  Slur_score()
-  {
-    score_ = 0.0;
-  }
-};
-
-class New_slur
-{
-public:
-  static void add_column (Grob *me, Grob *col);
-  DECLARE_SCHEME_CALLBACK (print, (SCM));
-  static void score_slopes (Grob *me, Grob *common[],
-			    Slur_score_parameters *score_param,
-			    Drul_array<Bound_info>,
-			    Drul_array<Offset> base_attach,
-			    Array<Slur_score> *scores);
-
-  static void score_edges (Grob *me, Grob *common[],
-			   Slur_score_parameters *score_param,
-			   Drul_array<Bound_info> extremes,
-			   Drul_array<Offset> base_attach,
-			   Array<Slur_score> *scores);
-  static void score_encompass (Grob *me, Grob *common[],
-			       Slur_score_parameters*,
-			       Drul_array<Bound_info>,
-			       Drul_array<Offset>, Array<Slur_score> *scores);
-  static Bezier avoid_staff_line (Grob *me, Grob **common,
-				  Drul_array<Bound_info> extremes,
-				  Bezier bez);
-
-  static Encompass_info get_encompass_info (Grob *me,
-					    Grob *col,
-					    Grob **common);
-  static void set_interface (Grob *);
-  static bool  has_interface (Grob *);
-  static Bezier get_curve (Grob *me);
-  static Bezier get_bezier (Grob *me, Drul_array<Offset>, Real, Real);
-  static Direction get_default_dir (Grob *me);
-  DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM));
-  DECLARE_SCHEME_CALLBACK (height, (SCM,SCM));
-
-  static void set_end_points (Grob *);
-  static Real get_boundary_notecolumn_y (Grob *me, Direction dir);
-  static Real broken_trend_y (Grob *me, Grob **, Direction dir);
-  static void set_control_points (Grob *me);
-  static Drul_array<Bound_info> get_bound_info (Spanner *me, Grob **common);
-
-  static void generate_curves (Grob *me,
-			       Grob *common[],
-			       Drul_array<Bound_info> extremes,
-			       Drul_array<Offset> base_attach,
-			       Array<Slur_score> *scores);
-  static Array<Slur_score> enumerate_attachments
-  (Grob *me, Grob *common[], Slur_score_parameters *score_param,
-   Drul_array<Bound_info> extremes,
-   Drul_array<Offset> base_attachment, Drul_array<Real> end_ys);
-  static Drul_array<Offset> get_base_attachments
-  (Spanner *sp, Grob **common, Drul_array<Bound_info> extremes);
-  static Drul_array<Real> get_y_attachment_range
-  (Spanner *sp, Grob **common, Drul_array<Bound_info> extremes,
-   Drul_array<Offset> base_attachment);
-};
-
-/* HDIR indicates the direction for the slur.  */
-Real
-New_slur::broken_trend_y (Grob *me, Grob **common, Direction hdir)
-{
-  /* A broken slur should maintain the same vertical trend
-    the unbroken slur would have had.  */
-  Real by = 0.0;
-  if (Spanner *mother = dynamic_cast<Spanner*> (me->original_))
-    {
-      int k = broken_spanner_index (dynamic_cast<Spanner*> (me));
-      int j = k + hdir;
-      if (j < 0 || j >= mother->broken_intos_.size ())
-	return by;
-
-      Grob *neighbor = mother->broken_intos_[j];
-      if (hdir == RIGHT)
-	neighbor->set_property ("direction",
-				me->get_property ("direction"));
-
-      Spanner *common_mother
-	= dynamic_cast<Spanner*> (common[Y_AXIS]->original_);
-      int common_k
-	= broken_spanner_index (dynamic_cast<Spanner*> (common[Y_AXIS]));
-      int common_j = common_k + hdir;
-
-      if (common_j < 0 || common_j >= common_mother->broken_intos_.size())
-	return by;
-
-      Grob *common_next_system = common_mother->broken_intos_[common_j];
-      Link_array<Grob> neighbor_cols
-	= Pointer_group_interface__extract_grobs (neighbor, (Grob *)0,
-						  "note-columns");
-
-      Grob *neighbor_col
-	= (hdir == RIGHT) ? neighbor_cols[0] : neighbor_cols.top ();
-      Grob *neighbor_common
-	= common_next_system->common_refpoint (neighbor_col, Y_AXIS);
-
-      Direction vdir = get_grob_direction (me);
-      Real neighbor_y
-	= neighbor_col->extent (neighbor_common, Y_AXIS)
-	.linear_combination (int(neighbor_cols.size()==1 ? CENTER : vdir))
-	- common_next_system->relative_coordinate (neighbor_common, Y_AXIS);
-
-      Link_array<Grob> my_cols
-	= Pointer_group_interface__extract_grobs (me, (Grob *)0,
-						  "note-columns");
-
-      Grob *extreme_col = (hdir == RIGHT) ? my_cols.top() : my_cols[0];
-      Real y = extreme_col->extent (common[Y_AXIS], Y_AXIS)
-	.linear_combination (int ((my_cols.size() == 1) ? CENTER : vdir));
-      by = (y*neighbor_cols.size() + neighbor_y*my_cols.size()) /
-	(my_cols.size() + neighbor_cols.size());
-    }
-  return by;
-}
-
-void
-New_slur::set_interface (Grob*me)
-{
-  /* Copy to mutable list. */
-  me->set_property ("attachment",
-		    ly_deep_copy (me->get_property ("attachment")));
-}
-
-void
-New_slur::add_column (Grob*me, Grob*n)
-{
-  Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-columns"), n);
-  me->add_dependency (n);
-
-  add_bound_item (dynamic_cast<Spanner*> (me), dynamic_cast<Item*> (n));
-}
-
-Encompass_info
-New_slur::get_encompass_info (Grob *me,
-			      Grob *col,
-			      Grob **common)
-{
-  Grob* stem = unsmob_grob (col->get_property ("stem"));
-
-  Encompass_info ei;
-
-  Direction dir = get_grob_direction (me);
-
-  if (!stem)
-    {
-      programming_error ("No stem for note column?");
-      ei.x_ = col->relative_coordinate (common[X_AXIS], X_AXIS);
-      ei.head_ = ei.stem_ = col->extent (common[Y_AXIS],
-					 Y_AXIS)[get_grob_direction (me)];
-      return ei;
-    }
-  Direction stem_dir = get_grob_direction (stem);
-
-  if (Grob *head = Note_column::first_head (col))
-    ei.x_ = head->extent (common[X_AXIS], X_AXIS).center ();
-  else
-    ei.x_ = col->extent (common[X_AXIS], X_AXIS).center ();
-
-  Grob * h = Stem::extremal_heads (stem)[Direction (dir)];
-  if (!h)
-    {
-      ei.head_ = ei.stem_ = col->extent (common[Y_AXIS], Y_AXIS)[dir];
-      return ei;
-    }
-
-  ei.head_ = h->extent (common[Y_AXIS], Y_AXIS)[dir];
-
-  if ((stem_dir == dir)
-      && !stem->extent (stem, Y_AXIS).is_empty ())
-    {
-      ei.stem_ = stem->extent (common[Y_AXIS], Y_AXIS)[dir];
-      if (Grob * b = Stem::get_beam (stem))
-	ei.stem_ += stem_dir * 0.5 * Beam::get_thickness (b);
-      ei.x_  = stem->extent (common[X_AXIS], X_AXIS).center ();
-    }
-  else
-    ei.stem_ = ei.head_;
-
-  return ei;
-}
-
-
-Direction
-New_slur::get_default_dir (Grob*me)
-{
-  Link_array<Grob> encompasses
-    = Pointer_group_interface__extract_grobs (me, (Grob*) 0, "note-columns");
-
-  Direction d = DOWN;
-  for (int i= 0; i < encompasses.size (); i ++)
-    {
-      if (Note_column::dir (encompasses[i]) < 0)
-	{
-	  d = UP;
-	  break;
-	}
-    }
-  return d;
-}
-
-MAKE_SCHEME_CALLBACK (New_slur, after_line_breaking,1);
-SCM
-New_slur::after_line_breaking (SCM smob)
-{
-  Spanner *me = dynamic_cast<Spanner*> (unsmob_grob (smob));
-  if (!scm_ilength (me->get_property ("note-columns")))
-    {
-      me->suicide ();
-      return SCM_UNSPECIFIED;
-    }
-
-  if (!get_grob_direction (me))
-    set_grob_direction (me, get_default_dir (me));
-
-  set_end_points (me);
-
-  return SCM_UNSPECIFIED;
-}
-
-Bezier
-New_slur::get_bezier (Grob *me, Drul_array<Offset> extremes,
-		      Real r_0,
-		      Real h_inf)
-{
-  Array<Offset> encompasses;
-  encompasses.push (extremes[LEFT]);
-  encompasses.push (extremes[RIGHT]);
-
-  Slur_bezier_bow bb (encompasses,
-		      get_grob_direction (me), h_inf, r_0);
-
-  return bb.get_bezier ();
-}
-
-
-Drul_array<Bound_info>
-New_slur::get_bound_info (Spanner* me,
-			  Grob **common)
-{
-  Drul_array<Bound_info> extremes;
-  Direction d = LEFT;
-  Direction dir = get_grob_direction (me);
-
-  do {
-    extremes[d].bound_ = me->get_bound (d);
-
-    if (Note_column::has_interface (extremes[d].bound_))
-      {
-	extremes[d].note_column_ = extremes[d].bound_;
-	extremes[d].stem_ = Note_column::get_stem (extremes[d].note_column_);
-	extremes[d].stem_dir_ = get_grob_direction (extremes[d].stem_);
-	extremes[d].stem_extent_[X_AXIS] = extremes[d].stem_->extent (common[X_AXIS], X_AXIS);
-	extremes[d].stem_extent_[Y_AXIS] = extremes[d].stem_->extent (common[Y_AXIS], Y_AXIS);
-	extremes[d].slur_head_ = Stem::extremal_heads (extremes[d].stem_)[dir];
-	extremes[d].slur_head_extent_ = extremes[d].slur_head_->extent (common[X_AXIS], X_AXIS);
-	extremes[d].staff_ = Staff_symbol_referencer::get_staff_symbol (extremes[d].slur_head_);
-	extremes[d].staff_space_ = Staff_symbol_referencer::staff_space (extremes[d].slur_head_);
-      }
-    else
-      {
-	extremes[d].neighbor_y_ = broken_trend_y (me, common, d);
-      }
-  } while (flip (&d) != LEFT);
-
-  return extremes;
-}
-
-void
-New_slur::set_end_points (Grob *me)
-{
-  Link_array<Grob> columns
-    = Pointer_group_interface__extract_grobs (me, (Grob *)0, "note-columns");
-  Slur_score_parameters params;
-  if (columns.is_empty ())
-    {
-      me->suicide ();
-      return;
-    }
-
-  SCM eltlist = me->get_property ("note-columns");
-  Grob *common[] = {common_refpoint_of_list (eltlist, me, X_AXIS),
-		    common_refpoint_of_list (eltlist, me, Y_AXIS)};
-
-
-  Spanner *sp = dynamic_cast<Spanner*> (me);
-  common[X_AXIS] = common[X_AXIS]->common_refpoint (sp->get_bound (RIGHT),
-						    X_AXIS);
-  common[X_AXIS] = common[X_AXIS]->common_refpoint (sp->get_bound (LEFT),
-						    X_AXIS);
-  Drul_array<Bound_info> extremes = get_bound_info (sp, common);
-  Drul_array<Offset> base_attachment
-    = get_base_attachments (sp, common, extremes);
-  Drul_array<Real> end_ys
-    = get_y_attachment_range (sp, common, extremes, base_attachment);
-  Array<Slur_score> scores = enumerate_attachments (me, common, &params,
-						    extremes, base_attachment,
-						    end_ys);
-
-  generate_curves (me, common, extremes, base_attachment, &scores);
-  score_edges (me, common, &params,extremes, base_attachment, &scores);
-  score_slopes (me, common, &params,extremes, base_attachment, &scores);
-  score_encompass (me, common, &params,extremes, base_attachment, &scores);
-  
-  Real opt = 1e6;
-  int opt_idx = 0;
-  // why backwards?
-  for (int i = scores.size (); i--;)
-    {
-      if (scores[i].score_  < opt)
-	{
-	  opt = scores[i].score_;
-	  opt_idx = i;
-	}
-    }
-
-#if DEBUG_SLUR_QUANTING
-  SCM inspect_quants = me->get_property ("inspect-quants");
-  if (to_boolean (me->get_paper ()
-		  ->lookup_variable (ly_symbol2scm ("debug-slur-quanting")))
-      && ly_c_pair_p (inspect_quants))
-    {
-      Drul_array<Real> ins = ly_scm2interval (inspect_quants);
-      int i = 0;
-
-      Real mindist = 1e6;
-      for (; i < scores.size (); i ++)
-	{
-	  Real d =fabs (scores[i].attachment_[LEFT][Y_AXIS] - ins[LEFT])
-	    + fabs (scores[i].attachment_[RIGHT][Y_AXIS] - ins[RIGHT]);
-	  if (d < mindist)
-	    {
-	      opt_idx = i;
-	      mindist= d;
-	    }
-	}
-      if (mindist > 1e5)
-	programming_error ("Could not find quant.");
-    }
-  scores[opt_idx].score_card_ += to_string ("i%d", opt_idx);
-
-  // debug quanting
-  me->set_property ("quant-score",
-		    scm_makfrom0str (scores[opt_idx].score_card_.to_str0 ()));
-#endif
-  
-
-  Bezier b = scores[opt_idx].curve_;
-  SCM controls = SCM_EOL;
-  for (int i = 4; i--;)
-    {
-      Offset o = b.control_[i] -
-	Offset (me->relative_coordinate (common[X_AXIS], X_AXIS),
-		me->relative_coordinate (common[Y_AXIS], Y_AXIS));
-
-      controls = scm_cons (ly_offset2scm (o), controls);
-    }
-
-  me->set_property ("control-points", controls);
-}
-
-
-Drul_array<Real>
-New_slur::get_y_attachment_range (Spanner*me,
-				  Grob **common,
-				  Drul_array<Bound_info> extremes,
-				  Drul_array<Offset> base_attachment)
-{
-  Drul_array<Real> end_ys;
-  Direction dir = get_grob_direction (me);
-  Direction d = LEFT;
-  do
-    {
-      if (extremes[d].note_column_)
-	{
-	  end_ys[d] = dir
-	    * ((dir * (base_attachment[d][Y_AXIS] + 4.0 * dir))
-	       >? (dir * (dir + extremes[d].note_column_->extent(common[Y_AXIS],
-								 Y_AXIS)[dir]))
-	       >? (dir * base_attachment[-d][Y_AXIS]));
-	}
-      else
-      end_ys[d] = extremes[d].neighbor_y_ + 4.0 * dir;
-    }
-  while (flip (&d) != LEFT);
-
-  return end_ys;
-}
-
-Drul_array<Offset>
-New_slur::get_base_attachments (Spanner *me,
-				Grob **common, Drul_array<Bound_info> extremes)
-{
-  Link_array<Grob> columns
-    = Pointer_group_interface__extract_grobs (me, (Grob *)0, "note-columns");
-  Drul_array<Offset> base_attachment;
-  Slur_score_parameters params;
-  Real staff_space = Staff_symbol_referencer::staff_space ((Grob*)me);
-  Direction dir = get_grob_direction (me);
-  Direction d = LEFT;
-  do
-    {
-      Grob *stem = extremes[d].stem_;
-      Grob *head = extremes[d].slur_head_;
-
-      Real x, y;
-      if (!extremes[d].note_column_)
-	{
-	  y = extremes[d].neighbor_y_;
-	  if (d== RIGHT)
-	    x = extremes[d].bound_->extent (common[X_AXIS], X_AXIS)[d];
-	  else
-	    x = me->get_broken_left_end_align ();
-	}
-      else
-	{
-	  if (stem
-	      && extremes[d].stem_dir_ == dir
-	      && Stem::get_beaming (stem, -d)
-	      && columns.size () > 2
-	      )
-	    y = extremes[d].stem_extent_[Y_AXIS][dir];
-	  else if (head)
-	    y = head->extent (common[Y_AXIS], Y_AXIS)[dir];
-	  y += dir * 0.5 * staff_space;
-
-	  Real pos
-	    = (y - extremes[d].staff_->relative_coordinate (common[Y_AXIS],
-							    Y_AXIS))
-	    * 2.0 / Staff_symbol::staff_space (extremes[d].staff_);
-
-	  /* start off staffline. */
-	  if (fabs (pos - round (pos)) < 0.2
-	      && Staff_symbol_referencer::on_staffline (head, (int) rint (pos))
-	      && Staff_symbol_referencer::line_count (head) - 1 >= rint (pos)
-	      )
-	    // TODO: calc from slur thick & line thick, parameter.	    
-	    y += 1.5 * staff_space * dir / 10;
-
-	  Grob * fh = Note_column::first_head (extremes[d].note_column_);
-	  x = fh->extent (common[X_AXIS], X_AXIS).linear_combination (CENTER);
-	}
-      base_attachment[d] = Offset (x, y);
-
-    } while (flip (&d) != LEFT);
-
-  return base_attachment;
-}
-
-void
-New_slur::generate_curves (Grob *me, Grob **common,
-			   Drul_array<Bound_info> extremes,
-			   Drul_array<Offset>,
-			   Array<Slur_score> *scores)
-{
-  (void) common;
-  (void) extremes;
-  Real staff_space = Staff_symbol_referencer::staff_space ((Grob *) me);
-  Real r_0 = robust_scm2double (me->get_property ("ratio"), 0.33);
-  Real h_inf = staff_space * ly_scm2double (me->get_property ("height-limit"));
-  for (int i = 0; i < scores->size(); i++)
-    {
-      Bezier bez= get_bezier (me, (*scores)[i].attachment_, r_0, h_inf);
-      bez = avoid_staff_line (me, common, extremes, bez);
-      (*scores)[i].attachment_[LEFT] = bez.control_[0];
-      (*scores)[i].attachment_[RIGHT] = bez.control_[3];
-      (*scores)[i].curve_ = bez;
-    }
-}
-
-Bezier
-New_slur::avoid_staff_line (Grob *me, Grob **common,
-			    Drul_array<Bound_info> extremes,
-			    Bezier bez)
-{
-  Offset horiz (1,0);
-  Array<Real> ts  = bez.solve_derivative (horiz);
-  Real lt =  me->get_paper ()->get_dimension (ly_symbol2scm ("linethickness"));
-  Real thick = robust_scm2double (me->get_property ("thickness"), 1.0) *  lt;
-
-  /* TODO: handle case of broken slur.  */
-  if (!ts.is_empty ()
-      && (extremes[LEFT].staff_ == extremes[RIGHT].staff_)
-      && extremes[LEFT].staff_ && extremes[RIGHT].staff_)
-    {
-      Real y = bez.curve_point (ts[0])[Y_AXIS];
-
-      Grob *staff = extremes[LEFT].staff_;
-
-      Real staff_space = extremes[LEFT].staff_space_;
-      Real p = 2 * (y - staff->relative_coordinate (common[Y_AXIS], Y_AXIS))
-	/ staff_space;
-
-      Real distance = fabs (round (p) - p);	//  in halfspaces
-      if (distance < 4 * thick
-	  && (int) fabs (round (p))
-	  <= 2 * Staff_symbol_referencer::staff_radius (staff) + 0.1
-	  && (int (fabs (round (p))) % 2
-	      != Staff_symbol_referencer::line_count (staff) % 2))
-	{
-	  Direction resolution_dir =  - get_grob_direction (me);
-	  // 	    (distance ?  :sign (p - round(p)))
-
-	  // TODO: parameter
-	  Real newp = round (p) + resolution_dir
-	    * 5 * thick;
-	  Real dy = (newp - p) * staff_space / 2.0;
-	  bez.translate (Offset (0, dy));
-	}
-    }
-  return bez;
-}
-
-Array<Slur_score>
-New_slur::enumerate_attachments (Grob *me, Grob **,
-				 Slur_score_parameters *score_param,
-				 Drul_array<Bound_info> extremes,
-				 Drul_array<Offset> base_attachment,
-				 Drul_array<Real> end_ys)
-{
-  /*ugh.   */
-  Array<Slur_score> scores;
-
-  Direction dir = get_grob_direction (me);
-  Real staff_space = Staff_symbol_referencer::staff_space ((Grob *)me);
-
-  Drul_array<Offset> os;
-  os[LEFT] = base_attachment[LEFT];
-  Real minimum_length = staff_space
-    * robust_scm2double (me->get_property ("minimum-length"), 2.0);
-
-  for (int i = 0; dir * os[LEFT][Y_AXIS] <= dir * end_ys[LEFT]; i++)
-    {
-      os[RIGHT] = base_attachment[RIGHT];
-      for (int j = 0; dir * os[RIGHT][Y_AXIS] <= dir * end_ys[RIGHT]; j++)
-	{
-	  Slur_score s;
-	  Direction d = LEFT;
-	  Drul_array<bool> attach_to_stem (false, false);
-	  do {  
-	    os[d][X_AXIS] = base_attachment[d][X_AXIS];
-	    if (extremes[d].stem_
-		&& !Stem::is_invisible (extremes[d].stem_)
-		&& extremes[d].stem_dir_ == dir
-		&& dir == -d)
-	      {
-		if (extremes[d].stem_extent_[Y_AXIS].contains (os[d][Y_AXIS]))
-		  {
-		    os[d][X_AXIS] =  extremes[d].slur_head_extent_[-d]
-		      - d * 0.3;
-		    attach_to_stem[d] = true;
-		  }
-		else if (dir *extremes[d].stem_extent_[Y_AXIS][dir] < dir * os[d][Y_AXIS])
-		  {
-		    os[d][X_AXIS] = extremes[d].stem_extent_[X_AXIS].center();
-		  }
-	      }
-	  } while (flip (&d) != LEFT);
-
-	  Offset dz;	  
-	  dz = os[RIGHT] - os[LEFT];
-	  if (dz[X_AXIS] < minimum_length
-	      || fabs (dz[Y_AXIS] / dz[X_AXIS]) > score_param->MAX_SLOPE
-	      )
-	    {
-	      do
-		{
-		 if (extremes[d].slur_head_)
-		   {
-		     os[d][X_AXIS] = extremes[d].slur_head_extent_.center ();
-		     attach_to_stem[d] = false;
-		   }
-	      }
-	      while (flip (&d) != LEFT);
-	    }
-
-	  dz = os[RIGHT] - os[LEFT];
-	  do {
-	    if (extremes[d].slur_head_
-		&& !attach_to_stem[d])
-	      {
-		/*
-		  horizontally move tilted slurs a little. Move more
-		  for bigger tilts.
-
-		  TODO: parameter
-		 */
-		os[d][X_AXIS] -=
-		  dir * extremes[d].slur_head_extent_.length () * sin (dz.arg  ()) / 3;
-	      }
-	  } while (flip (&d) != LEFT);
-	  
-	  s.attachment_ = os;
-	  scores.push (s);
-
-	  os[RIGHT][Y_AXIS] += dir * staff_space / 2;
-	}
-
-      os[LEFT][Y_AXIS] += dir * staff_space / 2;
-    }
-
-  return scores;
-}
-
-void
-New_slur::score_encompass (Grob *me, Grob *common[],
-			   Slur_score_parameters *score_param,
-			   Drul_array<Bound_info> ,
-			   Drul_array<Offset> ,
-			   Array<Slur_score> * scores)
-{
-  Link_array<Grob> encompasses
-    = Pointer_group_interface__extract_grobs (me, (Grob *)0, "note-columns");
-  Direction dir = get_grob_direction (me);
-
-  Array<Encompass_info> infos;
-
-  for (int i = 0; i < encompasses.size(); i++)
-    infos.push (get_encompass_info (me, encompasses[i], common));
-
-  for (int i = 0; i < scores->size (); i++)
-    {
-      Bezier const &bez (scores->elem (i).curve_);
-      Real demerit = 0.0;
-      for (int j = 0; j < infos.size(); j++)
-	{
-	  Real x = infos[j].x_;
-
-	  bool l_edge = j==0;
-	  bool r_edge = j==infos.size()-1;
-	  bool edge =  l_edge || r_edge;
-  
-	  if (!(x < scores->elem (i).attachment_[RIGHT][X_AXIS]
-		&& x > scores->elem (i).attachment_[LEFT][X_AXIS]))
-	    continue;
-	
-	  Real y = bez.get_other_coordinate (X_AXIS, x);
-	  if (!edge)
-	    {
-	      Real head_dy = (y - infos[j].head_);
-	      if (dir * head_dy < 0)
-		demerit += score_param->HEAD_ENCOMPASS_PENALTY;
-	      else
-		{
-		  Real hd = (head_dy)
-		    ? (1 / fabs (head_dy) - 1 / score_param->FREE_HEAD_DISTANCE)
-		    : score_param->HEAD_ENCOMPASS_PENALTY;
-		  hd = (hd >? 0)<? score_param->HEAD_ENCOMPASS_PENALTY;
-
-		  demerit += hd;	
-		}
-	    }	  
-
-	  if (dir * (y - infos[j].stem_) < 0)
-	    {
-	      Real stem_dem =score_param->STEM_ENCOMPASS_PENALTY ; 
-	      if ((l_edge && dir == UP)
-		  || (r_edge && dir == DOWN))
-		{
-		  stem_dem /= 5;
-		}
-
-	      demerit +=  stem_dem;
-	    }
-	  else if (!edge)
-	    {
-	      Interval ext;
-	      ext.add_point (infos[j].stem_);
-	      ext.add_point (infos[j].head_);
-
-	      demerit += - score_param->CLOSENESS_FACTOR * (dir * (y - (ext[dir] + dir * score_param->FREE_HEAD_DISTANCE)) <? 0) /
-		infos.size ();
-	    }
-	}
-
-#if DEBUG_SLUR_QUANTING
-      (*scores)[i].score_card_ += to_string ("C%.2f", demerit);
-#endif
-
-      (*scores)[i].score_ += demerit;
-    }
-}
-
-void
-New_slur::score_edges (Grob *me, Grob **,
-		       Slur_score_parameters * score_param,
-		       Drul_array<Bound_info> extremes,
-		       Drul_array<Offset> base_attach,
-		       Array<Slur_score> *scores)
-{
-  Direction dir = get_grob_direction (me);
-
-  for (int i = 0; i < scores->size (); i++)
-    {
-
-      Direction d = LEFT;
-      do {
-	Real y = scores->elem (i).attachment_[d][Y_AXIS];
-	Real dy = fabs (y - base_attach[d][Y_AXIS]);
-	
-	Real factor = score_param->EDGE_ATTRACTION_FACTOR;
-	Real demerit = factor * dy;
- 	if (extremes[d].stem_
- 	    && extremes[d].stem_dir_ == dir
- 	    && !Stem::get_beaming (extremes[d].stem_, -d)
- 	    )
- 	  demerit /= 5;
-	
-	(*scores)[i].score_ += demerit;
-#if DEBUG_SLUR_QUANTING
-	(*scores)[i].score_card_ += to_string ("E%.2f", demerit);
-#endif
-      } while (flip (&d) != LEFT);
-    }
-}
-
-void
-New_slur::score_slopes (Grob *me, Grob *common[],
-			Slur_score_parameters*score_param,
-			Drul_array<Bound_info> extremes,
-			Drul_array<Offset> base_attach,
-			Array<Slur_score> * scores)
-{
-  Drul_array<Real> ys;
-
-  Direction d = LEFT;
-  do {
-    if (extremes[d].slur_head_)
-      ys[d] = extremes[d].slur_head_ ->relative_coordinate (common[Y_AXIS],
-							    Y_AXIS);
-    else
-      ys[d] = extremes[d].neighbor_y_;
-  } while (flip (&d) != LEFT);
-
-  bool has_beams
-    = (extremes[LEFT].stem_ && Stem::get_beam (extremes[LEFT].stem_))
-    || (extremes[RIGHT].stem_ && Stem::get_beam (extremes[RIGHT].stem_));
-
-  Direction dir = get_grob_direction (me);
-  Real dy = ys[RIGHT] - ys[LEFT];
-  for (int i = 0; i < scores->size (); i++)
-    {
-      Offset slur_dz = (*scores)[i].attachment_[RIGHT]
-	-  (*scores)[i].attachment_[LEFT];
-      Real slur_dy = slur_dz[Y_AXIS]; 
-      Real demerit = 0.0;
-
-      demerit += ((fabs (slur_dy/slur_dz[X_AXIS])
-		   - score_param->MAX_SLOPE) >? 0)
-	* score_param->MAX_SLOPE_FACTOR;
-
-	/*
-	  0.2: account for staffline offset.
-	*/
-      Real max_dy = (fabs (dy) + 0.2);
-      if (has_beams)
-	max_dy += 1.0; 
-      
-      demerit += score_param->STEEPER_SLOPE_FACTOR * ((fabs (slur_dy) -max_dy) >? 0); 
-
-      
-      demerit += ((fabs (slur_dy/slur_dz[X_AXIS]) - score_param->MAX_SLOPE)>?0)  * score_param->MAX_SLOPE_FACTOR;
-      
-      if (sign (dy) == 0 &&
-	  sign (slur_dy) != 0)
-	demerit += score_param->NON_HORIZONTAL_PENALTY;
-
-      if (sign (dy)
-	  && sign (slur_dy)
-	  && sign (slur_dy) != sign (dy))
-	demerit += has_beams
-	  ? score_param->SAME_SLOPE_PENALTY / 10
-	  : score_param->SAME_SLOPE_PENALTY;
-
-#if DEBUG_SLUR_QUANTING
-      (*scores)[i].score_card_ += to_string ("S%.2f",d);
-#endif
-      (*scores)[i].score_ += demerit;
-    }
-}
-
-
-Bezier
-New_slur::get_curve (Grob*me)
-{
-  Bezier b;
-  int i = 0;
-  for (SCM s = me->get_property ("control-points"); s != SCM_EOL;
-       s = ly_cdr (s))
-    b.control_[i++] = ly_scm2offset (ly_car (s));
-
-  return b;
-}
-
-
 MAKE_SCHEME_CALLBACK (New_slur, height, 2);
 SCM
 New_slur::height (SCM smob, SCM ax)
@@ -998,6 +99,47 @@ New_slur::print (SCM smob)
 }
 
 
+Bezier
+New_slur::get_curve (Grob*me)
+{
+  Bezier b;
+  int i = 0;
+  for (SCM s = me->get_property ("control-points"); s != SCM_EOL;
+       s = ly_cdr (s))
+    b.control_[i++] = ly_scm2offset (ly_car (s));
+
+  return b;
+}
+
+
+void
+New_slur::set_interface (Grob*me)
+{
+  /* Copy to mutable list. */
+  me->set_property ("attachment",
+		    ly_deep_copy (me->get_property ("attachment")));
+}
+
+void
+New_slur::add_column (Grob*me, Grob*n)
+{
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-columns"), n);
+  me->add_dependency (n);
+
+  add_bound_item (dynamic_cast<Spanner*> (me), dynamic_cast<Item*> (n));
+}
+
+
+void
+New_slur::add_extra_encompass (Grob*me, Grob*n)
+{
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("encompass-objects"), n);
+  me->add_dependency (n);
+
+  add_bound_item (dynamic_cast<Spanner*> (me), dynamic_cast<Item*> (n));
+}
+
+
 ADD_INTERFACE (New_slur, "new-slur-interface",
 	       "A slur",
-	       "control-points dashed details direction height-limit note-columns ratio slope-limit thickness");
+	       "extra-encompass control-points dashed details direction height-limit note-columns ratio thickness");
diff --git a/lily/phrasing-slur-engraver.cc b/lily/phrasing-slur-engraver.cc
index e3e289ce38..69865eae59 100644
--- a/lily/phrasing-slur-engraver.cc
+++ b/lily/phrasing-slur-engraver.cc
@@ -5,7 +5,7 @@
 */
 
 #include "event.hh"
-#include "slur.hh"
+#include "new-slur.hh"
 #include "warn.hh"
 #include "note-column.hh"
 #include "context.hh"
@@ -82,9 +82,9 @@ Phrasing_slur_engraver::acknowledge_grob (Grob_info info)
     {
       Grob *e =info.grob_;
       for (int i = 0; i < phrasing_slurs_.size (); i++)
-	Slur::add_column (phrasing_slurs_[i], e);
+	New_slur::add_column (phrasing_slurs_[i], e);
       for (int i = 0; i < end_phrasing_slurs_.size (); i++)
-	Slur::add_column (end_phrasing_slurs_[i], e);
+	New_slur::add_column (end_phrasing_slurs_[i], e);
     }
 }
 
@@ -133,8 +133,6 @@ Phrasing_slur_engraver::process_acknowledged_grobs ()
 	  // push a new phrasing_slur onto stack.
 	  // (use temp. array to wait for all phrasing_slur STOPs)
 	  Grob* phrasing_slur = make_spanner ("PhrasingSlur", phrasing_slur_ev->self_scm ());
-	  Slur::set_interface (phrasing_slur); // can't remove.
-
 
 	  if (Direction updown = to_dir (phrasing_slur_ev->get_property ("direction")))
 	    {
diff --git a/lily/slur-engraver.cc b/lily/slur-engraver.cc
index 7c6bc4fb6a..4164777ea2 100644
--- a/lily/slur-engraver.cc
+++ b/lily/slur-engraver.cc
@@ -5,7 +5,7 @@
 */
 
 #include "event.hh"
-#include "slur.hh"
+#include "new-slur.hh"
 #include "warn.hh"
 #include "note-column.hh"
 #include "context.hh"
@@ -94,13 +94,20 @@ Slur_engraver::set_melisma (bool m)
 void
 Slur_engraver::acknowledge_grob (Grob_info info)
 {
+  Grob *e =info.grob_;
   if (Note_column::has_interface (info.grob_))
     {
-      Grob *e =info.grob_;
       for (int i = 0; i < slur_stack_.size (); i++)
-	Slur::add_column (slur_stack_[i], e);
+	New_slur::add_column (slur_stack_[i], e);
       for (int i = 0; i < end_slurs_.size (); i++)
-	Slur::add_column (end_slurs_[i], e);
+	New_slur::add_column (end_slurs_[i], e);
+    }
+  else
+    {
+      for (int i = 0; i < slur_stack_.size (); i++)
+	New_slur::add_extra_encompass (end_slurs_[i], e);
+      for (int i = 0; i < end_slurs_.size (); i++)
+	New_slur::add_extra_encompass (end_slurs_[i], e);
     }
 }
 
@@ -150,8 +157,6 @@ Slur_engraver::process_music ()
 	  // push a new slur onto stack.
 	  // (use temp. array to wait for all slur STOPs)
 	  Grob* slur = make_spanner ("Slur", slur_ev->self_scm ());
-	  Slur::set_interface (slur); // cannot remove yet!
-
 
 	  if (Direction updown = to_dir (slur_ev->get_property ("direction")))
 	    {
@@ -183,6 +188,6 @@ ENTER_DESCRIPTION (Slur_engraver,
 /* descr */       "Build slurs from Slur_evs",
 /* creats*/       "Slur",
 /* accepts */     "slur-event",
-/* acks  */      "note-column-interface",
+/* acks  */      "note-column-interface accidental-interface script-interface",
 /* reads */       "slurMelismaBusy",
 /* write */       "");
diff --git a/lily/slur-quanting.cc b/lily/slur-quanting.cc
new file mode 100644
index 0000000000..8748218a1f
--- /dev/null
+++ b/lily/slur-quanting.cc
@@ -0,0 +1,910 @@
+/*
+  slur.cc -- implement score based Slur
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 1996--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+
+#include <math.h>
+
+#include "directional-element-interface.hh"
+#include "group-interface.hh"
+#include "lily-guile.hh"
+#include "note-column.hh"
+#include "output-def.hh"
+#include "slur-bezier-bow.hh"
+#include "new-slur.hh"
+#include "spanner.hh"
+#include "staff-symbol-referencer.hh"
+#include "staff-symbol.hh"
+#include "stem.hh"
+#include "warn.hh"
+#include "beam.hh"
+
+
+
+#define DEBUG_SLUR_QUANTING 1
+
+struct Slur_score
+{
+  Drul_array<Offset> attachment_;
+  Real score_;
+  Bezier curve_;
+
+#if DEBUG_SLUR_QUANTING
+  String score_card_;
+#endif
+
+  Slur_score()
+  {
+    score_ = 0.0;
+  }
+};
+
+/*
+  TODO: put in details property.
+*/
+struct Slur_score_parameters
+{
+  int SLUR_REGION_SIZE;
+  Real HEAD_ENCOMPASS_PENALTY;
+  Real STEM_ENCOMPASS_PENALTY;
+  Real CLOSENESS_FACTOR;
+  Real EDGE_ATTRACTION_FACTOR;
+  Real SAME_SLOPE_PENALTY;
+  Real STEEPER_SLOPE_FACTOR;
+  Real NON_HORIZONTAL_PENALTY;
+  Real HEAD_STRICT_FREE_SPACE;
+  Real MAX_SLOPE;
+  Real MAX_SLOPE_FACTOR;
+  Real FREE_HEAD_DISTANCE;
+  Slur_score_parameters ();
+};
+
+/*
+  TODO:
+
+  - curve around flag for y coordinate
+  - better scoring.
+  - short-cut: try a smaller region first.
+  - collisions with accidentals
+  - collisions with scripts (staccato!)
+  - 
+*/
+struct Encompass_info
+{
+  Real x_;
+  Real stem_;
+  Real head_;
+  Encompass_info ()
+  {
+    x_ = 0.0;
+    stem_ = 0.0;
+    head_ = 0.0;
+  }
+};
+
+struct Bound_info
+{
+  Box stem_extent_;
+  Direction stem_dir_;
+  Grob *bound_;
+  Grob *note_column_;
+  Grob *slur_head_;
+  Grob *staff_;
+  Grob *stem_;
+  Interval slur_head_extent_;
+  Real neighbor_y_;
+  Real staff_space_;
+  
+  Bound_info ()
+  {
+    stem_ = 0;
+    neighbor_y_ = 0;
+    staff_ = 0;
+    slur_head_ = 0;
+    stem_dir_ = CENTER;
+    note_column_ = 0;
+  }
+};
+
+
+
+static void score_slopes (Grob *me, Grob *common[],
+			  Slur_score_parameters *score_param,
+			  Drul_array<Bound_info>,
+			  Drul_array<Offset> base_attach,
+			  Array<Slur_score> *scores);
+
+static void score_edges (Grob *me, Grob *common[],
+			 Slur_score_parameters *score_param,
+			 Drul_array<Bound_info> extremes,
+			 Drul_array<Offset> base_attach,
+			 Array<Slur_score> *scores);
+static void score_encompass (Grob *me, Grob *common[],
+			     Slur_score_parameters*,
+			     Drul_array<Bound_info>,
+			     Drul_array<Offset>, Array<Slur_score> *scores);
+static Bezier avoid_staff_line (Grob *me, Grob **common,
+				Drul_array<Bound_info> extremes,
+				Bezier bez);
+
+static Encompass_info get_encompass_info (Grob *me,
+					  Grob *col,
+					  Grob **common);
+static Bezier get_bezier (Grob *me, Drul_array<Offset>, Real, Real);
+static Direction get_default_dir (Grob *me);
+
+static void set_end_points (Grob *);
+static Real broken_trend_y (Grob *me, Grob **, Direction dir);
+static Drul_array<Bound_info> get_bound_info (Spanner *me, Grob **common);
+
+static void generate_curves (Grob *me,
+			     Grob *common[],
+			     Drul_array<Bound_info> extremes,
+			     Drul_array<Offset> base_attach,
+			     Array<Slur_score> *scores);
+static Array<Slur_score> enumerate_attachments
+(Grob *me, Grob *common[], Slur_score_parameters *score_param,
+ Drul_array<Bound_info> extremes,
+ Drul_array<Offset> base_attachment, Drul_array<Real> end_ys);
+static Drul_array<Offset> get_base_attachments
+(Spanner *sp, Grob **common, Drul_array<Bound_info> extremes);
+static Drul_array<Real> get_y_attachment_range
+(Spanner *sp, Grob **common, Drul_array<Bound_info> extremes,
+ Drul_array<Offset> base_attachment);
+
+void
+init_score_param (Slur_score_parameters *score_param)
+{
+  score_param->SLUR_REGION_SIZE = 5;
+  score_param->HEAD_ENCOMPASS_PENALTY = 1000.0;
+  score_param->STEM_ENCOMPASS_PENALTY = 30.0;
+  score_param->CLOSENESS_FACTOR = 10;
+  score_param->EDGE_ATTRACTION_FACTOR = 4;
+  score_param->SAME_SLOPE_PENALTY = 20;
+  score_param->STEEPER_SLOPE_FACTOR = 50;
+  score_param->NON_HORIZONTAL_PENALTY = 15;
+  score_param->HEAD_STRICT_FREE_SPACE = 0.2;
+  score_param->MAX_SLOPE = 1.1;
+  score_param->MAX_SLOPE_FACTOR = 10;
+  score_param->FREE_HEAD_DISTANCE = 0.3;
+}
+
+Slur_score_parameters::Slur_score_parameters()
+{
+  init_score_param (this);
+}
+
+/* HDIR indicates the direction for the slur.  */
+Real
+broken_trend_y (Grob *me, Grob **common, Direction hdir)
+{
+  /* A broken slur should maintain the same vertical trend
+     the unbroken slur would have had.  */
+  Real by = 0.0;
+  if (Spanner *mother = dynamic_cast<Spanner*> (me->original_))
+    {
+      int k = broken_spanner_index (dynamic_cast<Spanner*> (me));
+      int j = k + hdir;
+      if (j < 0 || j >= mother->broken_intos_.size ())
+	return by;
+
+      Grob *neighbor = mother->broken_intos_[j];
+      if (hdir == RIGHT)
+	neighbor->set_property ("direction",
+				me->get_property ("direction"));
+
+      Spanner *common_mother
+	= dynamic_cast<Spanner*> (common[Y_AXIS]->original_);
+      int common_k
+	= broken_spanner_index (dynamic_cast<Spanner*> (common[Y_AXIS]));
+      int common_j = common_k + hdir;
+
+      if (common_j < 0 || common_j >= common_mother->broken_intos_.size())
+	return by;
+
+      Grob *common_next_system = common_mother->broken_intos_[common_j];
+      Link_array<Grob> neighbor_cols
+	= Pointer_group_interface__extract_grobs (neighbor, (Grob *)0,
+						  "note-columns");
+
+      Grob *neighbor_col
+	= (hdir == RIGHT) ? neighbor_cols[0] : neighbor_cols.top ();
+      Grob *neighbor_common
+	= common_next_system->common_refpoint (neighbor_col, Y_AXIS);
+
+      Direction vdir = get_grob_direction (me);
+      Real neighbor_y
+	= neighbor_col->extent (neighbor_common, Y_AXIS)
+	.linear_combination (int(neighbor_cols.size()==1 ? CENTER : vdir))
+	- common_next_system->relative_coordinate (neighbor_common, Y_AXIS);
+
+      Link_array<Grob> my_cols
+	= Pointer_group_interface__extract_grobs (me, (Grob *)0,
+						  "note-columns");
+
+      Grob *extreme_col = (hdir == RIGHT) ? my_cols.top() : my_cols[0];
+      Real y = extreme_col->extent (common[Y_AXIS], Y_AXIS)
+	.linear_combination (int ((my_cols.size() == 1) ? CENTER : vdir));
+      by = (y*neighbor_cols.size() + neighbor_y*my_cols.size()) /
+	(my_cols.size() + neighbor_cols.size());
+    }
+  return by;
+}
+
+
+Encompass_info
+get_encompass_info (Grob *me,
+		    Grob *col,
+		    Grob **common)
+{
+  Grob* stem = unsmob_grob (col->get_property ("stem"));
+
+  Encompass_info ei;
+
+  Direction dir = get_grob_direction (me);
+
+  if (!stem)
+    {
+      programming_error ("No stem for note column?");
+      ei.x_ = col->relative_coordinate (common[X_AXIS], X_AXIS);
+      ei.head_ = ei.stem_ = col->extent (common[Y_AXIS],
+					 Y_AXIS)[get_grob_direction (me)];
+      return ei;
+    }
+  Direction stem_dir = get_grob_direction (stem);
+
+  if (Grob *head = Note_column::first_head (col))
+    ei.x_ = head->extent (common[X_AXIS], X_AXIS).center ();
+  else
+    ei.x_ = col->extent (common[X_AXIS], X_AXIS).center ();
+
+  Grob * h = Stem::extremal_heads (stem)[Direction (dir)];
+  if (!h)
+    {
+      ei.head_ = ei.stem_ = col->extent (common[Y_AXIS], Y_AXIS)[dir];
+      return ei;
+    }
+
+  ei.head_ = h->extent (common[Y_AXIS], Y_AXIS)[dir];
+
+  if ((stem_dir == dir)
+      && !stem->extent (stem, Y_AXIS).is_empty ())
+    {
+      ei.stem_ = stem->extent (common[Y_AXIS], Y_AXIS)[dir];
+      if (Grob * b = Stem::get_beam (stem))
+	ei.stem_ += stem_dir * 0.5 * Beam::get_thickness (b);
+      ei.x_  = stem->extent (common[X_AXIS], X_AXIS).center ();
+    }
+  else
+    ei.stem_ = ei.head_;
+
+  return ei;
+}
+
+
+Direction
+get_default_dir (Grob*me)
+{
+  Link_array<Grob> encompasses
+    = Pointer_group_interface__extract_grobs (me, (Grob*) 0, "note-columns");
+
+  Direction d = DOWN;
+  for (int i= 0; i < encompasses.size (); i ++)
+    {
+      if (Note_column::dir (encompasses[i]) < 0)
+	{
+	  d = UP;
+	  break;
+	}
+    }
+  return d;
+}
+
+MAKE_SCHEME_CALLBACK (New_slur, after_line_breaking,1);
+SCM
+New_slur::after_line_breaking (SCM smob)
+{
+  Spanner *me = dynamic_cast<Spanner*> (unsmob_grob (smob));
+  if (!scm_ilength (me->get_property ("note-columns")))
+    {
+      me->suicide ();
+      return SCM_UNSPECIFIED;
+    }
+
+  if (!get_grob_direction (me))
+    set_grob_direction (me, get_default_dir (me));
+
+  set_end_points (me);
+
+  return SCM_UNSPECIFIED;
+}
+
+
+Bezier
+get_bezier (Grob *me, Drul_array<Offset> extremes,
+	    Real r_0,
+	    Real h_inf)
+{
+  Array<Offset> encompasses;
+  encompasses.push (extremes[LEFT]);
+  encompasses.push (extremes[RIGHT]);
+
+  Slur_bezier_bow bb (encompasses,
+		      get_grob_direction (me), h_inf, r_0);
+
+  return bb.get_bezier ();
+}
+
+
+Drul_array<Bound_info>
+get_bound_info (Spanner* me,
+		Grob **common)
+{
+  Drul_array<Bound_info> extremes;
+  Direction d = LEFT;
+  Direction dir = get_grob_direction (me);
+
+  do {
+    extremes[d].bound_ = me->get_bound (d);
+
+    if (Note_column::has_interface (extremes[d].bound_))
+      {
+	extremes[d].note_column_ = extremes[d].bound_;
+	extremes[d].stem_ = Note_column::get_stem (extremes[d].note_column_);
+	extremes[d].stem_dir_ = get_grob_direction (extremes[d].stem_);
+	extremes[d].stem_extent_[X_AXIS] = extremes[d].stem_->extent (common[X_AXIS], X_AXIS);
+	extremes[d].stem_extent_[Y_AXIS] = extremes[d].stem_->extent (common[Y_AXIS], Y_AXIS);
+	extremes[d].slur_head_ = Stem::extremal_heads (extremes[d].stem_)[dir];
+	extremes[d].slur_head_extent_ = extremes[d].slur_head_->extent (common[X_AXIS], X_AXIS);
+	extremes[d].staff_ = Staff_symbol_referencer::get_staff_symbol (extremes[d].slur_head_);
+	extremes[d].staff_space_ = Staff_symbol_referencer::staff_space (extremes[d].slur_head_);
+      }
+    else
+      {
+	extremes[d].neighbor_y_ = broken_trend_y (me, common, d);
+      }
+  } while (flip (&d) != LEFT);
+
+  return extremes;
+}
+
+void
+set_end_points (Grob *me)
+{
+  Link_array<Grob> columns
+    = Pointer_group_interface__extract_grobs (me, (Grob *)0, "note-columns");
+  Slur_score_parameters params;
+  if (columns.is_empty ())
+    {
+      me->suicide ();
+      return;
+    }
+
+  SCM eltlist = me->get_property ("note-columns");
+  Grob *common[] = {common_refpoint_of_list (eltlist, me, X_AXIS),
+		    common_refpoint_of_list (eltlist, me, Y_AXIS)};
+
+
+  Spanner *sp = dynamic_cast<Spanner*> (me);
+  common[X_AXIS] = common[X_AXIS]->common_refpoint (sp->get_bound (RIGHT),
+						    X_AXIS);
+  common[X_AXIS] = common[X_AXIS]->common_refpoint (sp->get_bound (LEFT),
+						    X_AXIS);
+  Drul_array<Bound_info> extremes = get_bound_info (sp, common);
+  Drul_array<Offset> base_attachment
+    = get_base_attachments (sp, common, extremes);
+  Drul_array<Real> end_ys
+    = get_y_attachment_range (sp, common, extremes, base_attachment);
+  Array<Slur_score> scores = enumerate_attachments (me, common, &params,
+						    extremes, base_attachment,
+						    end_ys);
+
+  generate_curves (me, common, extremes, base_attachment, &scores);
+  score_edges (me, common, &params,extremes, base_attachment, &scores);
+  score_slopes (me, common, &params,extremes, base_attachment, &scores);
+  score_encompass (me, common, &params,extremes, base_attachment, &scores);
+  
+  Real opt = 1e6;
+  int opt_idx = 0;
+  // why backwards?
+  for (int i = scores.size (); i--;)
+    {
+      if (scores[i].score_  < opt)
+	{
+	  opt = scores[i].score_;
+	  opt_idx = i;
+	}
+    }
+
+#if DEBUG_SLUR_QUANTING
+  SCM inspect_quants = me->get_property ("inspect-quants");
+  if (to_boolean (me->get_paper ()
+		  ->lookup_variable (ly_symbol2scm ("debug-slur-quanting")))
+      && ly_c_pair_p (inspect_quants))
+    {
+      Drul_array<Real> ins = ly_scm2interval (inspect_quants);
+      int i = 0;
+
+      Real mindist = 1e6;
+      for (; i < scores.size (); i ++)
+	{
+	  Real d =fabs (scores[i].attachment_[LEFT][Y_AXIS] - ins[LEFT])
+	    + fabs (scores[i].attachment_[RIGHT][Y_AXIS] - ins[RIGHT]);
+	  if (d < mindist)
+	    {
+	      opt_idx = i;
+	      mindist= d;
+	    }
+	}
+      if (mindist > 1e5)
+	programming_error ("Could not find quant.");
+    }
+  scores[opt_idx].score_card_ += to_string ("i%d", opt_idx);
+
+  // debug quanting
+  me->set_property ("quant-score",
+		    scm_makfrom0str (scores[opt_idx].score_card_.to_str0 ()));
+#endif
+  
+
+  Bezier b = scores[opt_idx].curve_;
+  SCM controls = SCM_EOL;
+  for (int i = 4; i--;)
+    {
+      Offset o = b.control_[i] -
+	Offset (me->relative_coordinate (common[X_AXIS], X_AXIS),
+		me->relative_coordinate (common[Y_AXIS], Y_AXIS));
+
+      controls = scm_cons (ly_offset2scm (o), controls);
+    }
+
+  me->set_property ("control-points", controls);
+}
+
+
+Drul_array<Real>
+get_y_attachment_range (Spanner*me,
+			Grob **common,
+			Drul_array<Bound_info> extremes,
+			Drul_array<Offset> base_attachment)
+{
+  Drul_array<Real> end_ys;
+  Direction dir = get_grob_direction (me);
+  Direction d = LEFT;
+  do
+    {
+      if (extremes[d].note_column_)
+	{
+	  end_ys[d] = dir
+	    * ((dir * (base_attachment[d][Y_AXIS] + 4.0 * dir))
+	       >? (dir * (dir + extremes[d].note_column_->extent(common[Y_AXIS],
+								 Y_AXIS)[dir]))
+	       >? (dir * base_attachment[-d][Y_AXIS]));
+	}
+      else
+	end_ys[d] = extremes[d].neighbor_y_ + 4.0 * dir;
+    }
+  while (flip (&d) != LEFT);
+
+  return end_ys;
+}
+
+Drul_array<Offset>
+get_base_attachments (Spanner *me,
+		      Grob **common, Drul_array<Bound_info> extremes)
+{
+  Link_array<Grob> columns
+    = Pointer_group_interface__extract_grobs (me, (Grob *)0, "note-columns");
+  Drul_array<Offset> base_attachment;
+  Slur_score_parameters params;
+  Real staff_space = Staff_symbol_referencer::staff_space ((Grob*)me);
+  Direction dir = get_grob_direction (me);
+  Direction d = LEFT;
+  do
+    {
+      Grob *stem = extremes[d].stem_;
+      Grob *head = extremes[d].slur_head_;
+
+      Real x, y;
+      if (!extremes[d].note_column_)
+	{
+	  y = extremes[d].neighbor_y_;
+	  if (d== RIGHT)
+	    x = extremes[d].bound_->extent (common[X_AXIS], X_AXIS)[d];
+	  else
+	    x = me->get_broken_left_end_align ();
+	}
+      else
+	{
+	  if (stem
+	      && extremes[d].stem_dir_ == dir
+	      && Stem::get_beaming (stem, -d)
+	      && columns.size () > 2
+	      )
+	    y = extremes[d].stem_extent_[Y_AXIS][dir];
+	  else if (head)
+	    y = head->extent (common[Y_AXIS], Y_AXIS)[dir];
+	  y += dir * 0.5 * staff_space;
+
+	  if (stem)
+	    {
+	      SCM scripts = stem->get_property ((dir == UP
+						 ? "script-up"
+						 : "script-down"));
+
+	      /* FIXME: number of scripts, height, priority?
+	         articulation scripts should be inside slur, other,
+	         such as dynamics, pedals, fingering, should be
+	         outside.  */
+	      if (!SCM_NULLP (scripts))
+		y += dir * staff_space;
+	    }
+
+	  Real pos
+	    = (y - extremes[d].staff_->relative_coordinate (common[Y_AXIS],
+							    Y_AXIS))
+	    * 2.0 / Staff_symbol::staff_space (extremes[d].staff_);
+
+	  /* start off staffline. */
+	  if (fabs (pos - round (pos)) < 0.2
+	      && Staff_symbol_referencer::on_staffline (head, (int) rint (pos))
+	      && Staff_symbol_referencer::line_count (head) - 1 >= rint (pos)
+	      )
+	    // TODO: calc from slur thick & line thick, parameter.	    
+	    y += 1.5 * staff_space * dir / 10;
+
+	  Grob * fh = Note_column::first_head (extremes[d].note_column_);
+	  x = fh->extent (common[X_AXIS], X_AXIS).linear_combination (CENTER);
+	}
+      base_attachment[d] = Offset (x, y);
+
+    } while (flip (&d) != LEFT);
+
+  return base_attachment;
+}
+
+void
+generate_curves (Grob *me, Grob **common,
+		 Drul_array<Bound_info> extremes,
+		 Drul_array<Offset>,
+		 Array<Slur_score> *scores)
+{
+  (void) common;
+  (void) extremes;
+  Real staff_space = Staff_symbol_referencer::staff_space ((Grob *) me);
+  Real r_0 = robust_scm2double (me->get_property ("ratio"), 0.33);
+  Real h_inf = staff_space * ly_scm2double (me->get_property ("height-limit"));
+  for (int i = 0; i < scores->size(); i++)
+    {
+      Bezier bez= get_bezier (me, (*scores)[i].attachment_, r_0, h_inf);
+      bez = avoid_staff_line (me, common, extremes, bez);
+      (*scores)[i].attachment_[LEFT] = bez.control_[0];
+      (*scores)[i].attachment_[RIGHT] = bez.control_[3];
+      (*scores)[i].curve_ = bez;
+    }
+}
+
+Bezier
+avoid_staff_line (Grob *me, Grob **common,
+		  Drul_array<Bound_info> extremes,
+		  Bezier bez)
+{
+  Offset horiz (1,0);
+  Array<Real> ts  = bez.solve_derivative (horiz);
+  Real lt =  me->get_paper ()->get_dimension (ly_symbol2scm ("linethickness"));
+  Real thick = robust_scm2double (me->get_property ("thickness"), 1.0) *  lt;
+
+  /* TODO: handle case of broken slur.  */
+  if (!ts.is_empty ()
+      && (extremes[LEFT].staff_ == extremes[RIGHT].staff_)
+      && extremes[LEFT].staff_ && extremes[RIGHT].staff_)
+    {
+      Real y = bez.curve_point (ts[0])[Y_AXIS];
+
+      Grob *staff = extremes[LEFT].staff_;
+
+      Real staff_space = extremes[LEFT].staff_space_;
+      Real p = 2 * (y - staff->relative_coordinate (common[Y_AXIS], Y_AXIS))
+	/ staff_space;
+
+      Real distance = fabs (round (p) - p);	//  in halfspaces
+      if (distance < 4 * thick
+	  && (int) fabs (round (p))
+	  <= 2 * Staff_symbol_referencer::staff_radius (staff) + 0.1
+	  && (int (fabs (round (p))) % 2
+	      != Staff_symbol_referencer::line_count (staff) % 2))
+	{
+	  Direction resolution_dir =  
+	    (distance ?  get_grob_direction (me) : Direction (sign (p - round(p))));
+
+	  // TODO: parameter
+	  Real newp = round (p) + resolution_dir
+	    * 5 * thick;
+	  
+	  Real dy = (newp - p) * staff_space / 2.0;
+#if 0
+	  bez.translate (Offset (0, dy));
+#else
+	  bez.control_[1][Y_AXIS] += dy; 
+	  bez.control_[2][Y_AXIS] += dy; 
+	  
+#endif
+	}
+    }
+  return bez;
+}
+
+Array<Slur_score>
+enumerate_attachments (Grob *me, Grob **,
+		       Slur_score_parameters *score_param,
+		       Drul_array<Bound_info> extremes,
+		       Drul_array<Offset> base_attachment,
+		       Drul_array<Real> end_ys)
+{
+  /*ugh.   */
+  Array<Slur_score> scores;
+
+  Direction dir = get_grob_direction (me);
+  Real staff_space = Staff_symbol_referencer::staff_space ((Grob *)me);
+
+  Drul_array<Offset> os;
+  os[LEFT] = base_attachment[LEFT];
+  Real minimum_length = staff_space
+    * robust_scm2double (me->get_property ("minimum-length"), 2.0);
+
+  for (int i = 0; dir * os[LEFT][Y_AXIS] <= dir * end_ys[LEFT]; i++)
+    {
+      os[RIGHT] = base_attachment[RIGHT];
+      for (int j = 0; dir * os[RIGHT][Y_AXIS] <= dir * end_ys[RIGHT]; j++)
+	{
+	  Slur_score s;
+	  Direction d = LEFT;
+	  Drul_array<bool> attach_to_stem (false, false);
+	  do {  
+	    os[d][X_AXIS] = base_attachment[d][X_AXIS];
+	    if (extremes[d].stem_
+		&& !Stem::is_invisible (extremes[d].stem_)
+		&& extremes[d].stem_dir_ == dir
+		&& dir == -d)
+	      {
+		if (extremes[d].stem_extent_[Y_AXIS].contains (os[d][Y_AXIS]))
+		  {
+		    os[d][X_AXIS] =  extremes[d].slur_head_extent_[-d]
+		      - d * 0.3;
+		    attach_to_stem[d] = true;
+		  }
+		else if (dir *extremes[d].stem_extent_[Y_AXIS][dir] < dir * os[d][Y_AXIS])
+		  {
+		    os[d][X_AXIS] = extremes[d].stem_extent_[X_AXIS].center();
+		  }
+	      }
+	  } while (flip (&d) != LEFT);
+
+	  Offset dz;	  
+	  dz = os[RIGHT] - os[LEFT];
+	  if (dz[X_AXIS] < minimum_length
+	      || fabs (dz[Y_AXIS] / dz[X_AXIS]) > score_param->MAX_SLOPE
+	      )
+	    {
+	      do
+		{
+		  if (extremes[d].slur_head_)
+		    {
+		      os[d][X_AXIS] = extremes[d].slur_head_extent_.center ();
+		      attach_to_stem[d] = false;
+		    }
+		}
+	      while (flip (&d) != LEFT);
+	    }
+
+	  dz = os[RIGHT] - os[LEFT];
+	  do {
+	    if (extremes[d].slur_head_
+		&& !attach_to_stem[d])
+	      {
+		/*
+		  horizontally move tilted slurs a little. Move more
+		  for bigger tilts.
+
+		  TODO: parameter
+		*/
+		os[d][X_AXIS] -=
+		  dir * extremes[d].slur_head_extent_.length () * sin (dz.arg  ()) / 3;
+	      }
+	  } while (flip (&d) != LEFT);
+	  
+	  s.attachment_ = os;
+	  scores.push (s);
+
+	  os[RIGHT][Y_AXIS] += dir * staff_space / 2;
+	}
+
+      os[LEFT][Y_AXIS] += dir * staff_space / 2;
+    }
+
+  return scores;
+}
+
+void
+score_encompass (Grob *me, Grob *common[],
+		 Slur_score_parameters *score_param,
+		 Drul_array<Bound_info> ,
+		 Drul_array<Offset> ,
+		 Array<Slur_score> * scores)
+{
+  Link_array<Grob> encompasses
+    = Pointer_group_interface__extract_grobs (me, (Grob *)0, "note-columns");
+  Direction dir = get_grob_direction (me);
+
+  Array<Encompass_info> infos;
+
+  for (int i = 0; i < encompasses.size(); i++)
+    infos.push (get_encompass_info (me, encompasses[i], common));
+
+  for (int i = 0; i < scores->size (); i++)
+    {
+      Bezier const &bez (scores->elem (i).curve_);
+      Real demerit = 0.0;
+      for (int j = 0; j < infos.size(); j++)
+	{
+	  Real x = infos[j].x_;
+
+	  bool l_edge = j==0;
+	  bool r_edge = j==infos.size()-1;
+	  bool edge =  l_edge || r_edge;
+  
+	  if (!(x < scores->elem (i).attachment_[RIGHT][X_AXIS]
+		&& x > scores->elem (i).attachment_[LEFT][X_AXIS]))
+	    continue;
+	
+	  Real y = bez.get_other_coordinate (X_AXIS, x);
+	  if (!edge)
+	    {
+	      Real head_dy = (y - infos[j].head_);
+	      if (dir * head_dy < 0)
+		demerit += score_param->HEAD_ENCOMPASS_PENALTY;
+	      else
+		{
+		  Real hd = (head_dy)
+		    ? (1 / fabs (head_dy) - 1 / score_param->FREE_HEAD_DISTANCE)
+		    : score_param->HEAD_ENCOMPASS_PENALTY;
+		  hd = (hd >? 0)<? score_param->HEAD_ENCOMPASS_PENALTY;
+
+		  demerit += hd;	
+		}
+	    }	  
+
+	  if (dir * (y - infos[j].stem_) < 0)
+	    {
+	      Real stem_dem =score_param->STEM_ENCOMPASS_PENALTY ; 
+	      if ((l_edge && dir == UP)
+		  || (r_edge && dir == DOWN))
+		{
+		  stem_dem /= 5;
+		}
+
+	      demerit +=  stem_dem;
+	    }
+	  else if (!edge)
+	    {
+	      Interval ext;
+	      ext.add_point (infos[j].stem_);
+	      ext.add_point (infos[j].head_);
+
+	      demerit += - score_param->CLOSENESS_FACTOR * (dir * (y - (ext[dir] + dir * score_param->FREE_HEAD_DISTANCE)) <? 0) /
+		infos.size ();
+	    }
+	}
+
+#if DEBUG_SLUR_QUANTING
+      (*scores)[i].score_card_ += to_string ("C%.2f", demerit);
+#endif
+
+      (*scores)[i].score_ += demerit;
+    }
+}
+
+void
+score_edges (Grob *me, Grob **,
+	     Slur_score_parameters * score_param,
+	     Drul_array<Bound_info> extremes,
+	     Drul_array<Offset> base_attach,
+	     Array<Slur_score> *scores)
+{
+  Direction dir = get_grob_direction (me);
+
+  for (int i = 0; i < scores->size (); i++)
+    {
+
+      Direction d = LEFT;
+      do {
+	Real y = scores->elem (i).attachment_[d][Y_AXIS];
+	Real dy = fabs (y - base_attach[d][Y_AXIS]);
+	
+	Real factor = score_param->EDGE_ATTRACTION_FACTOR;
+	Real demerit = factor * dy;
+ 	if (extremes[d].stem_
+ 	    && extremes[d].stem_dir_ == dir
+ 	    && !Stem::get_beaming (extremes[d].stem_, -d)
+ 	    )
+ 	  demerit /= 5;
+	
+	(*scores)[i].score_ += demerit;
+#if DEBUG_SLUR_QUANTING
+	(*scores)[i].score_card_ += to_string ("E%.2f", demerit);
+#endif
+      } while (flip (&d) != LEFT);
+    }
+}
+
+void
+score_slopes (Grob *me, Grob *common[],
+	      Slur_score_parameters*score_param,
+	      Drul_array<Bound_info> extremes,
+	      Drul_array<Offset> base_attach,
+	      Array<Slur_score> * scores)
+{
+  Drul_array<Real> ys;
+
+  Direction d = LEFT;
+  do {
+    if (extremes[d].slur_head_)
+      ys[d] = extremes[d].slur_head_ ->relative_coordinate (common[Y_AXIS],
+							    Y_AXIS);
+    else
+      ys[d] = extremes[d].neighbor_y_;
+  } while (flip (&d) != LEFT);
+
+  bool has_beams
+    = (extremes[LEFT].stem_ && Stem::get_beam (extremes[LEFT].stem_))
+    || (extremes[RIGHT].stem_ && Stem::get_beam (extremes[RIGHT].stem_));
+
+  Direction dir = get_grob_direction (me);
+  Real dy = ys[RIGHT] - ys[LEFT];
+  for (int i = 0; i < scores->size (); i++)
+    {
+      Offset slur_dz = (*scores)[i].attachment_[RIGHT]
+	-  (*scores)[i].attachment_[LEFT];
+      Real slur_dy = slur_dz[Y_AXIS]; 
+      Real demerit = 0.0;
+
+      demerit += ((fabs (slur_dy/slur_dz[X_AXIS])
+		   - score_param->MAX_SLOPE) >? 0)
+	* score_param->MAX_SLOPE_FACTOR;
+
+      /*
+	0.2: account for staffline offset.
+      */
+      Real max_dy = (fabs (dy) + 0.2);
+      if (has_beams)
+	max_dy += 1.0; 
+      
+      demerit += score_param->STEEPER_SLOPE_FACTOR * ((fabs (slur_dy) -max_dy) >? 0); 
+
+      
+      demerit += ((fabs (slur_dy/slur_dz[X_AXIS]) - score_param->MAX_SLOPE)>?0)  * score_param->MAX_SLOPE_FACTOR;
+      
+      if (sign (dy) == 0 &&
+	  sign (slur_dy) != 0)
+	demerit += score_param->NON_HORIZONTAL_PENALTY;
+
+      if (sign (dy)
+	  && sign (slur_dy)
+	  && sign (slur_dy) != sign (dy))
+	demerit += has_beams
+	  ? score_param->SAME_SLOPE_PENALTY / 10
+	  : score_param->SAME_SLOPE_PENALTY;
+
+#if DEBUG_SLUR_QUANTING
+      (*scores)[i].score_card_ += to_string ("S%.2f",d);
+#endif
+      (*scores)[i].score_ += demerit;
+    }
+}
+
+
diff --git a/lily/slur.cc b/lily/slur.cc
index c63cfce064..36a8a2caa9 100644
--- a/lily/slur.cc
+++ b/lily/slur.cc
@@ -1,5 +1,5 @@
 /*
-  slur.cc -- implement Slur
+  slur.cc -- implement Old_slur
 
   source file of the GNU LilyPond music typesetter
 
@@ -39,7 +39,7 @@
 
 
 void
-Slur::set_interface (Grob*me)
+Old_slur::set_interface (Grob*me)
 {
   /* Copy to mutable list. */
   me->set_property ("attachment",
@@ -47,7 +47,7 @@ Slur::set_interface (Grob*me)
 }
 
 void
-Slur::add_column (Grob*me, Grob*n)
+Old_slur::add_column (Grob*me, Grob*n)
 {
   Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-columns"), n);
   me->add_dependency (n);
@@ -56,7 +56,7 @@ Slur::add_column (Grob*me, Grob*n)
 }
 
 void
-Slur::de_uglify (Grob*me, Slur_bezier_bow* bb, Real default_height)
+Old_slur::de_uglify (Grob*me, Slur_bezier_bow* bb, Real default_height)
 {
   Real length = bb->curve_.control_[3][X_AXIS] ; 
   Real ff = bb->fit_factor ();
@@ -91,7 +91,7 @@ Slur::de_uglify (Grob*me, Slur_bezier_bow* bb, Real default_height)
 
 
 Direction
-Slur::get_default_dir (Grob*me) 
+Old_slur::get_default_dir (Grob*me) 
 {
   Link_array<Grob> encompasses =
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-columns");
@@ -109,9 +109,9 @@ Slur::get_default_dir (Grob*me)
 }
 
 
-MAKE_SCHEME_CALLBACK (Slur, after_line_breaking,1);
+MAKE_SCHEME_CALLBACK (Old_slur, after_line_breaking,1);
 SCM
-Slur::after_line_breaking (SCM smob)
+Old_slur::after_line_breaking (SCM smob)
 {
   Grob *me = unsmob_grob (smob);
   if (!scm_ilength (me->get_property ("note-columns")))
@@ -127,7 +127,7 @@ Slur::after_line_breaking (SCM smob)
 
 
 void
-Slur::check_slope (Grob *me)
+Old_slur::check_slope (Grob *me)
 {
   /*
     Avoid too steep slurs.
@@ -174,7 +174,7 @@ Slur::check_slope (Grob *me)
   Set 'attachment grob property, and return it.
 */
 SCM
-Slur::set_extremities (Grob *me)
+Old_slur::set_extremities (Grob *me)
 {
   if (!get_grob_direction (me))
     set_grob_direction (me, get_default_dir (me));
@@ -214,7 +214,7 @@ Slur::set_extremities (Grob *me)
 
 
 Real
-Slur::get_boundary_notecolumn_y (Grob *me, Direction dir)
+Old_slur::get_boundary_notecolumn_y (Grob *me, Direction dir)
 {
   SCM cols = me->get_property ("note-columns");
 
@@ -248,7 +248,7 @@ Slur::get_boundary_notecolumn_y (Grob *me, Direction dir)
 }
 
 Offset
-Slur::broken_trend_offset (Grob *me, Direction dir)
+Old_slur::broken_trend_offset (Grob *me, Direction dir)
 {
   /*
     A broken slur should maintain the same vertical trend
@@ -284,7 +284,7 @@ UGH: this routine delivers offsets which are *not* relative to COMMON.
 UGH,  we should take COMMON-Y as argument.
 */ 
 Offset
-Slur::get_attachment (Grob *me, Direction dir,
+Old_slur::get_attachment (Grob *me, Direction dir,
 		      Grob **common) 
 {
   SCM s = me->get_property ("attachment");
@@ -406,7 +406,7 @@ Slur::get_attachment (Grob *me, Direction dir,
 }
 
 Offset
-Slur::encompass_offset (Grob*me,
+Old_slur::encompass_offset (Grob*me,
 			Grob* col,
 			Grob **common) 
 {
@@ -454,7 +454,7 @@ Slur::encompass_offset (Grob*me,
 }
 
 Array<Offset>
-Slur::get_encompass_offsets (Grob *me)
+Old_slur::get_encompass_offsets (Grob *me)
 {
   Spanner*sp = dynamic_cast<Spanner*> (me);
   SCM eltlist = me->get_property ("note-columns");
@@ -520,9 +520,9 @@ Slur::get_encompass_offsets (Grob *me)
 /*
   ugh ?
  */
-MAKE_SCHEME_CALLBACK (Slur, height, 2);
+MAKE_SCHEME_CALLBACK (Old_slur, height, 2);
 SCM
-Slur::height (SCM smob, SCM ax)
+Old_slur::height (SCM smob, SCM ax)
 {
   Axis a = (Axis)ly_scm2int (ax);
   Grob * me = unsmob_grob (smob);
@@ -538,9 +538,9 @@ Slur::height (SCM smob, SCM ax)
 /*
   Ugh should have dash-length + dash-period
  */
-MAKE_SCHEME_CALLBACK (Slur, print,1);
+MAKE_SCHEME_CALLBACK (Old_slur, print,1);
 SCM
-Slur::print (SCM smob)
+Old_slur::print (SCM smob)
 {
   Grob * me = unsmob_grob (smob);
   if (!scm_ilength (me->get_property ("note-columns")))
@@ -575,7 +575,7 @@ Slur::print (SCM smob)
 }
 
 void
-Slur::set_control_points (Grob*me)
+Old_slur::set_control_points (Grob*me)
 {
   Real staff_space = Staff_symbol_referencer::staff_space ((Grob*)me);
 
@@ -644,7 +644,7 @@ Slur::set_control_points (Grob*me)
 }
   
 Bezier
-Slur::get_curve (Grob*me) 
+Old_slur::get_curve (Grob*me) 
 {
   Bezier b;
   int i = 0;
@@ -695,7 +695,7 @@ Slur::get_curve (Grob*me)
 
 
 
-ADD_INTERFACE (Slur,"slur-interface",
+ADD_INTERFACE (Old_slur,"slur-interface",
   "A slur",
   "attachment attachment-offset beautiful control-points dashed details de-uglify-parameters direction extremity-function extremity-offset-alist height-limit note-columns ratio slope-limit thickness y-free quant-score");
 
diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm
index 2cdda26f88..8323f77c68 100644
--- a/scm/define-grobs.scm
+++ b/scm/define-grobs.scm
@@ -704,26 +704,14 @@
 
     (PhrasingSlur
      . (
-	(print-function . ,Slur::print)
+	(print-function . ,New_slur::print)
 	(thickness . 1.2)		
 	(spacing-procedure . ,Spanner::set_spacing_rods)		
 	(minimum-length . 1.5)
-	(after-line-breaking-callback . ,Slur::after_line_breaking)
-	(extremity-function . ,calc-slur-extremity)
-	(extremity-offset-alist . ,default-phrasing-slur-extremity-offset-alist)
-	(de-uglify-parameters . (1.5  0.8  -2.0))
-	(Y-extent-callback . ,Slur::height)
+	(after-line-breaking-callback . ,New_slur::after_line_breaking)
+	(Y-extent-callback . ,New_slur::height)
 	(height-limit . 2.0)
 	(ratio . 0.333)
-	(beautiful . 0.5)
-	(y-free . 0.75)
-	(attachment . (#f . #f))
-	(attachment-offset . ((0 . 0) . (0 . 0)))
-	(slope-limit . 0.8)
-	(details . ((force-blowfit . 0.5)
-		    (bezier-pct-c0 . -0.2) (bezier-pct-c3 . 0.000006)
-		    (bezier-pct-out-max . 0.8) (bezier-pct-in-max . 1.2)
-		    (bezier-area-steps . 1.0)))
 	(meta . ((interfaces . (slur-interface spanner-interface))))
 	))
 
@@ -829,30 +817,14 @@
     (Slur
      . (
 	(print-function . ,New_slur::print)
-	; ,Slur::print)
 	(thickness . 1.2)		
 	(spacing-procedure . ,Spanner::set_spacing_rods)		
 	(minimum-length . 1.5)
-	(after-line-breaking-callback .
-				      ,New_slur::after_line_breaking)
-		;		      ,Slur::after_line_breaking)
-	(extremity-function . ,calc-slur-extremity)
-	(extremity-offset-alist . ,default-slur-extremity-offset-alist)
-	(de-uglify-parameters . (1.5  0.8  -2.0))
-	(Y-extent-callback .
-			   ,New_slur::height)
+	(after-line-breaking-callback . ,New_slur::after_line_breaking)
+	(Y-extent-callback . ,New_slur::height)
 					; Slur::height)
 	(height-limit . 2.0)
 	(ratio . 0.25)
-	(beautiful . 0.5)
-	(y-free . 0.75)
-	(attachment . (#f . #f))
-	(attachment-offset . ((0 . 0) . (0 . 0)))
-	(slope-limit . 0.8)
-	(details . ((force-blowfit . 0.5)
-		    (bezier-pct-c0 . -0.2) (bezier-pct-c3 . 0.000006)
-		    (bezier-pct-out-max . 0.8) (bezier-pct-in-max . 1.2)
-		    (bezier-area-steps . 1.0)))
 	(meta . ((interfaces . (slur-interface spanner-interface))))
 	))
 
-- 
2.39.5