]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/slur-configuration.cc
Issue 4627: Convert Scheme_hash_table to using Smob1
[lilypond.git] / lily / slur-configuration.cc
index 02df6fe35ff6ea22ef40430162287fc69945f0d0..4bd0c7113959f92d21e29c19bf0e5f7b103c6356 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 2004--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  Copyright (C) 2004--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
   LilyPond is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -31,6 +31,9 @@
 #include "tie.hh"
 #include "warn.hh"
 
+using std::string;
+using std::vector;
+
 Bezier
 avoid_staff_line (Slur_score_state const &state,
                   Bezier bez)
@@ -43,27 +46,41 @@ avoid_staff_line (Slur_score_state const &state,
       && (state.extremes_[LEFT].staff_ == state.extremes_[RIGHT].staff_)
       && state.extremes_[LEFT].staff_ && state.extremes_[RIGHT].staff_)
     {
-      Real y = bez.curve_point (ts[0])[Y_AXIS];
+      Real t = ts[0]; //the first (usually only) point where slur is horizontal
+      Real y = bez.curve_point (t)[Y_AXIS];
+      // A Bezier curve at t moves 3t-3t² as far as the middle control points
+      Real factor = 3.0 * t * (1.0 - t);
 
       Grob *staff = state.extremes_[LEFT].staff_;
 
-      Real p = 2 * (y - staff->maybe_pure_coordinate (state.common_[Y_AXIS], Y_AXIS, state.stub_, 0, INT_MAX))
+      Real p = 2 * (y - staff->relative_coordinate (state.common_[Y_AXIS], Y_AXIS))
                / state.staff_space_;
 
-      Real const round = my_round (p);
-      Real const frac = p - round;
-      if (fabs (frac) < 4 * state.thickness_
-          && Staff_symbol_referencer::on_staff_line (staff, int (round)))
+      int round_p = (int) my_round (p);
+      if (!Staff_symbol_referencer::on_staff_line (staff, round_p))
+        round_p += (p > round_p) ? 1 : -1;
+      if (!Staff_symbol_referencer::on_staff_line (staff, round_p))
+        return bez;
+
+      Real const distance = (p - round_p) * state.staff_space_ / 2.0;
+      // Allow half the thickness of the slur at the point t, plus one basic
+      // blot-diameter (half for the slur outline, half for the staff line)
+      Real const min_distance = 0.5 * state.thickness_ * factor
+        + state.line_thickness_
+        + ((state.dir_ * distance > 0.0)
+           ? state.parameters_.gap_to_staffline_inside_
+           : state.parameters_.gap_to_staffline_outside_);
+      if (fabs (distance) < min_distance)
         {
-          Direction resolution_dir = frac ? state.dir_ : CENTER;
-
-          // TODO: parameter
-          Real newp = round + resolution_dir * 5 * state.thickness_;
+          Direction resolution_dir = (distance > 0.0) ? UP : DOWN;
 
-          Real dy = (newp - p) * state.staff_space_ / 2.0;
+          Real dy = resolution_dir * (min_distance - fabs (distance));
 
+          // Shape the curve, moving the horizontal point by factor * dy
           bez.control_[1][Y_AXIS] += dy;
           bez.control_[2][Y_AXIS] += dy;
+          // Move the entire curve by the remaining amount
+          bez.translate (Offset (0.0, dy - factor * dy));
         }
     }
   return bez;
@@ -105,7 +122,7 @@ fit_factor (Offset dz_unit, Offset dz_perp, Real close_to_edge_length,
 
       Real y = curve.get_other_coordinate (X_AXIS, p[X_AXIS]);
       if (y)
-        fit_factor = max (fit_factor, (p[Y_AXIS] / y));
+        fit_factor = std::max (fit_factor, (p[Y_AXIS] / y));
     }
   return fit_factor;
 }
