X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbeam.cc;h=a50f2904bc0b00e4a497c16c908b13cabf38d96b;hb=5d84bfad4626892bcffd05adcced53c8a2329047;hp=48d2be1e6e5c6de1be48262ee18d2c29dd13197b;hpb=c39d188d28fdc84cef8cbaea7b8d6e2fb718c30f;p=lilypond.git diff --git a/lily/beam.cc b/lily/beam.cc index 48d2be1e6e..a50f2904bc 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--2014 Han-Wen Nienhuys + Copyright (C) 1997--2015 Han-Wen Nienhuys Jan Nieuwenhuizen LilyPond is free software: you can redistribute it and/or modify @@ -119,11 +119,13 @@ Beam::get_beam_translation (Grob *me) Real beam_thickness = get_beam_thickness (me); Real fract = robust_scm2double (me->get_property ("length-fraction"), 1.0); - Real beam_translation = beam_count < 4 - ? (2 * staff_space + line - beam_thickness) / 2.0 - : (3 * staff_space + line - beam_thickness) / 3.0; - - return fract * beam_translation; + /* + if fract != 1.0, as is the case for grace notes, we want the gap + to decrease too. To achieve this, we divide the thickness by + fract */ + return (beam_count < 4 + ? (2 * staff_space * fract + line * fract - beam_thickness) / 2.0 + : (3 * staff_space * fract + line * fract - beam_thickness) / 3.0); } /* Maximum beam_count. */ @@ -145,11 +147,11 @@ MAKE_SCHEME_CALLBACK (Beam, calc_normal_stems, 1); SCM Beam::calc_normal_stems (SCM smob) { - Grob *me = unsmob_grob (smob); + Grob *me = unsmob (smob); extract_grob_set (me, "stems", stems); SCM val = Grob_array::make_array (); - Grob_array *ga = unsmob_grob_array (val); + Grob_array *ga = unsmob (val); for (vsize i = 0; i < stems.size (); i++) if (Stem::is_normal_stem (stems[i])) ga->add (stems[i]); @@ -161,7 +163,7 @@ MAKE_SCHEME_CALLBACK (Beam, calc_direction, 1); SCM Beam::calc_direction (SCM smob) { - Grob *me = unsmob_grob (smob); + Grob *me = unsmob (smob); /* Beams with less than 2 two stems don't make much sense, but could happen when you do @@ -203,7 +205,8 @@ Beam::calc_direction (SCM smob) placing this here avoids warnings downstream */ if (heads.size()) { - if (heads[0]->get_property ("style") == ly_symbol2scm ("kievan")) + if (scm_is_eq (heads[0]->get_property ("style"), + ly_symbol2scm ("kievan"))) { if (dir == CENTER) dir = DOWN; @@ -256,7 +259,7 @@ position_with_maximal_common_beams (SCM left_beaming, SCM right_beaming, for (SCM s = scm_car (right_beaming); scm_is_pair (s); s = scm_cdr (s)) { int k = -right_dir * scm_to_int (scm_car (s)) + i; - if (scm_c_memq (scm_from_int (k), left_beaming) != SCM_BOOL_F) + if (scm_is_true (ly_memv (scm_from_int (k), left_beaming))) count++; } @@ -274,7 +277,7 @@ MAKE_SCHEME_CALLBACK (Beam, calc_beaming, 1) SCM Beam::calc_beaming (SCM smob) { - Grob *me = unsmob_grob (smob); + Grob *me = unsmob (smob); extract_grob_set (me, "stems", stems); @@ -353,7 +356,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 = unsmob (smob); (void) me_grob->get_property ("beaming"); Spanner *me = dynamic_cast (me_grob); @@ -570,7 +573,7 @@ MAKE_SCHEME_CALLBACK (Beam, calc_x_positions, 1); SCM Beam::calc_x_positions (SCM smob) { - Spanner *me = unsmob_spanner (smob); + Spanner *me = unsmob (smob); SCM segments = me->get_property ("beam-segments"); Interval x_positions; x_positions.set_empty (); @@ -611,7 +614,7 @@ MAKE_SCHEME_CALLBACK (Beam, print, 1); SCM Beam::print (SCM grob) { - Spanner *me = unsmob_spanner (grob); + Spanner *me = unsmob (grob); /* TODO - mild code dup for all the commonx calls. Some use just common_refpoint_of_array, some (in print and @@ -739,7 +742,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 = *unsmob (Text_interface::interpret_markup (me->layout ()->self_scm (), properties, annotation)); if (!score.is_empty ()) @@ -870,11 +873,11 @@ Beam::consider_auto_knees (Grob *me) { Grob *stem = stems[i]; - Interval head_extents = Stem::head_positions (stem); - if (!head_extents.is_empty ()) + Interval head_extents; + if (Stem::head_count (stem)) { - head_extents[LEFT] += -1; - head_extents[RIGHT] += 1; + head_extents = Stem::head_positions (stem); + head_extents.widen (1); head_extents *= staff_space * 0.5; /* @@ -947,7 +950,7 @@ MAKE_SCHEME_CALLBACK (Beam, calc_stem_shorten, 1) SCM Beam::calc_stem_shorten (SCM smob) { - Grob *me = unsmob_grob (smob); + Grob *me = unsmob (smob); /* shortening looks silly for x staff beams @@ -961,7 +964,7 @@ Beam::calc_stem_shorten (SCM smob) int beam_count = get_beam_count (me); SCM shorten_list = me->get_property ("beamed-stem-shorten"); - if (shorten_list == SCM_EOL) + if (scm_is_null (shorten_list)) return scm_from_int (0); Real staff_space = Staff_symbol_referencer::staff_space (me); @@ -982,7 +985,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 = unsmob (smob); Drul_array ys = robust_scm2drul (ys_scm, Drul_array (infinity_f, -infinity_f)); bool cbs = to_boolean (align_broken_intos); @@ -1003,7 +1006,7 @@ where_are_the_whole_beams (SCM beaming) for (SCM s = scm_car (beaming); scm_is_pair (s); s = scm_cdr (s)) { - if (scm_c_memq (scm_car (s), scm_cdr (beaming)) != SCM_BOOL_F) + if (scm_is_true (ly_memv (scm_car (s), scm_cdr (beaming)))) l.add_point (scm_to_int (scm_car (s))); } @@ -1064,7 +1067,7 @@ MAKE_SCHEME_CALLBACK (Beam, set_stem_lengths, 1); SCM Beam::set_stem_lengths (SCM smob) { - Grob *me = unsmob_grob (smob); + Grob *me = unsmob (smob); /* trigger callbacks. */ (void) me->get_property ("direction"); @@ -1139,8 +1142,8 @@ Beam::set_beaming (Grob *me, Beaming_pattern const *beaming) { Grob *stem = stems[i]; SCM beaming_prop = stem->get_property ("beaming"); - if (beaming_prop == SCM_EOL - || index_get_cell (beaming_prop, d) == SCM_EOL) + if (scm_is_null (beaming_prop) + || scm_is_null (index_get_cell (beaming_prop, d))) { int count = beaming->beamlet_count (i, d); if (i > 0 @@ -1217,21 +1220,23 @@ 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); + if (!scm_is_number (prev_offset)) + prev_offset = SCM_INUM0; + + Grob *rest = unsmob (smob); if (scm_is_number (rest->get_property ("staff-position"))) - return scm_from_int (0); + return prev_offset; - Real offset = robust_scm2double (prev_offset, 0.0); + Grob *stem = unsmob (rest->get_object ("stem")); - Grob *st = unsmob_grob (rest->get_object ("stem")); - Grob *stem = st; if (!stem) - return scm_from_double (0.0); - Grob *beam = unsmob_grob (stem->get_object ("beam")); + return prev_offset; + + Grob *beam = unsmob (stem->get_object ("beam")); if (!beam - || !Beam::has_interface (beam) + || !has_interface (beam) || !Beam::normal_stem_count (beam)) - return scm_from_double (0.0); + return prev_offset; Grob *common_y = rest->common_refpoint (beam, Y_AXIS); @@ -1273,8 +1278,9 @@ Beam::rest_collision_callback (SCM smob, SCM prev_offset) + (beam_count - 1) * beam_translation; Real beam_y = stem_y - d * height_of_my_beams; + Real offset = robust_scm2double (prev_offset, 0.0); Interval rest_extent = rest->extent (rest, Y_AXIS); - rest_extent.translate (offset + rest->get_parent (Y_AXIS)->relative_coordinate (common_y, Y_AXIS)); + rest_extent.translate (offset + rest->parent_relative (common_y, Y_AXIS)); Real rest_dim = rest_extent[d]; Real minimum_distance @@ -1301,7 +1307,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 @@ -1310,29 +1316,21 @@ Beam::pure_rest_collision_callback (SCM smob, SCM, /* end */ SCM prev_offset) { - Real previous = robust_scm2double (prev_offset, 0.0); + if (!scm_is_number (prev_offset)) + prev_offset = SCM_INUM0; - Grob *me = unsmob_grob (smob); - Grob *stem = unsmob_grob (me->get_object ("stem")); + Grob *me = unsmob (smob); + Grob *stem = unsmob (me->get_object ("stem")); if (!stem) - return scm_from_double (previous); - Grob *beam = unsmob_grob (stem->get_object ("beam")); + return prev_offset; + Grob *beam = unsmob (stem->get_object ("beam")); if (!beam || !Beam::normal_stem_count (beam) || !is_direction (beam->get_property_data ("direction"))) - return scm_from_double (previous); + return prev_offset; 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; @@ -1352,7 +1350,7 @@ Beam::pure_rest_collision_callback (SCM smob, Grob *right; if (idx == (vsize) - 1 || my_stems.size () == 1) - return scm_from_double (previous); + return prev_offset; else if (idx == 0) left = right = my_stems[1]; else if (idx == my_stems.size () - 1) @@ -1363,24 +1361,27 @@ 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; - - // So that ceil below kicks in for rests that would otherwise brush - // up against a beam quanted to a ledger line, add a bit of space - // between the beam and the rest. - shift += (0.01 * beamdir); - - /* 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]; + Real previous = robust_scm2double (prev_offset, 0.0); + + /* 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 @@ -1424,7 +1425,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 (unsmob (smob))); } int