]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/slur-scoring.cc
Doc-es: various updates.
[lilypond.git] / lily / slur-scoring.cc
index 3d929ca750038217ed528e571bc10161ba80afa8..a3dad6fb5e9785888b05b119ac5320b24c0b36b0 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 1996--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  Copyright (C) 1996--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
   Jan Nieuwenhuizen <janneke@gnu.org>
 
   LilyPond is free software: you can redistribute it and/or modify
@@ -32,6 +32,7 @@
 #include "main.hh"
 #include "misc.hh"
 #include "note-column.hh"
+#include "note-head.hh"
 #include "output-def.hh"
 #include "paper-column.hh"
 #include "pitch.hh"
@@ -42,7 +43,6 @@
 #include "staff-symbol-referencer.hh"
 #include "staff-symbol.hh"
 #include "stem.hh"
-#include "time-signature.hh"
 #include "warn.hh"
 
 /*
@@ -69,7 +69,6 @@ Slur_score_state::Slur_score_state ()
 {
   musical_dy_ = 0.0;
   valid_ = false;
-  stub_ = false;
   edge_has_beams_ = false;
   has_same_beam_ = false;
   is_broken_ = false;
@@ -108,15 +107,15 @@ Slur_score_state::slur_direction () const
 Encompass_info
 Slur_score_state::get_encompass_info (Grob *col) const
 {
-  Grob *stem = unsmob_grob (col->get_object ("stem"));
+  Grob *stem = unsmob<Grob> (col->get_object ("stem"));
   Encompass_info ei;
 
   if (!stem)
     {
       programming_error ("no stem for note column");
       ei.x_ = col->relative_coordinate (common_[X_AXIS], X_AXIS);
-      ei.head_ = ei.stem_ = col->maybe_pure_extent (common_[Y_AXIS],
-                                         Y_AXIS, stub_, 0, INT_MAX)[dir_];
+      ei.head_ = ei.stem_ = col->extent (common_[Y_AXIS],
+                                         Y_AXIS)[dir_];
       return ei;
     }
   Direction stem_dir = get_grob_direction (stem);
@@ -129,16 +128,16 @@ Slur_score_state::get_encompass_info (Grob *col) const
   Grob *h = Stem::extremal_heads (stem)[Direction (dir_)];
   if (!h)
     {
-      ei.head_ = ei.stem_ = col->maybe_pure_extent (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX)[dir_];
+      ei.head_ = ei.stem_ = col->extent (common_[Y_AXIS], Y_AXIS)[dir_];
       return ei;
     }
 
-  ei.head_ = h->maybe_pure_extent (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX)[dir_];
+  ei.head_ = h->extent (common_[Y_AXIS], Y_AXIS)[dir_];
 
   if ((stem_dir == dir_)
-      && !stem->maybe_pure_extent (stem, Y_AXIS, stub_, 0, INT_MAX).is_empty ())
+      && !stem->extent (stem, Y_AXIS).is_empty ())
     {
-      ei.stem_ = stem->maybe_pure_extent (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX)[dir_];
+      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_beam_thickness (b);
 
@@ -163,7 +162,7 @@ Slur_score_state::get_bound_info () const
   for (LEFT_and_RIGHT (d))
     {
       extremes[d].bound_ = slur_->get_bound (d);
-      if (Note_column::has_interface (extremes[d].bound_))
+      if (has_interface<Note_column> (extremes[d].bound_))
         {
           extremes[d].note_column_ = extremes[d].bound_;
           extremes[d].stem_ = Note_column::get_stem (extremes[d].note_column_);
@@ -176,13 +175,9 @@ Slur_score_state::get_bound_info () const
               for (int a = X_AXIS; a < NO_AXES; a++)
                 {
                   Axis ax = Axis (a);
-                  Interval s = ax == Y_AXIS
-                               ? extremes[d].stem_->maybe_pure_extent (common_[ax], ax, stub_, 0, INT_MAX)
-                               : extremes[d].stem_->extent (common_[ax], ax);
+                  Interval s = extremes[d].stem_->extent (common_[ax], ax);
                   if (extremes[d].flag_)
-                    s.unite (ax == Y_AXIS
-                             ? extremes[d].flag_->maybe_pure_extent (common_[ax], ax, stub_, 0, INT_MAX)
-                             : extremes[d].flag_->extent (common_[ax], ax));
+                    s.unite (extremes[d].flag_->extent (common_[ax], ax));
                   if (s.is_empty ())
                     {
                       /*
@@ -190,9 +185,7 @@ Slur_score_state::get_bound_info () const
                         whole notes.
                       */
                       s = Interval (0, 0)
