]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/stem.cc
[mf] Prevent recreation of fonts at each call of `make' with recent mpost.
[lilypond.git] / lily / stem.cc
index 11cf6def8b6e66d4d02045fb85b1dd31aa77a76c..5b1a3d5041423e488e9cdc40eba25f4f7bf7a34a 100644 (file)
@@ -331,6 +331,7 @@ Stem::calc_length (SCM smob)
   int durlog = duration_log (me);
 
   Real ss = Staff_symbol_referencer::staff_space (me);
+  Real staff_rad = Staff_symbol_referencer::staff_radius (me);
   Real length = 7;
   SCM s = ly_assoc_get (ly_symbol2scm ("lengths"), details, SCM_EOL);
   if (scm_is_pair (s))
@@ -346,11 +347,25 @@ Stem::calc_length (SCM smob)
       SCM sshorten = ly_assoc_get (ly_symbol2scm ("stem-shorten"), details, SCM_EOL);
       SCM scm_shorten = scm_is_pair (sshorten)
        ? robust_list_ref (max (duration_log (me) - 2, 0), sshorten) : SCM_EOL;
-      Real shorten = 2* robust_scm2double (scm_shorten, 0);
-
-      /* On boundary: shorten only half */
-      if (abs (head_positions (me)[dir]) <= 1)
-       shorten *= 0.5;
+      Real shorten_property = 2 * robust_scm2double (scm_shorten, 0);
+      /*  change in length between full-size and shortened stems is executed gradually.
+          "transition area" = stems between full-sized and fully-shortened.
+          */
+      Real quarter_stem_length = 2 * scm_to_double (robust_list_ref (0, s));
+      /*  shortening_step = difference in length between consecutive stem lengths
+          in transition area. The bigger the difference between full-sized
+          and shortened stems, the bigger shortening_step is.
+          (but not greater than 1/2 and not smaller than 1/4).
+          value 6 is heuristic; it determines the suggested transition slope steepnesas.
+          */
+      Real shortening_step = min (max (0.25, (shorten_property / 6)), 0.5);
+      /*  Shortening of unflagged stems should begin on the first stem that sticks
+          more than 1 staffspace (2 units) out of the staff.
+          Shortening of flagged stems begins in the same moment as unflagged ones,
+          but not earlier than on the middle line note.
+          */
+      Real which_step = (min (1.0, quarter_stem_length - (2 * staff_rad) - 2.0)) + abs(hp[dir]);
+      Real shorten = min (max (0.0, (shortening_step * which_step)), shorten_property);
 
       length -= shorten;
     }
@@ -718,6 +733,32 @@ Stem::thickness (Grob *me)
     * Staff_symbol_referencer::line_thickness (me);
 }
 
+MAKE_SCHEME_CALLBACK (Stem, calc_stem_begin_position, 1);
+SCM
+Stem::calc_stem_begin_position (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  Direction d = get_grob_direction (me);
+  Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5;
+  Grob *lh
+    = to_boolean (me->get_property ("avoid-note-head"))
+    ? last_head (me)
+    : first_head (me);
+
+  Real pos = Staff_symbol_referencer::get_position (lh);
+
+  if (Grob *head = support_head (me))
+    {
+      Interval head_height = head->extent (head, Y_AXIS);
+      Real y_attach = Note_head::stem_attachment_coordinate (head, Y_AXIS);
+
+      y_attach = head_height.linear_combination (y_attach);
+      pos += d * y_attach / half_space;
+    }
+
+  return scm_from_double (pos);
+}
+
 MAKE_SCHEME_CALLBACK (Stem, print, 1);
 SCM
 Stem::print (SCM smob)
@@ -756,7 +797,7 @@ Stem::print (SCM smob)
   Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5;
 
   if (lh)
-    y2 = Staff_symbol_referencer::get_position (lh);
+    y2 = robust_scm2double (me->get_property ("stem-begin-position"), 0.0);
   else if (stemlet)
     {
       Real beam_translation = Beam::get_beam_translation (beam);
@@ -771,18 +812,6 @@ Stem::print (SCM smob)
 
   Interval stem_y (min (y1, y2), max (y2, y1));
 
-  if (Grob *head = support_head (me))
-    {
-      /*
-       must not take ledgers into account.
-      */
-      Interval head_height = head->extent (head, Y_AXIS);
-      Real y_attach = Note_head::stem_attachment_coordinate (head, Y_AXIS);
-
-      y_attach = head_height.linear_combination (y_attach);
-      stem_y[Direction (-d)] += d * y_attach / half_space;
-    }
-
   // URG
   Real stem_width = thickness (me);
   Real blot
@@ -1095,6 +1124,7 @@ ADD_INTERFACE (Stem,
               "note-heads "
               "positioning-done "
               "rests "
+              "stem-begin-position "
               "stem-end-position "
               "stem-info "
               "stemlet-length "