X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbeam.cc;h=a9a19b38c72fae30731caa1f58dea78b65499a6d;hb=47db9a3883d726ca53e2133a3b2298f78dd6a32e;hp=d73169a917181d046e8dfc50f9bd9cbc40b9d112;hpb=2a872121379fffe7b1cd5d23048b7ea04b4d1f68;p=lilypond.git diff --git a/lily/beam.cc b/lily/beam.cc index d73169a917..a9a19b38c7 100644 --- a/lily/beam.cc +++ b/lily/beam.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 1997--2012 Han-Wen Nienhuys + Copyright (C) 1997--2015 Han-Wen Nienhuys Jan Nieuwenhuizen 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 (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 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 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 ys = robust_scm2drul (ys_scm, Drul_array (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 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