]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/beam.cc
Run grand replace for 2015.
[lilypond.git] / lily / beam.cc
index d73169a917181d046e8dfc50f9bd9cbc40b9d112..a9a19b38c72fae30731caa1f58dea78b65499a6d 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
   Jan Nieuwenhuizen <janneke@gnu.org>
 
   LilyPond is free software: you can redistribute it and/or modify
@@ -145,11 +145,11 @@ MAKE_SCHEME_CALLBACK (Beam, calc_normal_stems, 1);
 SCM
 Beam::calc_normal_stems (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = Grob::unsmob (smob);
 
   extract_grob_set (me, "stems", stems);
   SCM val = Grob_array::make_array ();
-  Grob_array *ga = unsmob_grob_array (val);
+  Grob_array *ga = Grob_array::unsmob (val);
   for (vsize i = 0; i < stems.size (); i++)
     if (Stem::is_normal_stem (stems[i]))
       ga->add (stems[i]);
@@ -161,7 +161,7 @@ MAKE_SCHEME_CALLBACK (Beam, calc_direction, 1);
 SCM
 Beam::calc_direction (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = Grob::unsmob (smob);
 
   /* Beams with less than 2 two stems don't make much sense, but could happen
      when you do
@@ -197,6 +197,18 @@ Beam::calc_direction (SCM smob)
             dir = to_dir (stem->get_property_data ("direction"));
           else
             dir = to_dir (stem->get_property ("default-direction"));
+
+          extract_grob_set (stem, "note-heads", heads);
+          /* default position of Kievan heads with beams is down
+             placing this here avoids warnings downstream */
+          if (heads.size())
+            {
+               if (heads[0]->get_property ("style") == ly_symbol2scm ("kievan"))
+                 {
+                    if (dir == CENTER)
+                      dir = DOWN;
+                 }
+            }
         }
     }
 
