]> git.donarmstrong.com Git - lilypond.git/commitdiff
(class New_slur): new file. Score based slur
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Sun, 11 Jul 2004 02:09:07 +0000 (02:09 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Sun, 11 Jul 2004 02:09:07 +0000 (02:09 +0000)
computations.

ChangeLog
SConstruct
buildscripts/builder.py
input/SConscript
input/test/new-slur.ly [new file with mode: 0644]
lily/bezier.cc
lily/include/slur.hh
lily/new-slur.cc [new file with mode: 0644]
lily/slur.cc
lily/staff-symbol-referencer.cc

index 3ddfcbd5df9f93c71465e3e1ecf72533f87e6a74..cb6334504537c87dc1ebc4b66b92963938b3d4f5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2004-07-11  Han-Wen Nienhuys   <hanwen@xs4all.nl>
+
+       * lily/new-slur.cc (class New_slur): new file. Score based slur
+       computations.
+
 2004-07-10  Jan Nieuwenhuizen  <janneke@gnu.org>
 
        * mf/SConscript: Remove Builders.
index 1a3e000eaf5fe51005aa38b07af4df1fb812cbad..e9adef066be734a61c1386463bfdbad3f8f05cb7 100644 (file)
@@ -185,7 +185,6 @@ command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (
 PYTHON_INCLUDE = os.popen (command).read ()
 env.Append (CPPPATH = PYTHON_INCLUDE)
 
-
 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
 for i in headers:
        if conf.CheckCHeader (i):
@@ -352,7 +351,15 @@ env['MAKEINFO_PATH'] = ['.', '#/Documentation/user',
 
 ## TEXINFO_PAPERSIZE_OPTION= $(if $(findstring $(PAPERSIZE),a4),,-t @afourpaper)
 env['TEXINFO_PAPERSIZE_OPTION'] = '-t @afourpaper'
-
+#FIXME: ./python isn't sconsed yet, add scrdir/python for lilylib.py ...
+env.Append (PYTHONPATH = [os.path.join (outdir, 'usr/lib/python'),
+                         os.path.join (srcdir, 'buildscripts'),
+                         os.path.join (srcdir, 'python')])
+# huh, aha?
+env.Append (ENV = { 'PYTHONPATH' : string.join (env['PYTHONPATH'],
+                                               os.pathsep) } )
+
+# GS_FONTPATH, GS_LIB?
 SConscript ('buildscripts/builder.py')
 
 #subdirs = ['mf',]
index 62cc9185eaeed006dfe234855a973c7c964a716b..abd8ecd276184542fdafd4b964dc331478bbf9ed 100644 (file)
@@ -90,8 +90,8 @@ def add_ps_target (target, source, env):
 
 a = ('LILYPONDPREFIX=%(LILYPONDPREFIX)s '\
      + '%(PYTHON)s %(LILYPOND_PY)s%(verbose)s'\
-     + ' --include=$$(dirname $TARGET)'\
-     + ' --output=$$(dirname $TARGET)'\
+     + ' --include=${TARGET.dir}'\
+     + ' --output=${TARGET.base}'\
      + ' $SOURCE') % vars ()
 lilypond = Builder (action = a, suffix = '.pdf', src_suffix = '.ly')
 ##                 emitter = add_ps_target)
@@ -101,7 +101,7 @@ verbose = verbose_opt (env, ' --verbose')
 a = ('LILYPONDPREFIX=%(LILYPONDPREFIX)s '\
      + '%(PYTHON)s %(ABC2LY_PY)s%(verbose)s'\
      + ' --include=$$(dirname $TARGET)'\
-     + ' --output=$$(dirname $TARGET)'\
+     + ' --output=$$(dirname $TARGET)/$$(basename $TARGET .ly)'\
      + ' $SOURCE') % vars ()
 abc2ly = Builder (action = a, suffix = '.ly', src_suffix = '.abc')
 env.Append (BUILDERS = {'Abc2ly': abc2ly})
index 6df0a1a43b2cfc7ee2e8ee4eea9a7957eca2fe61..f184f96a2ce6fad432fbf02d0ea34ba8d0fd847b 100644 (file)
@@ -25,15 +25,12 @@ pdfs = pdfs + map (e.LilyPond, lys)
 
 LILYPOND_BIN = env['LILYPOND_BIN']
 
-#e.Depends (pdfs, LILYPOND_BIN)
-# e.Depends (pdfs, 'lilypond-internals.texi')
-
 mfbuild = os.path.join (env['absbuild'], 'mf', env['out'])
 e.Depends ('doc', mfbuild)
 e.Depends ('doc', LILYPOND_BIN)
-#e.Depends (doc, 'lilypond-internals.texi')
 
 e.Alias ('doc', pdfs)
+#e.Alias ('doc', 'example-1.pdf')
 
 #testing
 all_sources = ['SConscript',] + sources + abc_sources
diff --git a/input/test/new-slur.ly b/input/test/new-slur.ly
new file mode 100644 (file)
index 0000000..b408a86
--- /dev/null
@@ -0,0 +1,16 @@
+
+
+\relative {
+
+    \override Slur #'after-line-breaking-callback = #New_slur::after_line_breaking
+   \override Slur #'print-function = #New_slur::print     
+    \override Slur #'height = ##f
+    <c g> ( f <g b>)
+     f
+    <c g>^( f <g b>)
+    f
+    <c g>_( f <g b>)
+    <g b>_( g  <b d>)
+    <g b>_( \stemDown g \stemBoth  <b d>)
+    
+}
index b20de964a7642baf09838669184107a997642ca5..85208ade0708f9347d78a67c124f71dfe2d21fee 100644 (file)
@@ -59,6 +59,9 @@ translate (Array<Offset>* array, Offset o)
   Formula of the bezier 3-spline
 
   sum_{j=0}^3 (3 over j) z_j (1-t)^ (3-j)  t^j
+
+
+  A is the axis of X coordinate.
  */
 
 Real
index 476b960b92c19327f966542e2a9bd9ff3443e356..166c9f16317c7e8a929f697e3cf07cd316f7df52 100644 (file)
@@ -28,7 +28,7 @@ private:
   static Real get_boundary_notecolumn_y (Grob *me, Direction dir);
   static Offset broken_trend_offset (Grob *me, Direction dir);
   static Offset get_attachment (Grob *me,Direction dir, Grob **common);
-  static void de_uglyfy (Grob *me,Slur_bezier_bow* bb, Real default_height);
+  static void de_uglify (Grob *me,Slur_bezier_bow* bb, Real default_height);
   static SCM set_extremities (Grob *me);
   static void set_control_points (Grob *me);
   static void check_slope (Grob *me);
diff --git a/lily/new-slur.cc b/lily/new-slur.cc
new file mode 100644 (file)
index 0000000..37f2412
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+  slur.cc -- implement 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 "group-interface.hh"
+#include "lily-guile.hh"
+#include "lily-proto.hh"
+#include "lookup.hh"
+#include "main.hh"
+#include "note-column.hh"
+#include "output-def.hh"
+#include "paper-column.hh"
+#include "rod.hh"
+#include "slur-bezier-bow.hh"
+#include "slur.hh"
+#include "spanner.hh"
+#include "staff-symbol-referencer.hh"
+#include "stem.hh"
+#include "stencil.hh"
+#include "warn.hh"
+
+struct Encompass_info {
+  Real x_;
+  Real stem_;
+  Real head_;
+  Encompass_info ()
+  {
+    x_ = 0.0;
+    stem_ = 0.0;
+    head_ = 0.0;
+  }
+};
+
+/*
+  TODO: put in details list.
+  */
+const int SLUR_REGION_SIZE = 5;
+const Real HEAD_ENCOMPASS_PENALTY = 1000.0;
+const Real STEM_ENCOMPASS_PENALTY = 30.0;
+const Real CLOSENESS_FACTOR = 10;
+const Real EDGE_ATTRACTION_FACTOR = 4; 
+const Real HEAD_FREE_SPACE = 0.3;
+const Real SAME_SLOPE_PENALTY = 20;
+const Real STEEPER_SLOPE_FACTOR = 50;
+const Real NON_HORIZONTAL_PENALTY = 15;
+const Real HEAD_STRICT_FREE_SPACE = 0.2;
+
+#define DEBUG_SLUR_QUANTING 1
+
+struct Slur_score {
+  Drul_array<Offset> attachment_;
+  Real  score_;
+#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[], Drul_array<Offset> base_attach,
+                           Array<Slur_score> * scores);
+  
+  static  void score_encompass (Grob * me,  Grob *common[],
+                               Drul_array<Offset>, Array<Slur_score> * scores);
+  static void set_interface (Grob*);
+  static bool  has_interface (Grob*);
+  static Array<Offset> get_encompass_offsets (Grob *me);
+  static Bezier get_curve (Grob *me);
+  static Bezier get_bezier (Grob *me, Drul_array<Offset>);
+  static Direction get_default_dir (Grob *me);
+  DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM));
+  DECLARE_SCHEME_CALLBACK (height, (SCM,SCM));
+private:
+  static void set_end_points (Grob*);
+  static Real get_boundary_notecolumn_y (Grob *me, Direction dir);
+  static Offset broken_trend_offset (Grob *me, Direction dir);
+  static Offset get_attachment (Grob *me,Direction dir, Grob **common);
+  static void de_uglyfy (Grob *me,Slur_bezier_bow* bb, Real default_height);
+  static SCM set_extremities (Grob *me);
+  static void set_control_points (Grob *me);
+  static void check_slope (Grob *me);
+  static Encompass_info get_encompass_info (Grob *me, Grob *col, Grob **common);
+};
+
+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->relative_coordinate (common[Y_AXIS], Y_AXIS);
+      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 ();
+
+  ei.head_ = Stem::extremal_heads (stem)[Direction (stem_dir * dir)]->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];
+    }
+  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));
+
+  
+  if (!Note_column::has_interface (me->get_bound (LEFT))
+      || !Note_column::has_interface (me->get_bound (RIGHT)))
+    me->suicide ();            // fixme.
+  
+  set_end_points (me);
+
+  return SCM_UNSPECIFIED;
+}
+
+Bezier
+New_slur::get_bezier (Grob *me,  Drul_array<Offset> extremes)
+{
+  //  SCM details = me->get_property ("details");
+  SCM h_inf_scm = me->get_property ("height-limit");
+  SCM r_0_scm = me->get_property ("ratio");
+  Real staff_space = Staff_symbol_referencer::staff_space ((Grob*)me);
+
+  Real r_0 = robust_scm2double (r_0_scm, 1);
+  Real h_inf = staff_space * ly_scm2double (h_inf_scm);
+
+  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 ();
+}
+
+void
+New_slur::set_end_points (Grob *me)
+{
+  Link_array<Grob> columns =
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-columns");
+  
+
+  Real staff_space = Staff_symbol_referencer::staff_space ((Grob*)me);
+  Drul_array<Grob *> extremes (columns[0], columns.top ());
+  Direction dir = get_grob_direction (me);
+  
+  Drul_array<Offset> base_attachment;
+
+  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);
+
+  Direction d = LEFT;
+  Drul_array<Grob*> staves;
+  
+  do {
+    Grob *stem = Note_column::get_stem (extremes[d]);
+    Direction stemdir = get_grob_direction (stem);
+    Grob * h = Stem::extremal_heads (stem)[Direction (dir * stemdir)];
+    staves[d] = Staff_symbol_referencer::get_staff_symbol (h);
+
+    common[Y_AXIS] = common[Y_AXIS]->common_refpoint (staves[d], Y_AXIS);
+  } while (flip (&d) != LEFT);
+  
+  do
+    {
+      // c&p
+      Grob *stem = Note_column::get_stem (extremes[d]);
+      Direction stemdir = get_grob_direction (stem);
+      Grob * h = Stem::extremal_heads (stem)[Direction (dir * stemdir)];
+     
+      Real y = h->extent (common[Y_AXIS], Y_AXIS)[dir];
+
+      y += dir * 0.5 * staff_space;
+      if (Staff_symbol_referencer::on_staffline (h))
+       y += .5 * staff_space * dir ; 
+
+      Grob * fh = Note_column::first_head (extremes[d]);
+      Real x = fh->extent (common[X_AXIS],  X_AXIS).linear_combination (CENTER);
+
+      if (get_grob_direction (stem) == dir
+         && dir == -d)
+       {
+         x -=  d * fh->extent(fh, X_AXIS).length ();
+       }
+    
+      base_attachment[d] = Offset (x, y);
+
+    } while (flip (&d) != LEFT);
+
+  Drul_array<Real> staff_offsets;
+  do {
+    staff_offsets[d] = staves[d]->relative_coordinate (common[Y_AXIS], Y_AXIS);
+  } while (flip (&d) != LEFT);
+  
+  Array<Slur_score> scores;
+  
+  Drul_array<Offset> os;
+
+  /*ugh.   */
+  os[LEFT] = base_attachment[LEFT]; 
+  for (int i = 0; i < SLUR_REGION_SIZE; i++)
+    {
+      os[RIGHT] = base_attachment[RIGHT];
+      for (int j = 0; j < SLUR_REGION_SIZE; j++)
+       {
+         Slur_score s;
+         s.attachment_ = os;
+
+         scores.push (s);
+
+         Real y  = os[RIGHT][Y_AXIS]; 
+         
+         if (Staff_symbol_referencer::staff_radius (staves[RIGHT])
+             > fabs ((y - staff_offsets[RIGHT]) / staff_space))
+           y += dir *staff_space;
+         else
+           y += dir * staff_space / 2;
+
+         os[RIGHT][Y_AXIS] = y;          
+       }
+
+      Real y  = os[LEFT][Y_AXIS]; 
+
+      if (Staff_symbol_referencer::staff_radius (staves[LEFT])
+         > fabs ((y - staff_offsets[LEFT]) / staff_space))
+       y += dir *staff_space;
+      else
+       y += dir *staff_space / 2;
+
+      os[LEFT][Y_AXIS] = y;      
+    }
+  
+
+  score_encompass (me, common, base_attachment, &scores);
+  score_slopes (me, common, base_attachment, &scores);
+
+  Real opt = 1e6;
+  int opt_idx = -1;
+  for (int i = scores.size (); i--;)
+    {
+      if (scores[i].score_  < opt)
+       {
+         opt = scores[i].score_;
+         opt_idx = i;
+       }
+    }
+  
+  Bezier b (get_bezier (me, scores[opt_idx].attachment_));
+  
+  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);
+
+#if DEBUG_SLUR_QUANTING
+      qscores[opt_idx].score_card_ += to_string ("i%d", best_idx);
+      
+      // debug quanting
+      me->set_property ("quant-score",
+                       scm_makfrom0str (scores[opt_idx].score_card_.to_str0 ()));
+#endif
+  
+}
+
+void
+New_slur::score_encompass (Grob * me,  Grob *common[], Drul_array<Offset> base_attach,
+                          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;
+
+  int first = 1;
+  int last = encompasses.size () - 2;
+
+  for (int i = first; i <= last; i++)
+    infos.push (get_encompass_info (me, encompasses[i], common));
+  
+  for (int i =0 ; i < scores->size (); i++)
+    {
+      Bezier bez (get_bezier (me, scores->elem (i).attachment_));
+      Real demerit =0.;
+      for (int j = 0; j < infos.size(); j++)
+       {
+         Real x = infos[j].x_;
+
+         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 (dir * (y - infos[j].head_) < 0)
+           demerit += HEAD_ENCOMPASS_PENALTY;
+         
+         if (dir * (y - infos[j].stem_) < 0)
+           demerit += STEM_ENCOMPASS_PENALTY;
+         else
+           {
+             Interval ext;
+             ext.add_point (infos[j].stem_);
+             ext.add_point (infos[j].head_);
+
+             demerit += - CLOSENESS_FACTOR * (dir * (y - (ext[dir] + dir * HEAD_FREE_SPACE)) <? 0) ;
+           }
+       }
+
+      demerit /= infos.size ();
+      Direction d = LEFT;
+      do {
+       demerit +=
+         EDGE_ATTRACTION_FACTOR
+         * fabs (scores->elem (i).attachment_[d][Y_AXIS] - base_attach[d][Y_AXIS]);
+      } while (flip (&d) != LEFT);
+
+#if DEBUG_SLUR_QUANTING
+      (*qscores)[i].score_card_ += to_string ("E%.2f",d);
+#endif
+      
+      (*scores)[i].score_ += demerit;
+    }
+}
+
+
+void
+New_slur::score_slopes (Grob * me,  Grob *common[], Drul_array<Offset> base_attach,
+                       Array<Slur_score> * scores)
+{
+ Link_array<Grob> columns =
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-columns");
+  
+
+  Drul_array<Grob *> extremes (columns[0], columns.top ());
+  Direction dir = get_grob_direction (me);
+  Drul_array<Real> ys;
+
+  Direction d = LEFT;
+  do {
+    Grob *stem = Note_column::get_stem (extremes [d]);
+    Direction sd = get_grob_direction (stem);
+    ys[d] = Stem::extremal_heads (stem)[Direction (dir * sd)]
+      ->relative_coordinate (common[Y_AXIS], Y_AXIS);
+  } while (flip (&d) != LEFT);
+
+
+  Real dy = ys[RIGHT] - ys[LEFT];
+
+  for (int i =0 ; i < scores->size (); i++)
+    {
+      Real slur_dy = (*scores)[i].attachment_[RIGHT][Y_AXIS]
+       -  (*scores)[i].attachment_[LEFT][Y_AXIS];
+
+      Real demerit = 0.0;
+
+      demerit += STEEPER_SLOPE_FACTOR *  (dir * (slur_dy - dy) >? 0);
+      if (sign (dy) == 0 &&
+         sign (slur_dy) != 0)
+       demerit += NON_HORIZONTAL_PENALTY;
+      if (sign (dy)
+         && sign (slur_dy)
+         && sign (slur_dy) != sign (dy))
+       demerit += SAME_SLOPE_PENALTY;
+      
+#if DEBUG_SLUR_QUANTING
+      (*qscores)[i].score_card_ += to_string ("E%.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;
+}
+
+
+
+
+
+
+/*
+  ugh ?
+ */
+MAKE_SCHEME_CALLBACK (New_slur, height, 2);
+SCM
+New_slur::height (SCM smob, SCM ax)
+{
+  Axis a = (Axis)ly_scm2int (ax);
+  Grob * me = unsmob_grob (smob);
+  assert (a == Y_AXIS);
+
+  SCM mol = me->get_uncached_stencil ();
+  Interval ext;
+  if (Stencil * m = unsmob_stencil (mol))
+    ext = m->extent (a);
+  return ly_interval2scm (ext);
+}
+
+/*
+  Ugh should have dash-length + dash-period
+ */
+MAKE_SCHEME_CALLBACK (New_slur, print,1);
+SCM
+New_slur::print (SCM smob)
+{
+  Grob * me = unsmob_grob (smob);
+  if (!scm_ilength (me->get_property ("note-columns")))
+    {
+      me->suicide ();
+      return SCM_EOL;
+    }
+
+  Real base_thick = robust_scm2double (me->get_property ("thickness"), 1);
+  Real thick = base_thick * Staff_symbol_referencer::line_thickness (me);
+
+  Real ss = Staff_symbol_referencer::staff_space (me);
+  Bezier one = get_curve (me);
+
+  // get_curve may suicide
+  if (!scm_ilength (me->get_property ("note-columns")))
+    return SCM_EOL;
+
+  Stencil a;
+
+  /*
+    TODO: replace dashed with generic property.
+   */
+  SCM d =  me->get_property ("dashed");
+  if (ly_c_number_p (d))
+    a = Lookup::dashed_slur (one, thick, thick * robust_scm2double (d, 0));
+  else
+    a = Lookup::slur (one, get_grob_direction (me) * base_thick * ss / 10.0,
+                     thick);
+
+#if DEBUG_SLUR_QUANTING
+  SCM quant_score = me->get_property ("quant-score");
+  if (// debug_beam_quanting_flag      &&
+      ly_c_string_p (quant_score))
+    {
+      String str;
+      SCM properties = Font_interface::text_font_alist_chain (me);
+
+      Direction stem_dir = stems.size() ? to_dir (stems[0]->get_property ("direction")) : UP;
+    
+      Stencil tm = *unsmob_stencil (Text_item::interpret_markup
+        (me->get_paper ()->self_scm (), properties, quant_score));
+      a.add_at_edge (Y_AXIS, get_grob_direction (me), tm, 1.0, 0);
+    }
+#endif
+  
+  return a.smobbed_copy ();
+}
+
+
+
+
+
+ADD_INTERFACE (New_slur, "new-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");
index 0363945cc408a3658919dd05423a52cdc2358a7f..baaa56ec29d327861daff0ed376b97b6a54fdb48 100644 (file)
@@ -56,7 +56,7 @@ Slur::add_column (Grob*me, Grob*n)
 }
 
 void
-Slur::de_uglyfy (Grob*me, Slur_bezier_bow* bb, Real default_height)
+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 ();
@@ -619,7 +619,7 @@ Slur::set_control_points (Grob*me)
        Slurs that fit beautifully are not ugly
       */
       if (area > beautiful)
-       de_uglyfy (me, &bb, default_height);
+       de_uglify (me, &bb, default_height);
     }
 
   Bezier b = bb.get_bezier ();
index 4ef9fbe9be622197a5e14afb50b04788d8543193..e3070ff53d7373373b5505d095e4afef2b27e6e7 100644 (file)
@@ -37,6 +37,9 @@ Staff_symbol_referencer::on_staffline (Grob *me, int pos)
 Grob*
 Staff_symbol_referencer::get_staff_symbol (Grob *me)
 {
+  if (Staff_symbol::has_interface (me))
+    return me;
+  
   SCM st = me->get_property ("staff-symbol");
   return unsmob_grob (st);
 }