]> git.donarmstrong.com Git - lilypond.git/commitdiff
lilypond-1.3.29
authorfred <fred>
Tue, 26 Mar 2002 22:46:23 +0000 (22:46 +0000)
committerfred <fred>
Tue, 26 Mar 2002 22:46:23 +0000 (22:46 +0000)
14 files changed:
lily/atom.cc
lily/bezier-bow.cc
lily/bezier.cc
lily/include/bezier-bow.hh
lily/include/bezier.hh
lily/include/lily-guile.hh
lily/include/slur.hh
lily/lily-guile.cc
lily/lookup.cc
lily/molecule.cc
lily/paper-outputter.cc
lily/slur.cc
lily/tie.cc
scm/paper.scm

index 9dd82bc754f88893320db90a009ea5253fb0f57a..f44d4d2c4e475cb876dbc6ea67fb5404900a9b8e 100644 (file)
@@ -29,7 +29,7 @@ SCM
 translate_atom (Offset o, SCM func)
 {
   return gh_list (ly_symbol2scm ("translate-atom"),
-                 ly_quote_scm (ly_offset2scm (o)),
+                 ly_quote_scm (to_scm (o)),
                  func,
                  SCM_UNDEFINED);
 }
@@ -41,7 +41,7 @@ translate_atom_axis (Real r, Axis a, SCM func)
   Offset o ;
   o[a] = r;
   return gh_list (ly_symbol2scm ("translate-atom"),
-                 ly_quote_scm (ly_offset2scm (o)),
+                 ly_quote_scm (to_scm (o)),
                  func,
                  SCM_UNDEFINED);
 }
index 3565cddb31e60d7a46d058411da3fcc40f75a07e..0a51f936140fb643ee0d87c1b183d0f07b220ca3 100644 (file)
 #include "debug.hh"
 #include "main.hh"
 #include "lily-guile.hh"
-
-void
-flipy (Array<Offset>  &c)
-{
-  for (int i = c.size (); i--;)
-    c[i][Y_AXIS] = - c[i][Y_AXIS];
-}
-
-void
-rotate (Array<Offset> &c, Real phi)
-{
-  Offset rot (complex_exp (Offset (0, phi)));
-  for (int i = 0; i < c.size (); i++)
-    c[i] = complex_multiply (rot, c[i]);
-}
-
-void
-translate (Array<Offset> &c, Offset o)
-{
-  for (int i = 0; i < c.size (); i++)
-    c[i] += o;
-}
+#include "paper-def.hh"
 
 
-Bezier_bow::Bezier_bow (Array<Offset> points, Direction dir)
+Bezier_bow::Bezier_bow (Array<Offset> encompass, Direction dir)
 {
+  alpha_ = 0;
   dir_ = dir;
-  encompass_ = points;
-  to_canonic_form ();
-
-  rc_factor_ = 1.0;
-  height_limit_ = 1.0;
-  ratio_ = 1.0;
-}
-
-static Real
-default_height (Real len)
-{
-  // assume 20pt staff
-  // see fonts.doc
-  Real staff_space = 5.0;
-  Real h_inf = 2.0* staff_space;
-  Real r_0 = 0.33;
-  return h_inf * 2.0 / M_PI * atan ( M_PI * r_0 / (2.0 * h_inf) * len);
-}
-
-void
-Bezier_bow::blow_fit ()
-{
-  Real len = curve_.control_[3][X_AXIS]; 
-  Real h = curve_.control_[1][Y_AXIS] * fit_factor () / len;
-  curve_.control_[1][Y_AXIS] = h * len;
-  curve_.control_[2][Y_AXIS] = h * len;  
-  curve_.check_sanity ();
-}
-
-void
-Bezier_bow::de_uglyfy ()
-{
-  Real len = curve_.control_[3][X_AXIS] ; 
-  Real ff = fit_factor ();
-  for (int i = 1; i < 3; i++)
-    {
-      Real ind = abs (curve_.control_[(i-1)*3][X_AXIS]
-                     - curve_.control_[i][X_AXIS]) / len;
-      Real h = curve_.control_[i][Y_AXIS] * ff / len;
-
-      // ugh. Unhardcode this
-#if 0
-      // Too crude.
-      if (h > 4 * ind)
-       {
-         h = 4* ind; 
-       }
-#else
-      Real f = default_height (len) / len;
-      if (h > 2.0 * f)
-       {
-         h = 2.0 * f; 
-       }
-#endif
-      
-      if (h > 0.8 + -2 * ind)
-       {
-         h = 0.8 - 2  *ind; 
-       }
-      
-      curve_.control_[i][Y_AXIS] = h * len;  
-    } 
-
-  curve_.check_sanity ();
-}
-
-Real
-Bezier_bow::calc_enclosed_area_f () const
-{
-  Real a = 0;
-  for (int i=0; i < encompass_.size (); i++)
-    {
-      Interval x;
-      Interval y;
-      if (i == 0)
-       {
-         x = Interval (0, encompass_[1][X_AXIS] / 2);
-         y = Interval (0,
-                       curve_.get_other_coordinate (X_AXIS,
-                                                    encompass_[1][X_AXIS]
-                                                    / 2));
-       }
-      else if (i == encompass_.size () - 1)
-       {
-         x = Interval ((encompass_[i-1][X_AXIS] + encompass_[i][X_AXIS])/2, 
-                       encompass_[i][X_AXIS]);
-         y = Interval (0,
-                       (curve_.get_other_coordinate (X_AXIS,
-                                                     (x[MIN] + x[MAX]) / 2)));
-       }
-      else
-       {
-         x = Interval ((encompass_[i-1][X_AXIS] + encompass_[i][X_AXIS]) / 2, 
-                       (encompass_[i][X_AXIS] + encompass_[i+1][X_AXIS]) / 2);
-         y = Interval (encompass_[i][Y_AXIS],
-                       (curve_.get_other_coordinate (X_AXIS, x[MIN])
-                        + curve_.get_other_coordinate (X_AXIS,
-                                                       (x[MIN] + x[MAX]) / 2)
-                        + curve_.get_other_coordinate (X_AXIS, x[MAX])) / 3);
-       }
-      
-      Real da = x.length () * y.length ();
-      a += da;
-    }
-  return a;
-}
-
-Array<Offset>
-Bezier_bow::area_gradient_offset_arr ()
-{
-  Real len = curve_.control_[3][X_AXIS]; 
-  Real area = calc_enclosed_area_f ();
-  
-  Real grow = len / 10.0;
-  Array<Offset> da (2);
-  for (int i=1; i < 3; i++)
-    {
-      for (Axis a=X_AXIS; a < NO_AXES; incr (a)) 
-       {
-         Real r = curve_.control_[i][a];
-         curve_.control_[i][a] += grow;
-         da[i-1][a] = (calc_enclosed_area_f () - area) / grow;
-         
-         curve_.control_[i][a] = r;
-       }
-    }
-  return da;
-}
-
-void
-Bezier_bow::minimise_enclosed_area ()
-{
-  Real len = curve_.control_[3][X_AXIS]; 
-  Real beautiful = len * default_height (len) / 2.0;
-
-  DEBUG_OUT << to_str ("Beautiful: %f\n", beautiful);
-  DEBUG_OUT << to_str ("Length: %f\n", len);
-  int steps=2;
-  for (int i=0; i < steps; i++)
-    {
-      Real ff = fit_factor ();
-      if (!ff)
-       break;
-
-      DEBUG_OUT << to_str ("FitFac: %f\n", ff);
-
-      // slur must be higher at every point
-      if (ff > 1.01)
-       {
-         blow_fit ();
-         DEBUG_OUT << to_str ("Blown area: %f\n", calc_enclosed_area_f ());
-       }
-      else
-         DEBUG_OUT << to_str ("Init area: %f\n", calc_enclosed_area_f ());
-
-      Real area = calc_enclosed_area_f ();
-      
-
-      if (area <= beautiful)
-       break;
-
-      Array<Offset> da = area_gradient_offset_arr ();
-
-      /*
-       Urg: empiric cs
-            Small slurs are easily too asymmetric,
-            while big slurs are too symmetric
-
-            This makes short slurs strictly x-bound,
-            long slurs become y-bound.
-       */
-      Real ypct = 0.50;
-      //Real xpct = (0.07 * len * len / 1000.0) <? 0.80;
-      Real xpct = (0.1 * len * len * len / 100000.0) <? 0.80;
-
-      Real yu = (abs (curve_.control_[1][Y_AXIS] / da[0][Y_AXIS])
-                <? abs (curve_.control_[2][Y_AXIS] / da[1][Y_AXIS]))
-       * ypct;
-      Real xu = (abs (curve_.control_[1][X_AXIS] / da[0][X_AXIS])
-                <? abs ((curve_.control_[3][X_AXIS]
-                            - curve_.control_[2][X_AXIS]) / da[1][X_AXIS]))
-       * xpct;
-      Real u = yu <? xu;
-      DEBUG_OUT << to_str ("u (xu, yu): %f (%f, %f)\n", u, xu, yu);
-      DEBUG_OUT << to_str ("pct (x, y): (%f, %f)\n", xpct, ypct);
-
-      DEBUG_OUT << to_str ("da1: (%f, %f)\n", da[0][X_AXIS], da[0][Y_AXIS]);
-      DEBUG_OUT << to_str ("da2: (%f, %f)\n", da[1][X_AXIS], da[1][Y_AXIS]);
-
-      curve_.control_[1] -= da[0] * u;
-      curve_.control_[2] -= da[1] * u;
-    }
-  
-
-  if (fit_factor () > 1.5)
-    blow_fit ();
-
-  DEBUG_OUT << to_str ("Exarea: %f\n", calc_enclosed_area_f ());
-  Real area = calc_enclosed_area_f ();
-  /*
-    Slurs that fit beautifully are not ugly
-   */
-  if (area > beautiful)
-    {
-      DEBUG_OUT << "DE-UGLYFY\n";
-      de_uglyfy ();
-    }
-
-}
-
-void
-Bezier_bow::calculate ()
-{
-  calc_default ();
-  if (fit_factor () > 1.0)
-    {
-      //    calc_tangent_controls ();
-      // blow_fit ();
-      minimise_enclosed_area ();
-    }
+  encompass_ = encompass;
+  to_canonical_form ();
 }
 