-                          + (ax == Y_AXIS
-                             ? extremes[d].stem_->maybe_pure_coordinate (common_[ax], ax, stub_, 0, INT_MAX)
-                             : extremes[d].stem_->relative_coordinate (common_[ax], ax));
+                          + extremes[d].stem_->relative_coordinate (common_[ax], ax);
                     }
                   extremes[d].stem_extent_[ax] = s;
                 }
@@ -208,11 +201,14 @@ Slur_score_state::get_bound_info () const
                                          ::staff_space (extremes[d].stem_);
             }
 
-          if (extremes[d].slur_head_)
-            extremes[d].slur_head_x_extent_
-              = extremes[d].slur_head_->extent (common_[X_AXIS], X_AXIS);
-
         }
+      else if (has_interface<Note_head> (extremes[d].bound_))
+        {
+          extremes[d].slur_head_ = extremes[d].bound_;
+        }
+      if (extremes[d].slur_head_)
+        extremes[d].slur_head_x_extent_
+          = extremes[d].slur_head_->extent (common_[X_AXIS], X_AXIS);
     }
 
   return extremes;
@@ -222,8 +218,6 @@ void
 Slur_score_state::fill (Grob *me)
 {
   slur_ = dynamic_cast<Spanner *> (me);
-  stub_ = slur_->internal_has_interface (ly_symbol2scm ("cross-staff-stub-interface"));
-
   columns_
     = internal_extract_grob_array (me, ly_symbol2scm ("note-columns"));
 
@@ -235,8 +229,8 @@ Slur_score_state::fill (Grob *me)
 
   Slur::replace_breakable_encompass_objects (me);
   staff_space_ = Staff_symbol_referencer::staff_space (me);
-  Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
-  thickness_ = robust_scm2double (me->get_property ("thickness"), 1.0) * lt;
+  line_thickness_ = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
+  thickness_ = robust_scm2double (me->get_property ("thickness"), 1.0) * line_thickness_;
 
   dir_ = slur_direction ();
   parameters_.fill (me);
@@ -264,8 +258,8 @@ Slur_score_state::fill (Grob *me)
     }
 
   extremes_ = get_bound_info ();
-  is_broken_ = (!extremes_[LEFT].note_column_
-                || !extremes_[RIGHT].note_column_);
+  is_broken_ = (!(extremes_[LEFT].note_column_ || extremes_[LEFT].slur_head_)
+                || !(extremes_[RIGHT].note_column_ || extremes_[RIGHT].slur_head_));
 
   has_same_beam_
     = (extremes_[LEFT].stem_ && extremes_[RIGHT].stem_
@@ -291,11 +285,12 @@ Slur_score_state::fill (Grob *me)
                                          end_ys[RIGHT],
                                          end_ys[LEFT]);
       Real encompass_place = extra_encompass_infos_[i].extents_[Y_AXIS][dir_];