@@ -262,7 +274,7 @@ MAKE_SCHEME_CALLBACK (Beam, calc_beaming, 1)
 SCM
 Beam::calc_beaming (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = Grob::unsmob (smob);
 
   extract_grob_set (me, "stems", stems);
 
@@ -341,7 +353,7 @@ Beam::calc_beam_segments (SCM smob)
 {
   /* ugh, this has a side-effect that we need to ensure that
      Stem #'beaming is correct */
-  Grob *me_grob = unsmob_grob (smob);
+  Grob *me_grob = Grob::unsmob (smob);
   (void) me_grob->get_property ("beaming");
 
   Spanner *me = dynamic_cast<Spanner *> (me_grob);
@@ -541,16 +553,14 @@ Beam::calc_beam_segments (SCM smob)
     }
 
   SCM segments_scm = SCM_EOL;
-  SCM *tail = &segments_scm;
 
-  for (vsize i = 0; i < segments.size (); i++)
+  for (vsize i = segments.size (); i--;)
     {
-      *tail = scm_cons (scm_list_2 (scm_cons (ly_symbol2scm ("vertical-count"),
-                                              scm_from_int (segments[i].vertical_count_)),
-                                    scm_cons (ly_symbol2scm ("horizontal"),
-                                              ly_interval2scm (segments[i].horizontal_))),
-                        SCM_EOL);
-      tail = SCM_CDRLOC (*tail);
+      segments_scm = scm_cons (scm_list_2 (scm_cons (ly_symbol2scm ("vertical-count"),
+                                                    scm_from_int (segments[i].vertical_count_)),
+                                          scm_cons (ly_symbol2scm ("horizontal"),
+                                                    ly_interval2scm (segments[i].horizontal_))),
+                              segments_scm);
     }
 
   return segments_scm;
@@ -560,7 +570,7 @@ MAKE_SCHEME_CALLBACK (Beam, calc_x_positions, 1);
 SCM
 Beam::calc_x_positions (SCM smob)
 {
-  Spanner *me = unsmob_spanner (smob);
+  Spanner *me = Spanner::unsmob (smob);
   SCM segments = me->get_property ("beam-segments");
   Interval x_positions;
   x_positions.set_empty ();
@@ -601,7 +611,7 @@ MAKE_SCHEME_CALLBACK (Beam, print, 1);
 SCM
 Beam::print (SCM grob)
 {
-  Spanner *me = unsmob_spanner (grob);
+  Spanner *me = Spanner::unsmob (grob);
   /*
     TODO - mild code dup for all the commonx calls.
     Some use just common_refpoint_of_array, some (in print and
@@ -646,9 +656,9 @@ Beam::print (SCM grob)
   Interval placements = robust_scm2interval (me->get_property ("normalized-endpoints"), Interval (0.0, 0.0));
 
   Stencil the_beam;
-  int extreme = (segments[0].vertical_count_ == 0
-                 ? segments[0].vertical_count_
-                 : segments.back ().vertical_count_);
+  vsize extreme = (segments[0].vertical_count_ == 0
+                   ? segments[0].vertical_count_
+                   : segments.back ().vertical_count_);
 
   for (vsize i = 0; i < segments.size (); i++)
     {
@@ -729,7 +739,7 @@ Beam::print (SCM grob)
 
       Direction stem_dir = stems.size () ? to_dir (stems[0]->get_property ("direction")) : UP;
 
-      Stencil score = *unsmob_stencil (Text_interface::interpret_markup
+      Stencil score = *Stencil::unsmob (Text_interface::interpret_markup
                                        (me->layout ()->self_scm (), properties, annotation));
 
       if (!score.is_empty ())
@@ -848,9 +858,7 @@ Beam::consider_auto_knees (Grob *me)
   if (!scm_is_number (scm))
     return;
 
-  Interval_set gaps;
-
-  gaps.set_full ();
+  vector<Interval> forbidden_intervals;
 
   extract_grob_set (me, "normal-stems", stems);
 
@@ -884,15 +892,17 @@ Beam::consider_auto_knees (Grob *me)
         }
       head_extents_array.push_back (head_extents);
 
-      gaps.remove_interval (head_extents);
+      forbidden_intervals.push_back (head_extents);
     }
 
   Interval max_gap;
   Real max_gap_len = 0.0;
 
-  for (vsize i = gaps.allowed_regions_.size () - 1; i != VPOS; i--)
+  vector<Interval> allowed_regions
+    = Interval_set::interval_union (forbidden_intervals).complement ().intervals ();
+  for (vsize i = allowed_regions.size () - 1; i != VPOS; i--)
     {
-      Interval gap = gaps.allowed_regions_[i];
+      Interval gap = allowed_regions[i];
 
       /*
         the outer gaps are not knees.
@@ -937,7 +947,7 @@ MAKE_SCHEME_CALLBACK (Beam, calc_stem_shorten, 1)
 SCM
 Beam::calc_stem_shorten (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = Grob::unsmob (smob);
 
   /*
     shortening looks silly for x staff beams
@@ -972,7 +982,7 @@ MAKE_SCHEME_CALLBACK (Beam, quanting, 3);
 SCM
 Beam::quanting (SCM smob, SCM ys_scm, SCM align_broken_intos)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = Grob::unsmob (smob);
   Drul_array<Real> ys = robust_scm2drul (ys_scm, Drul_array<Real> (infinity_f, -infinity_f));
   bool cbs = to_boolean (align_broken_intos);
 
@@ -1054,7 +1064,7 @@ MAKE_SCHEME_CALLBACK (Beam, set_stem_lengths, 1);
 SCM
 Beam::set_stem_lengths (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = Grob::unsmob (smob);
 
   /* trigger callbacks. */
   (void) me->get_property ("direction");
@@ -1207,17 +1217,17 @@ MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Beam, rest_collision_callback, 2, 1, "");
 SCM
 Beam::rest_collision_callback (SCM smob, SCM prev_offset)
 {
-  Grob *rest = unsmob_grob (smob);
+  Grob *rest = Grob::unsmob (smob);
   if (scm_is_number (rest->get_property ("staff-position")))
     return scm_from_int (0);
 
   Real offset = robust_scm2double (prev_offset, 0.0);
 
-  Grob *st = unsmob_grob (rest->get_object ("stem"));
+  Grob *st = Grob::unsmob (rest->get_object ("stem"));
   Grob *stem = st;
   if (!stem)
     return scm_from_double (0.0);
-  Grob *beam = unsmob_grob (stem->get_object ("beam"));
+  Grob *beam = Grob::unsmob (stem->get_object ("beam"));
   if (!beam
       || !Beam::has_interface (beam)
       || !Beam::normal_stem_count (beam))
@@ -1291,7 +1301,7 @@ Beam::rest_collision_callback (SCM smob, SCM prev_offset)
 
 /*
   Estimate the position of a rest under a beam,
-  as the average position of its neighboring heads.
+  using the average position of its neighboring heads.
 */
 MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Beam, pure_rest_collision_callback, 4, 1, "");
 SCM
@@ -1302,11 +1312,11 @@ Beam::pure_rest_collision_callback (SCM smob,
 {
   Real previous = robust_scm2double (prev_offset, 0.0);
 
-  Grob *me = unsmob_grob (smob);
-  Grob *stem = unsmob_grob (me->get_object ("stem"));
+  Grob *me = Grob::unsmob (smob);
+  Grob *stem = Grob::unsmob (me->get_object ("stem"));
   if (!stem)
     return scm_from_double (previous);
-  Grob *beam = unsmob_grob (stem->get_object ("beam"));
+  Grob *beam = Grob::unsmob (stem->get_object ("beam"));
   if (!beam
       || !Beam::normal_stem_count (beam)
       || !is_direction (beam->get_property_data ("direction")))
@@ -1314,15 +1324,6 @@ Beam::pure_rest_collision_callback (SCM smob,
 
   Real ss = Staff_symbol_referencer::staff_space (me);
 
-  /*
-    This gives the extrema of rest positions.
-    Even with noteheads on ledgers, beams typically remain within the staff,
-    and push rests at most one staff-space (2 positions) from the staff.
-  */
-  Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
-  Interval rest_max_pos = staff ? Staff_symbol::line_span (staff) : Interval (0.0, 0.0);
-  rest_max_pos.widen (2);
-
   extract_grob_set (beam, "stems", stems);
   vector<Grob *> my_stems;
 
@@ -1353,18 +1354,26 @@ Beam::pure_rest_collision_callback (SCM smob,
       right = my_stems[idx + 1];
     }
 
-  /* In stems with several heads, use the one closest to the beam. */
+  /* Estimate the closest beam to be four positions away from the heads, */
   Direction beamdir = get_grob_direction (beam);
-  Real shift = min (max ( (Stem::head_positions (left)[beamdir]
-                           + Stem::head_positions (right)[beamdir]) / 2.0,
-                          rest_max_pos[DOWN]),
-                    rest_max_pos[UP]
-                   ) * ss / 2.0
-               - previous;
-  /* Always move by a whole number of staff spaces */
-  shift = ceil (fabs (shift / ss)) * ss * sign (shift);
-
-  return scm_from_double (previous + shift);
+  Real beam_pos = (Stem::head_positions (left)[beamdir]
+                   + Stem::head_positions (right)[beamdir]) / 2.0
+                  + 4.0 * beamdir; // four staff-positions
+  /* and that the closest beam never crosses staff center by more than two positions */
+  beam_pos = max (-2.0, beam_pos * beamdir) * beamdir;
+
+  Real minimum_distance
+    = ss * (robust_scm2double (stem->get_property ("stemlet-length"), 0.0)
+            + robust_scm2double (me->get_property ("minimum-distance"), 0.0));
+  Real offset = beam_pos * ss / 2.0
+                - minimum_distance * beamdir
+                - me->extent (me, Y_AXIS)[beamdir];
+
+  /* Always move by a whole number of staff spaces, always away from the beam */
+  offset = floor (min (0.0, (offset - previous) / ss * beamdir))
+           * ss * beamdir + previous;
+
+  return scm_from_double (offset);
 }
 
 bool
@@ -1408,7 +1417,7 @@ MAKE_SCHEME_CALLBACK (Beam, calc_cross_staff, 1)
 SCM
 Beam::calc_cross_staff (SCM smob)
 {
-  return scm_from_bool (is_cross_staff (unsmob_grob (smob)));
+  return scm_from_bool (is_cross_staff (Grob::unsmob (smob)));
 }
 
 int