]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/beam.cc
* input/regression/beam-quant-standard.ly: reindent, set
[lilypond.git] / lily / beam.cc
index 2ee9e7086c67c6b15fd1e277d3d785eae799102c..9cd5793264647d2b3387ec178fdd0e419419e699 100644 (file)
@@ -69,15 +69,17 @@ Beam::get_thickness (Grob *me)
 Real
 Beam::get_beam_translation (Grob *me)
 {
-  SCM func = me->get_property ("space-function");
+  int beam_count = get_beam_count (me);
+  Real staff_space = Staff_symbol_referencer::staff_space (me);
+  Real line = Staff_symbol_referencer::line_thickness (me);
+  Real thickness = get_thickness (me);
+  Real fract = robust_scm2double (me->get_property ("length-fraction"), 1.0);
+  
+  Real beam_translation = beam_count < 4
+    ? (2 * staff_space + line - thickness) / 2.0
+    : (3 * staff_space + line - thickness) / 3.0;
 
-  if (ly_is_procedure (func))
-    {
-      SCM s = scm_call_2 (func, me->self_scm (), scm_from_int (get_beam_count (me)));
-      return scm_to_double (s);
-    }
-  else
-    return 0.81;
+  return fract * beam_translation;
 }
 
 /* Maximum beam_count. */
@@ -95,25 +97,6 @@ Beam::get_beam_count (Grob *me)
   return m;
 }
 
-/*
-  Space return space between beams.
-*/
-MAKE_SCHEME_CALLBACK (Beam, space_function, 2);
-SCM
-Beam::space_function (SCM smob, SCM beam_count)
-{
-  Grob *me = unsmob_grob (smob);
-
-  Real staff_space = Staff_symbol_referencer::staff_space (me);
-  Real line = Staff_symbol_referencer::line_thickness (me);
-  Real thickness = get_thickness (me);
-
-  Real beam_translation = scm_to_int (beam_count) < 4
-    ? (2 * staff_space + line - thickness) / 2.0
-    : (3 * staff_space + line - thickness) / 3.0;
-
-  return scm_from_double (beam_translation);
-}
 
 /* After pre-processing all directions should be set.
    Several post-processing routines (stem, slur, script) need stem/beam
@@ -135,6 +118,8 @@ Beam::calc_direction (SCM smob)
      For a beam that  only has one stem, we try to do some disappearance magic:
      we revert the flag, and move on to The Eternal Engraving Fields. */
 
+  Direction d = CENTER;
+
   int count = visible_stem_count (me);
   if (count < 2)
     {
@@ -153,21 +138,32 @@ Beam::calc_direction (SCM smob)
          me->suicide ();
          return SCM_UNSPECIFIED;
        }
+      else
+       {
+         /*
+           ugh.
+
+           can happen in stem-tremolo case.
+           TODO: fixme.
+          */
+         d = Stem::get_default_dir (stems[0]);
+       }
     }
 
-  Direction d = CENTER;
   
   if (count >= 1)
     {
       d = get_default_dir (me);
       consider_auto_knees (me);
-      set_stem_directions (me, d);
+    }
 
+  if (d)
+    {
+      set_stem_directions (me, d);
       connect_beams (me);
-
       set_stem_shorten (me);
     }
-
+  
   return scm_from_int (d);
 }
 
@@ -427,10 +423,11 @@ Beam::print (SCM grob)
          if (stem)
            {
              int t = Stem::duration_log (stem);
-
-             SCM proc = me->get_property ("flag-width-function");
-             SCM result = scm_call_1 (proc, scm_from_int (t));
-             nw_f = scm_to_double (result);
+             // ugh. hardcoded.
+             if (t == 1)
+               nw_f = 1.98;
+             else
+               nw_f = 1.32;
            }
          else
            nw_f = break_overshoot[RIGHT] / 2;
@@ -508,9 +505,11 @@ Beam::print (SCM grob)
 
       Direction stem_dir = stems.size () ? to_dir (stems[0]->get_property ("direction")) : UP;
 
-      Stencil tm = *unsmob_stencil (Text_interface::interpret_markup
+      Stencil score = *unsmob_stencil (Text_interface::interpret_markup
                                    (me->get_layout ()->self_scm (), properties, quant_score));
-      the_beam.add_at_edge (Y_AXIS, stem_dir, tm, 1.0, 0);
+
+      if (!score.is_empty ())
+       the_beam.add_at_edge (Y_AXIS, stem_dir, score, 1.0, 0);
     }
 #endif
 
@@ -544,18 +543,18 @@ Beam::get_default_dir (Grob *me)
        }
     }
 