-      if (extra_encompass_infos_[i].type_ == ly_symbol2scm ("inside")
+      if (scm_is_eq (extra_encompass_infos_[i].type_,
+                     ly_symbol2scm ("inside"))
           && minmax (dir_, encompass_place, y_place) == encompass_place
           && (!extra_encompass_infos_[i].grob_->internal_has_interface (ly_symbol2scm ("key-signature-interface"))
-              && !Clef::has_interface (extra_encompass_infos_[i].grob_)
-              && !Time_signature::has_interface (extra_encompass_infos_[i].grob_)))
+              && !has_interface<Clef> (extra_encompass_infos_[i].grob_)
+              && !extra_encompass_infos_[i].grob_->internal_has_interface (ly_symbol2scm ("time-signature-interface"))))
         {
           for (LEFT_and_RIGHT (d))
             additional_ys[d] = minmax (dir_,
@@ -325,7 +320,7 @@ Slur_score_state::fill (Grob *me)
       if (!is_broken_
           && extremes_[d].slur_head_)
         musical_dy_ += d
-                       * extremes_[d].slur_head_->maybe_pure_coordinate (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX);
+                       * extremes_[d].slur_head_->relative_coordinate (common_[Y_AXIS], Y_AXIS);
     }
 
   edge_has_beams_
@@ -340,14 +335,7 @@ MAKE_SCHEME_CALLBACK (Slur, calc_control_points, 1)
 SCM
 Slur::calc_control_points (SCM smob)
 {
-  Spanner *me = unsmob_spanner (smob);
-
-  if (!to_boolean (me->get_property ("cross-staff"))
-      && me->internal_has_interface (ly_symbol2scm ("cross-staff-stub-interface")))
-    {
-      me->suicide ();
-      return SCM_EOL;
-    }
+  Spanner *me = unsmob<Spanner> (smob);
 
   Slur_score_state state;
   state.fill (me);
@@ -388,9 +376,7 @@ Slur::calc_control_points (SCM smob)
     {
       Offset o = best->curve_.control_[i]
                  - Offset (me->relative_coordinate (state.common_[X_AXIS], X_AXIS),
-                           me->maybe_pure_coordinate (state.common_[Y_AXIS], Y_AXIS,
-                               state.stub_, 0, INT_MAX));
-
+                           me->relative_coordinate (state.common_[Y_AXIS], Y_AXIS));
       controls = scm_cons (ly_offset2scm (o), controls);
     }
 
@@ -477,12 +463,21 @@ Slur_score_state::get_y_attachment_range () const
     {
       if (extremes_[d].note_column_)
         {
-          end_ys[d] = dir_
-                      * max (max (dir_ * (base_attachments_[d][Y_AXIS]
-                                          + parameters_.region_size_ * dir_),
-                                  dir_ * (dir_ + extremes_[d].note_column_->maybe_pure_extent
-                                                   (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX)[dir_])),
-                             dir_ * base_attachments_[-d][Y_AXIS]);
+          Interval nc_extent = extremes_[d].note_column_
+                               ->extent (common_[Y_AXIS], Y_AXIS);
+          if (nc_extent.is_empty ())
+            slur_->warning ("slur trying to encompass an empty note column.");
+          else
+            end_ys[d] = dir_
+                        * max (max (dir_ * (base_attachments_[d][Y_AXIS]
+                                            + parameters_.region_size_ * dir_),
+                                    dir_ * (dir_ + nc_extent[dir_])),
+                               dir_ * base_attachments_[-d][Y_AXIS]);
+        }
+      else if (extremes_[d].slur_head_)
+        {
+          // allow only minimal movement
+          end_ys[d] = base_attachments_[d][Y_AXIS] + 0.3 * dir_;
         }
       else
         end_ys[d] = base_attachments_[d][Y_AXIS] + parameters_.region_size_ * dir_;
@@ -531,7 +526,7 @@ Slur_score_state::get_base_attachments () const
                   || has_same_beam_))
             y = extremes_[d].stem_extent_[Y_AXIS][dir_];
           else if (head)
-            y = head->maybe_pure_extent (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX)[dir_];
+            y = head->extent (common_[Y_AXIS], Y_AXIS)[dir_];
           y += dir_ * 0.5 * staff_space_;
 
           y = move_away_from_staffline (y, head);
@@ -542,12 +537,22 @@ Slur_score_state::get_base_attachments () const
                : extremes_[d].bound_->extent (common_[X_AXIS], X_AXIS))
               .linear_combination (CENTER);
         }