-
-  
 Bezier
-Bezier_bow::get_curve ()const
+Bezier_bow::get_bezier () const
 {
   Bezier rv = curve_;
   if (dir_ == DOWN)
@@ -281,191 +41,81 @@ Bezier_bow::get_curve ()const
   return rv;
 }
 
-static Real const FUDGE = 1e-8;
-
-/*
-  This function calculates 2 center control points,
-  based on lines through c_0 --> left disturbing
-  and c_3--> right disturbing encompass points.
-  
-  See Documentation/fonts.tex
- */
 void
-Bezier_bow::calc_tangent_controls ()
-{
-  Real b = curve_.control_[3][X_AXIS];
-  Real h = curve_.control_[1][Y_AXIS];
-  
-
-  Drul_array<Offset> disturb;
-  Drul_array<Real> maxtan;  
-  maxtan[LEFT]  = maxtan[RIGHT] = h/(b/2);
-  disturb[LEFT]  = disturb[RIGHT] =   Offset (b / 2, h);
-
-  for (int i = 1; i < encompass_.size () -1; i++)
-    {
-      Real y= encompass_[i][Y_AXIS];
-      if (y> 0)
-        {
-         Real x = encompass_[i][X_AXIS];
-         
-         Direction d = LEFT;
-         do
-           {
-             // 1 if d == LEFT
-             int k = (1 - d)/2;
-             Real tan = y /  ((1-k)* b - d * x);
-
-             if (tan > maxtan[d])
-               {
-                 maxtan[d] = tan;
-                 disturb[d] = Offset (x,y);
-               }
-           }
-         while (flip (&d)!=LEFT);
-       }
-    }
-
-  for (int i = 0; i < encompass_.size (); i++ )
-    h = h >? encompass_[i][Y_AXIS];
-
-  /*
-    The curve will always be under line between curve_.control_0 -> curve_.control_1, so
-    make it extra steep by slur_rc_factor
-  */
-
-
-  Drul_array<Real> angles;
-  Direction d = LEFT;
-  do
-    {
-      maxtan[d] *= -d * rc_factor_;
-      angles[d] = atan (maxtan[d]);
-    }
-  while (flip(&d) != LEFT);
-
-  Real rc3 = 0.0;
-
-  /* 
-    if we have two disturbing points, have line through those...
-    in order to get a sane line, make sure points are reasonably far apart
-    X distance must be reasonably(!) big (division)
-   */
-  if (abs (disturb[LEFT][X_AXIS] - disturb[RIGHT][X_AXIS]) > FUDGE)
-    rc3 = (disturb[RIGHT][Y_AXIS] - disturb[LEFT][Y_AXIS]) / (disturb[RIGHT][X_AXIS] - disturb[LEFT][X_AXIS]);
-
-  else
-    rc3 = tan ((angles[LEFT] - angles[RIGHT]) / 2);
-
-
-  // ugh: be less steep
-  rc3 /= 2*rc_factor_;
-  
-
-  Real c2 = -maxtan[RIGHT] * curve_.control_[3][X_AXIS];
-
-  // use highest because rc3 is damped.
-  Real maxy = disturb[LEFT][Y_AXIS] >? disturb[RIGHT][Y_AXIS];
-  Real c3 = disturb[LEFT][Y_AXIS] > disturb[RIGHT][Y_AXIS] ?
-    maxy - rc3 * disturb[LEFT][X_AXIS] :
-    maxy - rc3 * disturb[RIGHT][X_AXIS];
-
-  curve_.control_[1][X_AXIS] = c3 / (maxtan[LEFT] - rc3);
-  curve_.control_[1][Y_AXIS] = maxtan[LEFT] * curve_.control_[1][X_AXIS];
-  
-  curve_.control_[2][X_AXIS] = (c3 - c2) / (maxtan[RIGHT] - rc3);
-  curve_.control_[2][Y_AXIS] = maxtan[RIGHT] * curve_.control_[2][X_AXIS] + c2;
-
-
-  curve_.check_sanity();
-}
-
-/*
-  max ( encompass.y / curve.y )
-  
- */
-Real
-Bezier_bow::fit_factor () const
-{
-  Real x1 = encompass_[0][X_AXIS];
-  Real x2 = encompass_.top ()[X_AXIS];
-
-  Real factor = 0.0;
-  for (int i=1; i < encompass_.size ()-1; i++)
-    {
-      if (encompass_[i][X_AXIS] > x1 && encompass_[i][X_AXIS] < x2)
-       {
-        Real y = curve_.get_other_coordinate (X_AXIS, encompass_[i][X_AXIS]);
-        if (y>0)
-          {
-            Real f = encompass_[i][Y_AXIS] / y;
-            factor = factor >? f;
-          }
-       }
-    }
-
-
-  return factor;
-}
-
-
-
-
-void
-Bezier_bow::to_canonic_form ()
+Bezier_bow::to_canonical_form ()
 {
   origin_ = encompass_[0];
-  translate (encompass_,-origin_);
+  translate (&encompass_, -origin_);
 
   Offset delta = encompass_.top () - encompass_[0];
   alpha_ = delta.arg ();
 
-  rotate (encompass_, -alpha_);
+  rotate (&encompass_, -alpha_);
   if (dir_ == DOWN)
     {
-      flipy (encompass_);
+      flip (&encompass_, Y_AXIS);
     }
 
   while (encompass_.size () > 1 && encompass_[1][X_AXIS] <= 0.0)
     {
-      programming_error ("Degenerate slur: infinite steepness reqd");
+      programming_error ("Degenerate bow: infinite steepness reqd");
       encompass_.del (1);
     }
 
   Real l = encompass_.top ()[X_AXIS];
   while (encompass_.size () > 1 && encompass_.top (1)[X_AXIS] >= l)
     {
-      programming_error ("Degenerate slur: infinite steepness reqd");
+      programming_error ("Degenerate bow: infinite steepness reqd");
       encompass_.del (encompass_.size ()-2);
     }
 }
 
-
+void
+Bezier_bow::set_default_bezier (Real h_inf, Real r_0)
+{
+  curve_ = get_default_bezier (h_inf, r_0);
+}
 
 /*
- See Documentation/fonts.tex
+  See Documentation/programmer/fonts.doc
  */