-  SCM func = me->get_property ("dir-function");
-  SCM s = scm_call_2 (func,
-                     scm_cons (scm_from_int (count[UP]),
-                               scm_from_int (count[DOWN])),
-                     scm_cons (scm_from_int (total[UP]),
-                               scm_from_int (total[DOWN])));
-
-  if (scm_is_number (s) && scm_to_int (s))
-    return to_dir (s);
-
-  /* If dir is not determined: get default */
-  return to_dir (me->get_property ("neutral-direction"));
+  Direction dir = CENTER;
+  
+  if (Direction d =  (Direction) sign (count[UP] - count[DOWN]))
+    dir = d;
+  else if (Direction d = (Direction)  sign (total[UP] / count[UP] - total[DOWN]/count[DOWN]))
+    dir = d;
+  else if (Direction d = (Direction)  sign (total[UP] - total[DOWN]))
+    dir = d;
+  else
+    dir = to_dir (me->get_property ("neutral-direction"));
+  
+  return dir;
 }
 
 /* Set all stems with non-forced direction to beam direction.
@@ -741,14 +740,11 @@ Beam::calc_positions (SCM smob)
   for (SCM i = callbacks; scm_is_pair (i); i = scm_cdr (i))
     scm_call_1 (scm_car (i), me->self_scm ());
 
-  /*
-    TODO: move this in separate calc function.
-   */
-  set_stem_lengths (me);
   return SCM_UNSPECIFIED;
 }
 
 
+
 void
 set_minimum_dy (Grob *me, Real *dy)
 {
@@ -772,23 +768,19 @@ set_minimum_dy (Grob *me, Real *dy)
 }
 
 /*
-  Compute  a first approximation to the beam slope.
+  Compute a first approximation to the beam slope.
 */
-MAKE_SCHEME_CALLBACK (Beam, least_squares, 1);
+MAKE_SCHEME_CALLBACK (Beam, calc_least_squares_positions, 2);
 SCM
-Beam::least_squares (SCM smob)
+Beam::calc_least_squares_positions (SCM smob, SCM posns)
 {
+  (void) posns;
+  
   Grob *me = unsmob_grob (smob);
 
   int count = visible_stem_count (me);
   Interval pos (0, 0);
 
-  if (count < 1)
-    {
-      me->set_property ("positions", ly_interval2scm (pos));
-      return SCM_UNSPECIFIED;
-    }
-
   Array<Real> x_posns;
   extract_grob_set (me, "stems", stems);
   Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS);
@@ -817,7 +809,7 @@ Beam::least_squares (SCM smob)
   Real y = 0;
   Real slope = 0;
   Real dy = 0;
-
+  Real ldy = 0.0;
   if (!ideal.delta ())
     {
       Interval chord (Stem::chord_start_y (first_visible_stem (me)),
@@ -845,8 +837,7 @@ Beam::least_squares (SCM smob)
        slope esp. of the first part of a broken beam should predict
        where the second part goes.
       */
-      me->set_property ("least-squares-dy",
-                       scm_from_double (pos[RIGHT] - pos[LEFT]));
+      ldy = pos[RIGHT] - pos[LEFT];
     }
   else
     {
@@ -867,7 +858,8 @@ Beam::least_squares (SCM smob)
       dy = slope * dx;
 
       set_minimum_dy (me, &dy);
-      me->set_property ("least-squares-dy", scm_from_double (dy));
+
+      ldy = dy;
       pos = Interval (y, (y + dy));
     }
 
@@ -876,9 +868,8 @@ Beam::least_squares (SCM smob)
   */
   scale_drul (&pos, 1 / Staff_symbol_referencer::staff_space (me));
 
-  me->set_property ("positions", ly_interval2scm (pos));
-
-  return SCM_UNSPECIFIED;
+  me->set_property ("least-squares-dy",  scm_from_double (ldy));
+  return ly_interval2scm (pos);
 }
 
 /*
@@ -888,9 +879,9 @@ Beam::least_squares (SCM smob)
   TODO: we should use the concaveness to control the amount of damping
   applied.
 */
-MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 1);
+MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 2);
 SCM