+      else if (head)
+        {
+          y = head->extent (common_[Y_AXIS], Y_AXIS)
+            .linear_combination (0.5*dir_);
+
+          // Don't "move_away_from_staffline" because that makes it
+          // harder to recognize the specific attachment point
+          x = head->extent (common_[X_AXIS], X_AXIS)[-d];
+        }
+
       base_attachment[d] = Offset (x, y);
     }
 
   for (LEFT_and_RIGHT (d))
     {
-      if (!extremes_[d].note_column_)
+      if (!extremes_[d].note_column_ && !extremes_[d].slur_head_)
         {
           Real x = 0;
           Real y = 0;
@@ -563,7 +568,7 @@ Slur_score_state::get_base_attachments () const
 
           if (extremes_[-d].bound_ != col)
             {
-              y = maybe_pure_robust_relative_extent (col, common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX)[dir_];
+              y = robust_relative_extent (col, common_[Y_AXIS], Y_AXIS)[dir_];
               y += dir_ * 0.5 * staff_space_;
 
               if (get_grob_direction (col) == dir_
@@ -609,8 +614,8 @@ Slur_score_state::move_away_from_staffline (Real y,
     return y;
 
   Real pos
-    = (y - staff_symbol->maybe_pure_coordinate (common_[Y_AXIS],
-                                              Y_AXIS, stub_, 0, INT_MAX))
+    = (y - staff_symbol->relative_coordinate (common_[Y_AXIS],
+                                              Y_AXIS))
       * 2.0 / staff_space_;
 
   if (fabs (pos - my_round (pos)) < 0.2
@@ -641,23 +646,24 @@ Slur_score_state::generate_avoid_offsets () const
   extract_grob_set (slur_, "encompass-objects", extra_encompasses);
   for (vsize i = 0; i < extra_encompasses.size (); i++)
     {
-      if (Slur::has_interface (extra_encompasses[i]))
+      if (has_interface<Slur> (extra_encompasses[i]))
         {
           Grob *small_slur = extra_encompasses[i];
           Bezier b = Slur::get_curve (small_slur);
 
           Offset z = b.curve_point (0.5);
           z += Offset (small_slur->relative_coordinate (common_[X_AXIS], X_AXIS),
-                       small_slur->maybe_pure_coordinate (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX));
+                       small_slur->relative_coordinate (common_[Y_AXIS], Y_AXIS));
 
           z[Y_AXIS] += dir_ * parameters_.free_slur_distance_;
           avoid.push_back (z);
         }
-      else if (extra_encompasses[i]->get_property ("avoid-slur") == ly_symbol2scm ("inside"))
+      else if (scm_is_eq (extra_encompasses[i]->get_property ("avoid-slur"),
+                          ly_symbol2scm ("inside")))
         {
           Grob *g = extra_encompasses [i];
           Interval xe = g->extent (common_[X_AXIS], X_AXIS);
-          Interval ye = g->maybe_pure_extent (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX);
+          Interval ye = g->extent (common_[Y_AXIS], Y_AXIS);
 
           if (!xe.is_empty ()
               && !ye.is_empty ())
@@ -734,7 +740,7 @@ Slur_score_state::enumerate_attachments (Drul_array<Real> end_ys) const
                 }
             }
 
-          dz = os[RIGHT] - os[LEFT];
+          dz = (os[RIGHT] - os[LEFT]).direction ();
           for (LEFT_and_RIGHT (d))
             {
               if (extremes_[d].slur_head_
@@ -746,7 +752,7 @@ Slur_score_state::enumerate_attachments (Drul_array<Real> end_ys) const
                      TODO: parameter */
                   os[d][X_AXIS]
                   -= dir_ * extremes_[d].slur_head_x_extent_.length ()
-                     * sin (dz.arg ()) / 3;
+                    * dz[Y_AXIS] / 3;
                 }
             }
 
@@ -769,13 +775,13 @@ Slur_score_state::get_extra_encompass_infos () const
   vector<Extra_collision_info> collision_infos;
   for (vsize i = encompasses.size (); i--;)
     {
-      if (Slur::has_interface (encompasses[i]))
+      if (has_interface<Slur> (encompasses[i]))
         {
           Spanner *small_slur = dynamic_cast<Spanner *> (encompasses[i]);
           Bezier b = Slur::get_curve (small_slur);
 
           Offset relative (small_slur->relative_coordinate (common_[X_AXIS], X_AXIS),
-                           small_slur->maybe_pure_coordinate (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX));
+                           small_slur->relative_coordinate (common_[Y_AXIS], Y_AXIS));
 
           for (int k = 0; k < 3; k++)
             {
@@ -809,13 +815,13 @@ Slur_score_state::get_extra_encompass_infos () const
         {
           Grob *g = encompasses [i];
           Interval xe = g->extent (common_[X_AXIS], X_AXIS);
-          Interval ye = g->maybe_pure_extent (common_[Y_AXIS], Y_AXIS, stub_, 0, INT_MAX);
-          if (Dots::has_interface (g))
+          Interval ye = g->extent (common_[Y_AXIS], Y_AXIS);
+          if (has_interface<Dots> (g))
             ye.widen (0.2);
 
           Real xp = 0.0;
           Real penalty = parameters_.extra_object_collision_penalty_;
-          if (Accidental_interface::has_interface (g))
+          if (has_interface<Accidental_interface> (g))
             {
               penalty = parameters_.accidental_collision_;