-void
-Bezier_bow::calc_default ()
+Bezier
+Bezier_bow::get_default_bezier (Real h_inf, Real r_0) const
 {
-  Real pi = M_PI;
-
-  Real alpha = height_limit_ * 2.0 / pi;
-  Real beta = pi * ratio_ / (2.0 * height_limit_);
-
-  Offset delta (encompass_.top ()[X_AXIS] 
-    - encompass_[0][X_AXIS], 0);
-
+  Offset delta (encompass_.top ()[X_AXIS] - encompass_[0][X_AXIS], 0);
   Real b = delta.length ();
-  Real indent = alpha * atan (beta * b);
-  Real height = indent;
-  curve_.control_ [0] = Offset (0, 0);
-  curve_.control_ [1] = Offset (indent, height);
-  curve_.control_ [2] = Offset (b - indent, height);
-  curve_.control_ [3] = Offset (b, 0);
-}
+  Real height = get_default_height (h_inf, r_0, b);
+  // urg: scmify this?
+  Real indent = height;
 
+  Bezier curve;
+  curve.control_[0] = Offset (0, 0);
+  curve.control_[1] = Offset (indent, height);
+  curve.control_[2] = Offset (b - indent, height);
+  curve.control_[3] = Offset (b, 0);
+  return curve;
+}
 
+/*
+  See Documentation/programmer/fonts.doc
+ */
+Real
+Bezier_bow::get_default_height (Real h_inf, Real r_0, Real b) const
+{
+#if 0
+  Real pi = M_PI;
 
+  Real alpha = 2.0 * h_inf / pi;
+  Real beta = pi * r_0 / (2.0 * h_inf);
 
+  return alpha * atan (beta * b);
+#else
+  SCM h = scm_eval (scm_listify (ly_symbol2scm ("slur-default-height"),
+                                gh_double2scm (h_inf),
+                                gh_double2scm (r_0),
+                                gh_double2scm (b),
+                                SCM_UNDEFINED));
+  return gh_scm2double (h);
+#endif
+}
+  
index 28634b473c683b283e95cd27d465814a62d15ab4..6b388e1d8ff47f7c0589b610e296df1f8864a390 100644 (file)
 #include "bezier.hh"
 #include "polynomial.hh"
 
+Real
+binomial_coefficient (Real over , int under)
+{
+  Real x = 1.0;
+
+  while (under)
+    {
+      x *= over / Real (under);
+
+      over  -= 1.0;
+      under --;
+    }
+  return x;
+}
+
+void
+flip (Array<Offset>* arr_p, Axis a)
+{
+  // huh?
+  //  for (int i = c.size (); i--;)
+  for (int i = 0; i < arr_p->size (); i++)
+    (*arr_p)[i][a] = - (*arr_p)[i][a];
+}
+
+void
+rotate (Array<Offset>* arr_p, Real phi)
+{
+  Offset rot (complex_exp (Offset (0, phi)));
+  for (int i = 0; i < arr_p->size (); i++)
+    (*arr_p)[i] = complex_multiply (rot, (*arr_p)[i]);
+}
+
+void
+translate (Array<Offset>* arr_p, Offset o)
+{
+  for (int i = 0; i < arr_p->size (); i++)
+    (*arr_p)[i] += o;
+}
+
 /*
 
   Formula of the bezier 3-spline
@@ -18,6 +57,7 @@
  */
 
 Bezier::Bezier ()
+  : control_ (CONTROL_COUNT)
 {
 }
 
@@ -33,20 +73,6 @@ Bezier::get_other_coordinate (Axis a,  Real x) const
   return c[other];
 }
 
-Real
-binomial_coefficient (Real over , int under)
-{
-  Real x = 1.0;
-
-  while (under)
-    {
-      x *= over / Real (under);
-
-      over  -= 1.0;
-      under --;
-    }
-  return x;
-}
 
 Offset
 Bezier::curve_point (Real t)const
@@ -151,27 +177,23 @@ Bezier::extent (Axis a)const
 void
 Bezier::flip (Axis a)
 {
-  for (int i = CONTROL_COUNT; i--;)
-    control_[i][a] = - control_[i][a];
+  ::flip (&control_, a);
 }
 
 void
 Bezier::rotate (Real phi)
 {
-  Offset rot (complex_exp (Offset (0, phi)));
-  for (int i = 0; i < CONTROL_COUNT; i++)
-    control_[i] = complex_multiply (rot, control_[i]);
+  ::rotate (&control_, phi);
 }
 
 void
 Bezier::translate (Offset o)
 {
-  for (int i = 0; i < CONTROL_COUNT; i++)
-    control_[i] += o;
+  ::translate (&control_, o);
 }
 
 void
-Bezier::check_sanity () const
+Bezier::assert_sanity () const
 {
   for (int i=0; i < CONTROL_COUNT; i++)
     assert (!isnan (control_[i].length ())
index d442124a5c1d0f34efbdbb25bf3a42858c31d289..4c2ea55fc9a15e729b6112d2fd2ab01a1deffdad 100644 (file)
   from bow paratime_signatures.  */
 class Bezier_bow
 {
-  Bezier curve_;
-  Array<Offset> encompass_;
-  
-  void blow_fit ();
-  void de_uglyfy ();
-  void calc_default ();
-  void to_canonic_form ();
-  void calc_tangent_controls ();
-  Real calc_enclosed_area_f () const;
-  void minimise_enclosed_area ();
-  Array<Offset> area_gradient_offset_arr ();
+public:
+  Bezier_bow (Array<Offset> encompass, Direction dir);
 
-  Real fit_factor () const;
+  Bezier get_bezier () const;
+  Bezier get_default_bezier (Real h_inf, Real r_0) const;
+  Real get_default_height (Real h_inf, Real r_0, Real length) const;
+  void set_default_bezier (Real h_inf, Real r_0);
 
+  /**
+     The canonical bezier.
+   */
+  Bezier curve_;
 
-  Paper_def* paper_l_;
+protected:
+  Array<Offset> encompass_;
+
+private:
+  void to_canonical_form ();
   Direction dir_;
   Real alpha_;
   Offset origin_;
-public:
-  Real  rc_factor_;
-  Real height_limit_;
-  Real ratio_;
-
-
-  Real vertical_offset_needed () const;
-  
-  Bezier_bow (Array<Offset> points, Direction dir);
-  void calculate ();
-  Bezier get_curve () const;
 };
 
 
index 47890afca282bb42045d8cda90003774fbf06e6a..3ac97b71706ea7baa09ac9f819f47ba254841465 100644 (file)
@@ -24,10 +24,12 @@ class Bezier
 public:
   Bezier ();
 
+  void assert_sanity () const;
+  void flip (Axis);
+  void reverse ();
   void rotate (Real);
   void translate (Offset);
-  void flip (Axis);
-  void check_sanity () const;
+
   Real get_other_coordinate (Axis a, Real x) const;
   Array<Real> solve_point (Axis, Real coordinate) const;
   Array<Real> solve_derivative (Offset) const;
@@ -35,12 +37,13 @@ public:
   Polynomial polynomial (Axis)const;
   Offset curve_point (Real t) const;
 
-  void reverse ();
-
   static const int CONTROL_COUNT = 4;
-  Offset control_[CONTROL_COUNT];
+  Array<Offset> control_;
 };
 
+void flip (Array<Offset>* arr_p, Axis a);
+void rotate (Array<Offset>* arr_p, Real phi);
+void translate (Array<Offset>* arr_p, Offset o);
 
 #endif // BEZIER_HH
 
index 8d808ac4039208a140aee1bc946175836c90181f..b79ffbf89522d6620113c6e2d0673d5fede0bedb 100644 (file)
@@ -20,8 +20,6 @@ SCM ly_eval_str (String s);
 SCM ly_symbol2scm (char const *);
 String ly_symbol2string (SCM);
 
-SCM ly_offset2scm (Offset o);
-Offset ly_scm2offset (SCM s);
 SCM ly_eval (SCM a);
 SCM ly_parse_scm (char const* s, int* n);
 SCM ly_quote_scm (SCM s);
@@ -54,6 +52,9 @@ int scm_to (SCM s, int* i);
 SCM to_scm (Real r);
 Real scm_to (SCM s, Real* r);
 
+SCM to_scm (Offset o);
+Offset scm_to (SCM s, Offset* o);
+
 /*
   snarfing.
  */
index 2fc37f1df81cd728d8d7e73bfe22d4ad1c1e4235..4f14512047e2d7bc7172ec1ca1b91c47ebc0cb71 100644 (file)
@@ -15,8 +15,6 @@
  */
 class Slur : public Spanner
 {
-  int cross_staff_count () const;
-  Offset encompass_offset (Note_column const* )const;
 public:
   Slur ();
   VIRTUAL_COPY_CONS(Score_element);
@@ -25,7 +23,7 @@ public:
 
 
 protected:
-  virtual Molecule* do_brew_molecule_p () const;
+  virtual Molecule do_brew_molecule () const;
   virtual Array<Offset> get_encompass_offset_arr () const;
   Bezier get_curve () const;
   Drul_array<Real> dy_f_drul_;
@@ -35,6 +33,13 @@ protected:
   virtual void do_post_processing ();
   virtual void do_add_processing ();
   Array<Rod> get_rods () const;
+
+private:  
+  void de_uglyfy (class Slur_bezier_bow* bb, Real default_height);
+  void set_extremities ();
+  void set_control_points ();
+  int cross_staff_count () const;
+  Offset encompass_offset (Note_column const* )const;
 };
 
 #endif // SLUR_HH
index 0ed09ec2de6e83fd1b810e93a9c7e2ecddb6b2cd..ccca3060e97edf6a8ff7e262ff7c1cabd9aaaf38 100644 (file)
@@ -328,13 +328,13 @@ appendable_list_append (SCM l, SCM elt)
 
 
 SCM
-ly_offset2scm (Offset o)
+to_scm (Offset o)
 {
   return gh_cons (gh_double2scm (o[X_AXIS]), gh_double2scm(o[Y_AXIS]));
 }
 
 Offset
-ly_scm2offset (SCM s)
+scm_to (SCM s, Offset*)
 {
   return Offset (gh_scm2double (gh_car (s)),
                 gh_scm2double (gh_cdr (s)));
index 28a50a073eeb96b44316f1950668ac6cc15eb218..f1d1189b2495ec7653b19ae93c338fa37cee65b0 100644 (file)
@@ -59,9 +59,10 @@ Lookup::afm_find (String s, bool warn) const
        }
     }
   AFM_CharMetricInfo const *cm = afm_l_->find_char_metric (s, warn);