@@ -137,7 +154,7 @@ Slur_configuration::generate_curve (Slur_score_state const &state,
   (control3 - control0).  */
 
   Real max_indent = len / 3.1;
-  indent = min (indent, max_indent);
+  indent = std::min (indent, max_indent);
 
   Real a1 = sqr (len) / 3.0;
   Real a2 = 0.75 * sqr (indent + len / 3.0);
@@ -167,7 +184,7 @@ Slur_configuration::generate_curve (Slur_score_state const &state,
   Real ff = fit_factor (dz_unit, dz_perp, state.parameters_.close_to_edge_length_,
                         curve, state.dir_, avoid);
 
-  height = max (height, min (height * ff, max_h));
+  height = std::max (height, std::min (height * ff, max_h));
 
   curve.control_[0] = attachment_[LEFT];
   curve.control_[1] = attachment_[LEFT] + dz_perp * height * state.dir_
@@ -187,7 +204,7 @@ Slur_configuration::Slur_configuration ()
 };
 
 void
-Slur_configuration::add_score (Real s, string desc)
+Slur_configuration::add_score (Real s, const string &desc)
 {
   if (s < 0)
     {
@@ -241,7 +258,7 @@ Slur_configuration::score_encompass (Slur_score_state const &state)
               Real hd = (head_dy)
                         ? (1 / fabs (head_dy) - 1 / state.parameters_.free_head_distance_)
                         : state.parameters_.head_encompass_penalty_;
-              hd = min (max (hd, 0.0), state.parameters_.head_encompass_penalty_);
+              hd = std::min (std::max (hd, 0.0), state.parameters_.head_encompass_penalty_);
 
               demerit += hd;
             }
@@ -256,7 +273,7 @@ Slur_configuration::score_encompass (Slur_score_state const &state)
             {
 
               Real closest
-                = state.dir_ * max (state.dir_ * state.encompass_infos_[j].get_point (state.dir_), state.dir_ * line_y);
+                = state.dir_ * std::max (state.dir_ * state.encompass_infos_[j].get_point (state.dir_), state.dir_ * line_y);
               Real d = fabs (closest - y);
 
               convex_head_distances.push_back (d);
@@ -282,7 +299,7 @@ Slur_configuration::score_encompass (Slur_score_state const &state)
 
       for (vsize j = 0; j < n; j++)
         {
-          min_dist = min (min_dist, convex_head_distances[j]);
+          min_dist = std::min (min_dist, convex_head_distances[j]);
           avg_distance += convex_head_distances[j];
         }
 
@@ -305,9 +322,9 @@ Slur_configuration::score_encompass (Slur_score_state const &state)
       Real variance_penalty = state.parameters_.head_slur_distance_max_ratio_;
       if (min_dist > 0.0)
         variance_penalty
-          = min ((avg_distance / (min_dist + state.parameters_.absolute_closeness_measure_) - 1.0), variance_penalty);
+          = std::min ((avg_distance / (min_dist + state.parameters_.absolute_closeness_measure_) - 1.0), variance_penalty);
 
-      variance_penalty = max (variance_penalty, 0.0);
+      variance_penalty = std::max (variance_penalty, 0.0);
       variance_penalty *= state.parameters_.head_slur_distance_factor_;
 
       add_score (variance_penalty, "variance");
@@ -320,7 +337,7 @@ Slur_configuration::score_extra_encompass (Slur_score_state const &state)
   // we find forbidden attachments
   vector<Offset> forbidden_attachments;
   for (vsize i = 0; i < state.extra_encompass_infos_.size (); i++)
-    if (Tie::has_interface (state.extra_encompass_infos_[i].grob_))
+    if (has_interface<Tie> (state.extra_encompass_infos_[i].grob_))
       {
         Grob *t = state.extra_encompass_infos_[i].grob_;
         Grob *common_x = Grob::get_vertical_axis_group (t);
@@ -398,19 +415,19 @@ Slur_configuration::score_extra_encompass (Slur_score_state const &state)
         }
 
       Real dist = 0.0;
-      if (info.type_ == ly_symbol2scm ("around"))
+      if (scm_is_eq (info.type_, ly_symbol2scm ("around")))
         dist = info.extents_[Y_AXIS].distance (y);
 
       /*
         Have to score too: the curve enumeration is limited in its
         shape, and may produce curves which collide anyway.
        */
-      else if (info.type_ == ly_symbol2scm ("inside"))
+      else if (scm_is_eq (info.type_, ly_symbol2scm ("inside")))
         dist = state.dir_ * (y - info.extents_[Y_AXIS][state.dir_]);
       else
         programming_error ("unknown avoidance type");
 
-      dist = max (dist, 0.0);
+      dist = std::max (dist, 0.0);
 
       Real penalty = info.penalty_ * peak_around (0.1 * state.parameters_.extra_encompass_free_distance_,
                                                   state.parameters_.extra_encompass_free_distance_,
@@ -456,7 +473,7 @@ Slur_configuration::score_slopes (Slur_score_state const &state)
   Real slur_dy = slur_dz[Y_AXIS];
   Real demerit = 0.0;
 
-  demerit += max ((fabs (slur_dy / slur_dz[X_AXIS])
+  demerit += std::max ((fabs (slur_dy / slur_dz[X_AXIS])
                    - state.parameters_.max_slope_), 0.0)
              * state.parameters_.max_slope_factor_;
 
@@ -467,9 +484,9 @@ Slur_configuration::score_slopes (Slur_score_state const &state)
 
   if (!state.is_broken_)
     demerit += state.parameters_.steeper_slope_factor_
-               * (max (fabs (slur_dy) - max_dy, 0.0));
+               * (std::max (fabs (slur_dy) - max_dy, 0.0));
 
-  demerit += max ((fabs (slur_dy / slur_dz[X_AXIS])
+  demerit += std::max ((fabs (slur_dy / slur_dz[X_AXIS])
                    - state.parameters_.max_slope_), 0.0)
              * state.parameters_.max_slope_factor_;