-Beam::shift_region_to_valid (SCM grob)
+Beam::shift_region_to_valid (SCM grob, SCM posns)
 {
   Grob *me = unsmob_grob (grob);
   /*
@@ -904,7 +895,7 @@ Beam::shift_region_to_valid (SCM grob)
   Grob *fvs = first_visible_stem (me);
 
   if (!fvs)
-    return SCM_UNSPECIFIED;
+    return posns;
 
   Real x0 = fvs->relative_coordinate (commonx, X_AXIS);
   for (int i = 0; i < stems.size (); i++)
@@ -917,11 +908,12 @@ Beam::shift_region_to_valid (SCM grob)
 
   Grob *lvs = last_visible_stem (me);
   if (!lvs)
-    return SCM_UNSPECIFIED;
+    return posns;
 
   Real dx = lvs->relative_coordinate (commonx, X_AXIS) - x0;
 
-  Drul_array<Real> pos = ly_scm2interval (me->get_property ("positions"));
+  Drul_array<Real> pos = ly_scm2interval (posns);
+  
 
   scale_drul (&pos, Staff_symbol_referencer::staff_space (me));
 
@@ -978,28 +970,35 @@ Beam::shift_region_to_valid (SCM grob)
   pos = Drul_array<Real> (y, (y + dy));
   scale_drul (&pos, 1 / Staff_symbol_referencer::staff_space (me));
 
-  me->set_property ("positions", ly_interval2scm (pos));
-  return SCM_UNSPECIFIED;
+  return ly_interval2scm (pos);
 }
 
 /* This neat trick is by Werner Lemberg,
    damped = tanh (slope)
    corresponds with some tables in [Wanske] CHECKME */
-MAKE_SCHEME_CALLBACK (Beam, slope_damping, 1);
+MAKE_SCHEME_CALLBACK (Beam, slope_damping, 2);
 SCM
-Beam::slope_damping (SCM smob)
+Beam::slope_damping (SCM smob, SCM posns)
 {
   Grob *me = unsmob_grob (smob);
+  Drul_array<Real> pos = ly_scm2interval (posns);
 
   if (visible_stem_count (me) <= 1)
     return SCM_UNSPECIFIED;
 
+  
   SCM s = me->get_property ("damping");
   Real damping = scm_to_double (s);
-
+  Real concaveness = robust_scm2double (me->get_property ("concaveness"), 0.0);
+  if (concaveness >= 10000)
+    {
+      pos[LEFT] = pos[RIGHT];
+      me->set_property ("least-squares-dy", scm_from_double (0));
+      damping = 0;
+    }
+  
   if (damping)
     {
-      Drul_array<Real> pos = ly_scm2interval (me->get_property ("positions"));
       scale_drul (&pos, Staff_symbol_referencer::staff_space (me));
 
       Real dy = pos[RIGHT] - pos[LEFT];
@@ -1014,8 +1013,6 @@ Beam::slope_damping (SCM smob)
 
       Real slope = dy && dx ? dy / dx : 0;
 
-      Real concaveness = robust_scm2double (me->get_property ("concaveness"), 0.0);
-
       slope = 0.6 * tanh (slope) / (damping + concaveness);
 
       Real damped_dy = slope * dx;
@@ -1026,10 +1023,9 @@ Beam::slope_damping (SCM smob)
       pos[RIGHT] -= (dy - damped_dy) / 2;
 
       scale_drul (&pos, 1 / Staff_symbol_referencer::staff_space (me));
-
-      me->set_property ("positions", ly_interval2scm (pos));
     }
-  return SCM_UNSPECIFIED;
+
+  return ly_interval2scm (pos);
 }
 
 /*
@@ -1095,18 +1091,21 @@ Beam::calc_stem_y (Grob *me, Grob *s, Grob ** common,
   Hmm.  At this time, beam position and slope are determined.  Maybe,
   stem directions and length should set to relative to the chord's
   position of the beam.  */
-void
-Beam::set_stem_lengths (Grob *me)
+MAKE_SCHEME_CALLBACK(Beam, set_stem_lengths, 2); 
+SCM
+Beam::set_stem_lengths (SCM smob,  SCM posns)
 {
+  Grob *me = unsmob_grob (smob);
+  
   extract_grob_set (me, "stems", stems);
   if (!stems.size ())
-    return;
+    return posns;
 
   Grob *common[2];
   for (int a = 2; a--;)
     common[a] = common_refpoint_of_array (stems, me, Axis (a));
 
-  Drul_array<Real> pos = ly_scm2realdrul (me->get_property ("positions"));
+  Drul_array<Real> pos = ly_scm2realdrul (posns);
   Real staff_space = Staff_symbol_referencer::staff_space (me);
   scale_drul (&pos, staff_space);
 
@@ -1146,6 +1145,8 @@ Beam::set_stem_lengths (Grob *me)
 
       Stem::set_stemend (s, 2 * stem_y / staff_space);
     }
+
+  return posns;
 }
 
 void
@@ -1395,18 +1396,17 @@ ADD_INTERFACE (Beam,
               "damping "
               "details "
               "direction " 
-              "dir-function "
-              "flag-width-function "
               "gap "
               "gap-count "
               "inspect-quants "
               "knee "
+              "length-fraction "
               "least-squares-dy "
               "neutral-direction "
               "position-callbacks "
               "positions "
               "quant-score "
               "shorten "
-              "space-function "
+              "stems "
               "thickness "
               );