-  Molecule m;
+
   if (!cm)
     {
+      Molecule m;
       m.set_empty (false);
       return m;
     }
@@ -71,9 +72,7 @@ Lookup::afm_find (String s, bool warn) const
                    SCM_UNDEFINED));
 
   at= fontify_atom (afm_l_,at);
-  m.dim_ = afm_bbox_to_box (cm->charBBox);
-  m.add_atom (at);
-  return m;
+  return Molecule ( afm_bbox_to_box (cm->charBBox), at);
 }
 
 Molecule
@@ -177,19 +176,17 @@ Lookup::beam (Real slope, Real width, Real thick)
   Real max_y = (0 >? height) + thick/2;
 
   
-  Molecule m;
-  m.dim_[X_AXIS] = Interval (0, width);
-  m.dim_[Y_AXIS] = Interval (min_y, max_y);
 
-  
-  SCM at = (gh_list (ly_symbol2scm ("beam"),
-             gh_double2scm (width),
-             gh_double2scm (slope),
-             gh_double2scm (thick),
-             SCM_UNDEFINED));
+  Box b( Interval (0, width),
+        Interval (min_y, max_y));
 
-  m.add_atom (at);
-  return m;
+  
+  SCM at = gh_list (ly_symbol2scm ("beam"),
+                   gh_double2scm (width),
+                   gh_double2scm (slope),
+                   gh_double2scm (thick),
+                   SCM_UNDEFINED);
+  return Molecule (b, at);
 }
 
 
@@ -198,9 +195,10 @@ Molecule
 Lookup::dashed_slur (Bezier b, Real thick, Real dash)
 {
   SCM l = SCM_EOL;
+  // this is silly, we have array_to_scm
   for (int i= 4; i -- ;)
     {
-      l = gh_cons (ly_offset2scm (b.control_[i]), l);
+      l = gh_cons (to_scm (b.control_[i]), l);
     }
 
   SCM at = (gh_list (ly_symbol2scm ("dashed-slur"),
@@ -208,9 +206,9 @@ Lookup::dashed_slur (Bezier b, Real thick, Real dash)
                               gh_double2scm (dash),
                               ly_quote_scm (l),
                               SCM_UNDEFINED));
-  Molecule m;
-  m.add_atom (at);
-  return m;
+
+  Box box (Interval(0,0),Interval( 0,0));
+  return   Molecule (box, at);
 }
 
 
@@ -228,8 +226,6 @@ Lookup::fill (Box b)
 Molecule
 Lookup::filledbox (Box b ) 
 {
-  Molecule m;
-  
   SCM  at  = (gh_list (ly_symbol2scm ("filledbox"),
                     gh_double2scm (-b[X_AXIS][LEFT]),
                     gh_double2scm (b[X_AXIS][RIGHT]),                 
@@ -237,9 +233,7 @@ Lookup::filledbox (Box b )
                     gh_double2scm (b[Y_AXIS][UP]),                    
                     SCM_UNDEFINED));
 
-  m.dim_ = b;
-  m.add_atom (at);
-  return m;
+  return Molecule ( b,at);
 }
 
 Molecule
@@ -320,7 +314,6 @@ sanitise_PS_string (String t)
 Molecule
 Lookup::text (String style, String text, Paper_def *paper_l) 
 {
-  Molecule m;
   if (style.empty_b ())
     style = "roman";
   
@@ -361,15 +354,14 @@ Lookup::text (String style, String text, Paper_def *paper_l)
   else if (output_global_ch == "ps")
     text = sanitise_PS_string (text);
     
-  m.dim_ = metric_l->text_dimension (text);
+
   
   SCM at = (gh_list (ly_symbol2scm ("text"),
                     ly_str02scm (text.ch_C()),
                     SCM_UNDEFINED));
   at = fontify_atom (metric_l,at);
-  
-  m.add_atom (at);
-  return m;
+  return Molecule ( metric_l->text_dimension (text),
+                   at);
 }
   
 
@@ -377,8 +369,6 @@ Lookup::text (String style, String text, Paper_def *paper_l)
 Molecule
 Lookup::staff_brace (Real y, int staff_size) 
 {
-  Molecule m;
-
   // URG
   Real step  = 1.0;
   int minht  = 2 * staff_size;
@@ -396,10 +386,9 @@ Lookup::staff_brace (Real y, int staff_size)
 
   at = fontify_atom (all_fonts_global_p->find_font (nm), at);
   
-  m.dim_[Y_AXIS] = Interval (-y/2,y/2);
-  m.dim_[X_AXIS] = Interval (0,0);
-  m.add_atom (at);
-  return m;
+  Box b ( Interval (-y/2,y/2),
+          Interval (0,0));
+  return Molecule(b, at);
 }
  
 
@@ -417,10 +406,11 @@ Lookup::slur (Bezier curve, Real curvethick, Real linethick)
   back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));  
 
   SCM scontrols[8];
+  // this is silly, we have array_to_scm
   for (int i=4; i--;)
-    scontrols[ i ] = ly_offset2scm (back.control_[i]);
+    scontrols[ i ] = to_scm (back.control_[i]);
   for (int i=4 ; i--;)
-    scontrols[i+4] = ly_offset2scm (curve.control_[i]);
+    scontrols[i+4] = to_scm (curve.control_[i]);
 
   /*
     Need the weird order b.o. the way PS want its arguments  
@@ -438,17 +428,13 @@ Lookup::slur (Bezier curve, Real curvethick, Real linethick)
                     gh_double2scm (linethick),
                     SCM_UNDEFINED));
 
-  Molecule m; 
-  m.dim_[X_AXIS] = curve.extent (X_AXIS);
-  m.dim_[Y_AXIS] = curve.extent (Y_AXIS);
-  m.add_atom (at);
-  return m;
+  Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
+  return Molecule (b, at);
 }
 
 Molecule
 Lookup::staff_bracket (Real height, Paper_def* paper_l)
 {
-  Molecule m;
   SCM at = ( gh_list (ly_symbol2scm ("bracket"),
                      gh_double2scm (paper_l->get_var("bracket_arch_angle")),
                      gh_double2scm (paper_l->get_var("bracket_arch_width")),
@@ -458,10 +444,9 @@ Lookup::staff_bracket (Real height, Paper_def* paper_l)
                      gh_double2scm (paper_l->get_var("bracket_arch_thick")),
                      gh_double2scm (paper_l->get_var("bracket_thick")),
                      SCM_UNDEFINED));
-  
-  m.add_atom (at);                              
-  m.dim_[Y_AXIS] = Interval (-height/2,height/2);
-  m.dim_[X_AXIS] = Interval (0,4 PT);
+
+  Box b ( Interval (-height/2,height/2), Interval (0,4 PT));
+  Molecule m (b, at);
 
   m.translate_axis (- 4. / 3. * m.dim_[X_AXIS].length (), X_AXIS);
   return m;
index f447d542d6e44738d8e117eebf5bca1addc56668..cd4d0482063cfdfabfd6933b8b6bbe431e4688cd 100644 (file)
   ugh. Rewrite not finished yet. Still must copy atom lists.
  */
 
+
 #include <math.h>
 
+#include "dimensions.hh"
 #include "interval.hh"
 #include "string.hh"
 #include "molecule.hh"
@@ -32,67 +34,60 @@ Molecule::extent(Axis a) const
   return dim_[a];
 }
 
+Molecule::Molecule (Box b, SCM func)
+{
+  expr_ = func;
+  dim_ = b ;
+}
+
+Molecule::Molecule()
+{
+  expr_ = SCM_EOL;
+  set_empty (true);
+}
+
 void
 Molecule::translate (Offset o)
 {
-  if (isinf (o.length ()))
-    {
-      programming_error ("Translating infinitely. Ignore.");
-      return;
-    }
-    
-  for (SCM ptr = gh_cdr (atom_list_);  ptr != SCM_EOL; ptr = gh_cdr(ptr))
+  Axis a = X_AXIS;
+  while (a < NO_AXES)
     {
-      gh_set_car_x (ptr, translate_atom (o, gh_car (ptr)));
+      if (abs(o[a]) > 30 CM
+         || isinf (o[a]) || isnan (o[a]))
+       {
+         programming_error ("Improbable offset for translation: setting to zero");
+         o[a] =  0.0;
+       }
+      incr (a);
     }
+
+  expr_ = gh_list (ly_symbol2scm ("translate-molecule"),
+                  to_scm (o),
+                  expr_, SCM_UNDEFINED);
   if (!empty_b ())
     dim_.translate (o);
 }
+  
 
 void
 Molecule::translate_axis (Real x,Axis a)
 {
-  if (isinf (x))
-    {
-      programming_error ("Translating infinitely. Ignore.");
-      return;
-    }
-  for (SCM ptr = gh_cdr (atom_list_);  ptr != SCM_EOL; ptr = gh_cdr(ptr))
-    {
-      gh_set_car_x (ptr, translate_atom_axis (x, a, gh_car (ptr)));
-    }
+  Offset o(0,0);
+  o[a] = x;
+  translate (o);
+}  
+
 
-  if (!dim_[a].empty_b ())
-    dim_[a] += x;
-}
 
 void
 Molecule::add_molecule (Molecule const &m)
 {
-  for (SCM ptr = gh_cdr (m.atom_list_);  ptr != SCM_EOL; ptr = gh_cdr(ptr))
-    {
-      add_atom (gh_car (ptr));
-    }
+  expr_ = gh_list (ly_symbol2scm ("combine-molecule"),
+                  m.expr_,
+                  expr_, SCM_UNDEFINED);
   dim_.unite (m.dim_);
 }
 
-void
-Molecule::add_atom (SCM atomsmob)
-{
-  gh_set_cdr_x (atom_list_,
-               gh_cons  (atomsmob, gh_cdr (atom_list_)));
-}
-
-void
-Molecule::operator=(Molecule const & src)
-{
-  if (&src == this)
-    return;
-
-  atom_list_ = gh_cons (SCM_EOL,scm_list_copy (gh_cdr (src.atom_list_)));
-  dim_= src.dim_;
-}
-
 void
 Molecule::set_empty (bool e)
 {
@@ -112,41 +107,16 @@ void
 Molecule::print () const
 {
 #ifndef NPRINT
-  for (SCM ptr = gh_cdr (atom_list_);  ptr != SCM_EOL; ptr = gh_cdr(ptr))
-    gh_display (gh_car (ptr));
+  gh_display (expr_);
 #endif
 }
 
-Molecule::Molecule (Molecule const &s)
-{
-  atom_list_ = gh_cons (SCM_EOL, scm_list_copy (gh_cdr (s.atom_list_)));
-  dim_ = s.dim_;
-}
-
-Molecule::~Molecule ()
-{
-}
-
-
 void
 Molecule::align_to (Axis a, Direction d)
 {
-  if (d == CENTER)
-    {
-      Interval i (extent (a));
-      translate_axis (-i.center (), a);
-    }
-  else
-    {
-      translate_axis (-extent (a)[d], a);
-    }
-}
-
-Molecule::Molecule ()
-{
-  dim_[X_AXIS].set_empty ();
-  dim_[Y_AXIS].set_empty ();
-  atom_list_ = gh_cons (SCM_EOL, SCM_EOL);
+  Interval i (extent (a));
+  Real r =  (d == CENTER) ? i.center () : i[d];
+  translate_axis (-r, a);
 }
 
 
@@ -168,5 +138,5 @@ Molecule::add_at_edge (Axis a, Direction d, Molecule const &m, Real padding)
 bool
 Molecule::empty_b () const
 {
-  return gh_cdr (atom_list_) == SCM_EOL;
+  return expr_ == SCM_EOL;
 }
index f3863b13bd202634c9f5909d0aa7ea4d7070f904..fc5630d9ac7c95bca21f18901557a9b3eb6cfe66 100644 (file)
@@ -73,57 +73,43 @@ Paper_outputter::output_header ()
 }
 
 void
-Paper_outputter::output_molecule (Molecule const*m, Offset o, char const *nm)
+Paper_outputter::output_molecule (SCM expr, Offset o, char const *nm)
 {
+#if 0
   if (flower_dstream)
     {
       output_comment (nm);
     }
+#endif
+  
+  SCM offset_sym = ly_symbol2scm ("translate-molecule");
+  SCM combine_sym = ly_symbol2scm ("combine-molecule");
+enter:
 
-  SCM offset_sym = ly_symbol2scm ("translate-atom"); 
-  for (SCM ptr = gh_cdr (m->atom_list_); ptr != SCM_EOL; ptr = gh_cdr (ptr))
+  if (!gh_pair_p (expr))
+    return;
+  
+  SCM head =gh_car (expr);
+  if (head == offset_sym)
     {
-      SCM func =  gh_car (ptr);
-      SCM funcptr = func;
-
-      Offset a_off (0,0);
-      while (gh_pair_p (funcptr))
-       {
-         if (gh_car (funcptr) == offset_sym)
-           {
-             SCM quot = gh_cadr (funcptr);
-             a_off += ly_scm2offset (gh_cadr (quot));
-           }
-         funcptr = scm_last_pair (funcptr);
-         if (funcptr != SCM_EOL )
-           {
-             funcptr = gh_car (funcptr);
-           }
-       }
-      
-      a_off += o;
-      
-      Axis a = X_AXIS;
-      while (a < NO_AXES)
-       {
-         if (abs(a_off[a]) > 30 CM
-             || isinf (a_off[a]) || isnan (a_off[a]))
-           {
-             programming_error ("Improbable offset for object: setting to zero");
-             a_off[a] =  0.0;
-           }
-         incr (a);
-       }
-
-       
-      SCM box_scm
-       = gh_list (ly_symbol2scm ("placebox"),
-                  gh_double2scm (a_off[X_AXIS]),
-                  gh_double2scm (a_off[Y_AXIS]),
-                  func,
-                  SCM_UNDEFINED);
+      o += scm_to (gh_cadr (expr), &o);
+      expr = gh_caddr (expr);
+      goto enter;
+    }
+  else if (head == combine_sym)
+    {
+      output_molecule (gh_cadr (expr), o, nm);
+      expr = gh_caddr (expr);
+      goto enter;              // tail recursion
+    }
+  else
+    {
+      output_scheme (gh_list (ly_symbol2scm ("placebox"),
+                             gh_double2scm (o[X_AXIS]),
+                             gh_double2scm (o[Y_AXIS]),
+                             expr,
+                             SCM_UNDEFINED));
 
-      output_scheme (box_scm);
     }
 }
 
index bc64fd20c4f35e8ad537c038ade4da51908c2f10..679ece65b5b264333a03e235cd0938a21be8c108 100644 (file)
 #include "molecule.hh"
 #include "debug.hh"
 #include "box.hh"
-#include "bezier.hh"
 #include "bezier-bow.hh"
 #include "main.hh"
 #include "cross-staff.hh"
 #include "group-interface.hh"
+#include "staff-symbol-referencer.hh"
+#include "lily-guile.icc"
+
+
+class Slur_bezier_bow : public Bezier_bow
+{
+public:
+  Slur_bezier_bow (Array<Offset> encompass, Direction dir);
+  Array<Real> area_x_gradients_array (Real area);
+  void blow_fit ();
+  Real enclosed_area_f () const;
+  Real fit_factor () const;
+  void minimise_enclosed_area (Paper_def* paper_l, Real default_height);
+};
+
+Slur_bezier_bow::Slur_bezier_bow (Array<Offset> encompass, Direction dir)
+  : Bezier_bow (encompass, dir)
+{
+}
+
+void
+Slur_bezier_bow::blow_fit ()
+{
+  Real len = curve_.control_[3][X_AXIS]; 
+  Real h = curve_.control_[1][Y_AXIS] * fit_factor () / len;
+  curve_.control_[1][Y_AXIS] = h * len;
+  curve_.control_[2][Y_AXIS] = h * len;  
+  curve_.assert_sanity ();
+}
+
+
+Real
+Slur_bezier_bow::enclosed_area_f () const
+{
+  Real a = 0;
+  for (int i=0; i < encompass_.size (); i++)
+    {
+      Interval x;
+      Interval y;
+      if (i == 0)
+       {
+         x = Interval (0, encompass_[1][X_AXIS] / 2);
+         y = Interval (0,
+                       curve_.get_other_coordinate (X_AXIS,
+                                                    encompass_[1][X_AXIS]
+                                                    / 2));
+       }
+      else if (i == encompass_.size () - 1)
+       {
+         x = Interval ((encompass_[i-1][X_AXIS] + encompass_[i][X_AXIS])/2, 
+                       encompass_[i][X_AXIS]);
+         y = Interval (0,
+                       (curve_.get_other_coordinate (X_AXIS,
+                                                     (x[MIN] + x[MAX]) / 2)));
+       }
+      else
+       {
+         x = Interval ((encompass_[i-1][X_AXIS] + encompass_[i][X_AXIS]) / 2, 
+                       (encompass_[i][X_AXIS] + encompass_[i+1][X_AXIS]) / 2);
+         y = Interval (encompass_[i][Y_AXIS],
+                       (curve_.get_other_coordinate (X_AXIS, x[MIN])
+                        + curve_.get_other_coordinate (X_AXIS,
+                                                       (x[MIN] + x[MAX]) / 2)
+                        + curve_.get_other_coordinate (X_AXIS, x[MAX])) / 3);
+       }
+      
+      Real da = x.length () * y.length ();
+      a += da;
+    }
+  return a;
+}
+
+Array<Real>
+Slur_bezier_bow::area_x_gradients_array (Real area)
+{
+  Real len = curve_.control_[3][X_AXIS]; 
+  Real grow = len / 10.0;
+  Array<Real> da (2);
+  for (int i=0; i < 2; i++)
+    {
+      Real r = curve_.control_[i+1][X_AXIS];
+      curve_.control_[i+1][X_AXIS] += grow;
+      da[i] = (enclosed_area_f () - area) / grow;
+      curve_.control_[i+1][X_AXIS] = r; 
+    }
+  return da;
+}
+
+void
+Slur_bezier_bow::minimise_enclosed_area (Paper_def* paper_l,
+                                        Real default_height)
+{
+  Real length = curve_.control_[3][X_AXIS]; 
+  Real bbc = paper_l->get_var ("bezier_beautiful");
+  Real beautiful = length * default_height / bbc;
+
+  DEBUG_OUT << to_str ("Beautiful: %f\n", beautiful);
+  DEBUG_OUT << to_str ("Length: %f\n", length);
+  DEBUG_OUT << to_str ("D-height: %f\n", default_height);
+  DEBUG_OUT << to_str ("FitFac: %f\n", fit_factor ());
+
+  if (fit_factor () > 1.0)
+    blow_fit ();
+  
+  Real pct_c0 = paper_l->get_var ("bezier_pct_c0");
+  Real pct_c3 = paper_l->get_var ("bezier_pct_c3");
+  Real pct_in_max = paper_l->get_var ("bezier_pct_in_max");
+  Real pct_out_max = paper_l->get_var ("bezier_pct_out_max");
+  Real steps = paper_l->get_var ("bezier_area_steps");
+
+  for (int i=0; i < steps; i++)
+    {
+      Real area = enclosed_area_f ();
+      if (!i)
+       DEBUG_OUT << to_str ("Init area: %f\n", area);
+
+      if (area <= beautiful)
+       break;
+
+      Array<Real> da = area_x_gradients_array (area);
+
+      // urg
+      Real pct = pct_c0 + pct_c3 * length * length * length;
+      pct *= (steps - i) / steps;
+      if (da[0] > 0 || da[1] < 0)
+       pct = pct <? pct_out_max;
+      else
+       pct = pct <? pct_in_max;
+
+      Real u = (abs (curve_.control_[1][X_AXIS] / da[0])
+               <? abs ((curve_.control_[3][X_AXIS]
+                        - curve_.control_[2][X_AXIS]) / da[1]));
+
+      DEBUG_OUT << to_str ("pct: %f\n", pct);
+      DEBUG_OUT << to_str ("u: %f\n", u);
+
+      DEBUG_OUT << to_str ("da: (%f, %f)\n", da[0], da[1]);
+      DEBUG_OUT << to_str ("da*u: (%f, %f)\n", da[0]*u*pct, da[1]*u*pct);
+      DEBUG_OUT << to_str ("cx: (%f, %f)\n", curve_.control_[1][X_AXIS],
+                          curve_.control_[2][X_AXIS]);
+
+      curve_.control_[1][X_AXIS] -= da[0] * u * pct;
+      curve_.control_[2][X_AXIS] -= da[1] * u * pct;
+    }
+
+  Real area = enclosed_area_f ();
+  DEBUG_OUT << to_str ("Exarea: %f\n", area);
+}
+
+
+
+/*
+  max ( encompass.y / curve.y )
+  
+ */
+Real
+Slur_bezier_bow::fit_factor () const
+{
+  Real x1 = encompass_[0][X_AXIS];
+  Real x2 = encompass_.top ()[X_AXIS];
+
+  Real factor = 0.0;
+  for (int i=1; i < encompass_.size ()-1; i++)
+    {
+      if (encompass_[i][X_AXIS] > x1 && encompass_[i][X_AXIS] < x2)
+       {
+        Real y = curve_.get_other_coordinate (X_AXIS, encompass_[i][X_AXIS]);
+        if (y>0)
+          {
+            Real f = encompass_[i][Y_AXIS] / y;
+            factor = factor >? f;
+          }
+       }
+    }
+
+
+  return factor;
+}
+
+
+
+
+
+/*
+  Slur
+*/
 
 Slur::Slur ()
 {
+  // URG
   dy_f_drul_[LEFT] = dy_f_drul_[RIGHT] = 0.0;
   dx_f_drul_[LEFT] = dx_f_drul_[RIGHT] = 0.0;
+
   set_elt_property ("note-columns", SCM_EOL);
+  set_elt_property ("control-points", SCM_EOL);
+
+#if 0
+  /*
+    I still don't understand the merits of this Group_interface.
+   */
+  Group_interface c (this, "control-points");
+  c.set_interface ();
+#endif
 }
 
 void
@@ -50,6 +246,36 @@ Slur::add_column (Note_column*n)
     }
 }
 
+void
+Slur::de_uglyfy (Slur_bezier_bow* bb, Real default_height)
+{
+  Real length = bb->curve_.control_[3][X_AXIS] ; 
+  Real ff = bb->fit_factor ();
+  for (int i = 1; i < 3; i++)
+    {
+      Real ind = abs (bb->curve_.control_[(i-1)*3][X_AXIS]
+                     - bb->curve_.control_[i][X_AXIS]) / length;
+      Real h = bb->curve_.control_[i][Y_AXIS] * ff / length;
+
+      Real f = default_height / length;
+      Real c1 = paper_l ()->get_var ("bezier_control1");
+      Real c2 = paper_l ()->get_var ("bezier_control2");
+      Real c3 = paper_l ()->get_var ("bezier_control3");
+      if (h > c1 * f)
+       {
+         h = c1 * f; 
+       }
+      else if (h > c2 + c3 * ind)
+       {
+         h = c2 + c3 * ind; 
+       }
+      
+      bb->curve_.control_[i][Y_AXIS] = h * length;
+    } 
+
+  bb->curve_.assert_sanity ();
+}
+
 Direction
 Slur::get_default_dir () const
 {
@@ -94,7 +320,7 @@ Slur::encompass_offset (Note_column const* col) const
   if (!stem_l)
     {
       warning (_ ("Slur over rest?"));
-      o[X_AXIS] = col->hpos_f ();
+     o[X_AXIS] = col->hpos_f ();
       o[Y_AXIS] = col->extent (Y_AXIS)[dir];
       return o;  
     }
@@ -125,13 +351,19 @@ Slur::encompass_offset (Note_column const* col) const
   return o;
 }
 
-/*
-  ARGRARGRARGRARGAR!
+void
+Slur::do_post_processing ()
+{
+  set_extremities ();
+  set_control_points ();
+} 
 
-  Fixme
+/*
+  urg
+  FIXME
  */
 void
-Slur::do_post_processing ()
+Slur::set_extremities ()
 {
   Link_array<Note_column> encompass_arr =
     Group_interface__extract_elements (this, (Note_column*)0, "note-columns");
@@ -287,158 +519,6 @@ Slur::do_post_processing ()
        
   if (!fix_broken_b)
     dy_f_drul_[RIGHT] += interstaff_f;
-
-
-
-  return; 
-
-  /*
-    Now we've got a fine slur
-    Catch and correct some ugly cases
-   */
-  String infix = interstaff_b ? "interstaff_" : "";
-  Real height_damp_f = paper_l ()->get_var ("slur_"+infix +"height_damping");
-  Real slope_damp_f = paper_l ()->get_var ("slur_"+infix +"slope_damping");
-  Real snap_f = paper_l ()->get_var ("slur_"+infix +"snap_to_stem");
-  Real snap_max_dy_f = paper_l ()->get_var ("slur_"+infix +"snap_max_slope_change");
-
-  Real dx_f = spanner_length ()+ dx_f_drul_[RIGHT] - dx_f_drul_[LEFT];
-  Real dy_f = dy_f_drul_[RIGHT] - dy_f_drul_[LEFT];
-  if (!fix_broken_b)
-    dy_f -= interstaff_f;
-
-  /*
-    Avoid too steep slurs.
-   */
-  Real slope_ratio_f = abs (dy_f / dx_f);
-  if (slope_ratio_f > slope_damp_f)
-    {
-      Direction d = (Direction)(- my_dir * (sign (dy_f)));
-      if (!d)
-       d = LEFT;
-      Real damp_f = (slope_ratio_f - slope_damp_f) * dx_f;
-      /*
-       must never change sign of dy
-       */
-      damp_f = damp_f <? abs (dy_f);
-      dy_f_drul_[d] += my_dir * damp_f;
-    }
-
-  /*
-   Avoid too high slurs 
-
-   Wierd slurs may look a lot better after they have been
-   adjusted a bit.
-   So, we'll do this in 3 steps
-   */
-  for (int i = 0; i < 3; i++)
-    {
-      Bezier c (get_curve ());
-      
-      Offset size (c.extent (X_AXIS).length (),
-                  c.extent (Y_AXIS).length ());
-
-      dy_f = dy_f_drul_[RIGHT] - dy_f_drul_[LEFT];
-      if (!fix_broken_b)
-       dy_f -= interstaff_f;
-
-      Real height_ratio_f = abs (size[Y_AXIS] / size[X_AXIS]);
-      if (height_ratio_f > height_damp_f)
-       {
-         Direction d = (Direction)(- my_dir * (sign (dy_f)));
-         if (!d)
-           d = LEFT;
-         /* take third step */
-         Real damp_f = (height_ratio_f - height_damp_f) * size[X_AXIS] / 3;
-         /*
-           if y positions at about the same height, correct both ends
-         */
-         if (abs (dy_f / dx_f ) < slope_damp_f)
-           {
-             dy_f_drul_[-d] += my_dir * damp_f;
-             dy_f_drul_[d] += my_dir * damp_f;
-           }
-         /*
-           don't change slope too much, would have been catched by slope damping
-         */
-         else
-           {
-             damp_f = damp_f <? abs (dy_f/2);
-             dy_f_drul_[d] += my_dir * damp_f;
-           }
-       }
-    }
-
-  /*
-    If, after correcting, we're close to stem-end...
-  */
-  Drul_array<Real> snapy_f_drul;
-  snapy_f_drul[LEFT] = snapy_f_drul[RIGHT] = 0;
-  Drul_array<Real> snapx_f_drul;
-  snapx_f_drul[LEFT] = snapx_f_drul[RIGHT] = 0;
-  Drul_array<bool> snapped_b_drul;
-  snapped_b_drul[LEFT] = snapped_b_drul[RIGHT] = false;
-  do
-    {
-      Note_column * nc = note_column_drul[d];
-      if (nc == spanned_drul_[d]
-         && nc->stem_l ()
-         && nc->stem_l ()->get_direction () == my_dir
-         && abs (nc->stem_l ()->extent (Y_AXIS)[my_dir]
-                 - dy_f_drul_[d] + (d == LEFT ? 0 : interstaff_f))
-             <= snap_f)
-       {
-         /*
-           prepare to attach to stem-end
-         */
-         snapx_f_drul[d] = nc->stem_l ()->hpos_f ()
-           - spanned_drul_[d]->relative_coordinate (0, X_AXIS);
-
-         snapy_f_drul[d] = nc->stem_l ()->extent (Y_AXIS)[my_dir]
-           + interstaff_interval[d]
-           + my_dir * 2 * y_gap_f;
-         
-         snapped_b_drul[d] = true;
-       }
-    }
-  while (flip (&d) != LEFT);
-
-  /*
-    only use snapped positions if sign (dy) will not change
-    and dy doesn't change too much
-    */
-  if (!fix_broken_b)
-    dy_f += interstaff_f;
-
-
-  /*
-    (sigh)
-
-    More refactoring could be done.
-   */
-  Real maxsnap = abs (dy_f * snap_max_dy_f);
-  if (snapped_b_drul[LEFT] && snapped_b_drul[RIGHT]
-      && ((sign (snapy_f_drul[RIGHT] - snapy_f_drul[LEFT]) == sign (dy_f)))
-      && (!dy_f || (abs (snapy_f_drul[RIGHT] - snapy_f_drul[LEFT] - dy_f)
-                   < maxsnap)))
-    {
-      dy_f_drul_ = snapy_f_drul;
-      dx_f_drul_ = snapx_f_drul;
-    }
-  else
-    do
-      {
-       Direction od = (Direction)-d;
-       if (snapped_b_drul[d]
-           && d * sign (snapy_f_drul[d] - dy_f_drul_[od]) == sign (dy_f)
-           && (!dy_f || (abs (snapy_f_drul[d] - dy_f_drul_[od]  - d * dy_f)
-                         < maxsnap)))
-         {
-           dy_f_drul_[d] = snapy_f_drul[d];
-           dx_f_drul_[d] = snapx_f_drul[d];
-         }
-      }
-    while (flip (&d) != LEFT);
 }
 
 
@@ -560,8 +640,8 @@ ugly_scm (Bezier  b)
 /*
   Ugh should have dash-length + dash-period
  */
-Molecule*
-Slur::do_brew_molecule_p () const
+Molecule
+Slur::do_brew_molecule () const
 {
   Real thick = paper_l ()->get_var ("slur_thickness");
   Bezier one = get_curve ();
@@ -586,26 +666,60 @@ Slur::do_brew_molecule_p () const
       a.add_molecule (mark);
     }
 #endif
-  return new Molecule (a); 
+  return a;
 }
 
+void
+Slur::set_control_points ()
+{
+  Slur_bezier_bow bb (get_encompass_offset_arr (),
+                     directional_element (this).get ());
+
+  Real staff_space = Staff_symbol_referencer_interface (this).staff_space ();
+  Real h_inf = paper_l ()->get_var ("slur_height_limit_factor") * staff_space;
+  Real r_0 = paper_l ()->get_var ("slur_ratio");
 
+  bb.set_default_bezier (h_inf, r_0);
 
+  if (bb.fit_factor () > 1.0)
+    {
+      Real length = bb.curve_.control_[3][X_AXIS]; 
+      Real default_height = bb.get_default_height (h_inf, r_0, length);
+      bb.minimise_enclosed_area (paper_l(), default_height);
+      
+      Real bff = paper_l ()->get_var ("slur_force_blowfit");
+      bb.curve_.control_[1][Y_AXIS] *= bff;
+      bb.curve_.control_[2][Y_AXIS] *= bff;
+      bb.blow_fit ();
+
+      Real sb = paper_l ()->get_var ("slur_beautiful");
+      Real beautiful = length * default_height * sb;
+      Real area = bb.enclosed_area_f ();
+      
+      /*
+       Slurs that fit beautifully are not ugly
+      */
+      if (area > beautiful)
+       de_uglyfy (&bb, default_height);
+    }
+
+  Bezier b = bb.get_bezier ();
+  SCM controls = array_to_scm (b.control_);
+  set_elt_property ("control-points", controls);
+}
+  
+  
 Bezier
 Slur::get_curve () const
 {
+  Bezier b;
+  Array<Offset> controls (4);
+  scm_to_array (get_elt_property ("control-points"), &controls);
+  b.control_ = controls;
+  
   Array<Offset> enc (get_encompass_offset_arr ());
-  Direction dir =  directional_element (this).get ();
-  Bezier_bow b (enc,dir);
-
-  b.ratio_ = paper_l ()->get_var ("slur_ratio");
-  b.height_limit_ = paper_l ()->get_var ("slur_height_limit");
-  b.rc_factor_ = paper_l ()->get_var ("slur_rc_factor");
-
-  b.calculate ();
-
-  Bezier  curve =  b.get_curve ();
-
+  Direction dir = directional_element (this).get ();
+  
   Real x1 = enc[0][X_AXIS];
   Real x2 = enc.top ()[X_AXIS];
   
@@ -615,12 +729,11 @@ Slur::get_curve () const
       Real x = enc[i][X_AXIS];
       if (x > x1 && x <x2)
        {
-         Real y = curve.get_other_coordinate (X_AXIS, x);
+         Real y = b.get_other_coordinate (X_AXIS, x);
          off = off >? dir *  (enc[i][Y_AXIS] - y);
        }
     }
-  curve.translate (Offset (0, dir * off));
-  return curve;
+  b.translate (Offset (0, dir * off));
+  return b;
 }
 
-       
index b96a815dfa3b6a4df8b40d7dcc5f3564d0847976..7f1befbf66a19e613f4062fba48b000167791f00 100644 (file)
@@ -106,8 +106,8 @@ Tie::do_post_processing()
   if (!directional_element (this).get ())
     directional_element (this).set (get_default_dir ());
   
-  Real staff_space = paper_l ()->get_var ("interline");
-  Real half_staff_space = staff_space / 2;
+  Real staff_space = staff_symbol_referencer (this).staff_space ();
+  Real half_space = staff_space / 2;
   Real x_gap_f = paper_l ()->get_var ("tie_x_gap");
   Real y_gap_f = paper_l ()->get_var ("tie_y_gap");
 
@@ -150,7 +150,7 @@ Tie::do_post_processing()
 
   Real ypos = position_f ();
 
-  Real y_f = half_staff_space * ypos; 
+  Real y_f = half_space * ypos; 
   int ypos_i = int (ypos);
  
   Real dx_f = extent (X_AXIS).length () + dx_f_drul_[RIGHT] - dx_f_drul_[LEFT];
@@ -158,14 +158,14 @@ Tie::do_post_processing()
   if (dx_f < paper_l ()->get_var ("tie_staffspace_length"))
     {
       if (abs (ypos_i) % 2)
-       y_f += dir * half_staff_space;
+       y_f += dir * half_space;
       y_f += dir * y_gap_f;
     }
   else
     {
       if (! (abs (ypos_i) % 2))
-       y_f += dir * half_staff_space;
-      y_f += dir * half_staff_space;
+       y_f += dir * half_space;
+      y_f += dir * half_space;
       y_f -= dir * y_gap_f;
     }
   
@@ -188,8 +188,8 @@ Tie::get_rods () const
 
 
 
-Molecule*
-Tie::do_brew_molecule_p () const
+Molecule 
+Tie::do_brew_molecule () const
 {
   Real thick = paper_l ()->get_var ("tie_thickness");
   Bezier one = get_curve ();
@@ -201,7 +201,7 @@ Tie::do_brew_molecule_p () const
   else
     a = lookup_l ()->slur (one, directional_element (this).get () * thick, thick);
   
-  return new Molecule (a)
+  return a
 }
 
 
@@ -212,12 +212,12 @@ Tie::get_curve () const
   Direction d (directional_element (this).get ());
   Bezier_bow b (get_encompass_offset_arr (), d);
 
-  b.ratio_ = paper_l ()->get_var ("slur_ratio");
-  b.height_limit_ = paper_l ()->get_var ("slur_height_limit");
-  b.rc_factor_ = paper_l ()->get_var ("slur_rc_factor");
+  Real staff_space = staff_symbol_referencer (this).staff_space ();
+  Real h_inf = paper_l ()->get_var ("tie_height_limit_factor") * staff_space;
+  Real r_0 = paper_l ()->get_var ("tie_ratio");
 
-  b.calculate ();
-  Bezier c (b.get_curve ());
+  b.set_default_bezier (h_inf, r_0);
+  Bezier c = b.get_bezier ();
 
   /* should do this for slurs as well. */
   Array<Real> horizontal (c.solve_derivative (Offset (1,0)));
@@ -227,15 +227,14 @@ Tie::get_curve () const
       /*
        ugh. Doesnt work for non-horizontal curves.
        */
-      Real space = staff_symbol_referencer (this).staff_space ();
       Real y = c.curve_point (horizontal[0])[Y_AXIS];
 
-      Real ry = rint (y/space) * space;
+      Real ry = rint (y/staff_space) * staff_space;
       Real diff = ry - y;
       Real newy = y;
       if (fabs (diff) < paper_l ()->get_var ("tie_staffline_clearance"))
        {
-         newy = ry - 0.5 * space * sign (diff) ;
+         newy = ry - 0.5 * staff_space * sign (diff) ;
        }
 
       Real y0 = c.control_ [0][Y_AXIS];
index 36ccac9622234ae7f5f7dd0b48a674de0bcfe6b3..9a6b05a8c02f2a700f22a096158ee5ebd3a13e9f 100644 (file)
@@ -2,7 +2,7 @@
 ;;;
 ;;;  source file of the GNU LilyPond music typesetter
 ;;; 
-;;; (c) 1999 Jan Nieuwenhuizen <janneke@gnu.org>
+;;; (c) 1999--2000 Jan Nieuwenhuizen <janneke@gnu.org>
 
 ;;; All dimensions are measured in staff-spaces
 
 
 (define stem-shorten '(0.5))
 (define grace-stem-shorten '(0.0))
+
+;; urg
+(define pi (* 2 (acos 0)))
+
+(define (slur-default-height h-inf r-0 b)
+  (let ((alpha (/ (* 2.0 h-inf) pi))
+       (beta (/ (* pi r-0) (* 2.0 h-inf))))
+    (* alpha (atan (* beta b)))))