From 1f1bb533fc2e81105eda69ee71352fc3993641d9 Mon Sep 17 00:00:00 2001 From: fred Date: Wed, 27 Mar 2002 02:06:46 +0000 Subject: [PATCH] lilypond-1.5.41 --- input/test/beam-hss.ly | 6 +- input/test/beam-position.ly | 3 +- input/test/beam-second.ly | 14 + input/test/knee-sym.ly | 10 + lily/beam.cc | 684 ++++++++++++++++-------------------- lily/include/beam.hh | 18 +- scm/beam.scm | 42 +-- scm/slur.scm | 14 +- 8 files changed, 353 insertions(+), 438 deletions(-) create mode 100644 input/test/beam-second.ly create mode 100644 input/test/knee-sym.ly diff --git a/input/test/beam-hss.ly b/input/test/beam-hss.ly index eea591381a..bd39978ae6 100644 --- a/input/test/beam-hss.ly +++ b/input/test/beam-hss.ly @@ -1,6 +1,7 @@ \header { -texidoc = "Beams in hang, straddle sit positions." +texidoc = "Beams in hang, straddle sit positions, forced there using +quanting." } @@ -9,9 +10,6 @@ texidoc = "Beams in hang, straddle sit positions." #(define ps-testing #t) \score { \notes\relative c'{ - \property Voice.Beam \override #'height-quant-function - = #(lambda (x y) '(0 4)) - \property Voice.Beam \override #'vertical-position-quant-function = #(lambda (beam dy x staff-line) (let* ((thick (ly-get-grob-property beam 'thickness)) diff --git a/input/test/beam-position.ly b/input/test/beam-position.ly index 59d7922004..02b5646a72 100644 --- a/input/test/beam-position.ly +++ b/input/test/beam-position.ly @@ -2,8 +2,7 @@ fragment = \notes { - \property Voice.Beam \set #'staff-position = #4 - \property Voice.Beam \set #'height = #-4 + \property Voice.Beam \set #'positions = #'(4 . 0) [c'8 c] } diff --git a/input/test/beam-second.ly b/input/test/beam-second.ly new file mode 100644 index 0000000000..d2bb26787e --- /dev/null +++ b/input/test/beam-second.ly @@ -0,0 +1,14 @@ +\header{ + texidoc="" +} +\score{ + \notes\relative c''{ + \stemUp + [b8 c] + [b16 c] + [a' b] + } + \paper{ + linewidth = 0.0 + } +} \ No newline at end of file diff --git a/input/test/knee-sym.ly b/input/test/knee-sym.ly new file mode 100644 index 0000000000..155a317f85 --- /dev/null +++ b/input/test/knee-sym.ly @@ -0,0 +1,10 @@ +\score{ + \notes\relative c'{ + [a8 b'' a,, b''] + [b8 a,, b'' a,,] + \stemUp [ b8 \stemDown b''] + } + \paper{ + linewidth = 0.0 + } +} \ No newline at end of file diff --git a/lily/beam.cc b/lily/beam.cc index 0fc84e6a42..9f15cdc24e 100644 --- a/lily/beam.cc +++ b/lily/beam.cc @@ -3,7 +3,7 @@ source file of the GNU LilyPond music typesetter - (c) 1997--2002 Han-Wen Nienhuys + (c) 1997--2002 Han-Wen Nienhuys Jan Nieuwenhuizen */ @@ -11,12 +11,17 @@ /* [TODO] - -* shorter! (now +- 1000 lines) + * different left/right quanting: slope, multiplicity - -* less hairy code + * Fix TODO + + * Junk stem_info. + + * Remove #'direction from beam. A beam has no direction per se. + It may only set directions for stems. - -* Remove #'direction from beam. The beam has no direction per se. - It may only set directions for stems. + * Rewrite stem_beams. + */ @@ -38,7 +43,7 @@ #include "warn.hh" void -Beam::add_stem (Grob*me, Grob*s) +Beam::add_stem (Grob *me, Grob *s) { Pointer_group_interface::add_grob (me, ly_symbol2scm ("stems"), s); @@ -51,51 +56,48 @@ Beam::add_stem (Grob*me, Grob*s) } int -Beam::get_multiplicity (Grob*me) +Beam::get_multiplicity (Grob *me) { int m = 0; for (SCM s = me->get_grob_property ("stems"); gh_pair_p (s); s = ly_cdr (s)) { - Grob * sc = unsmob_grob (ly_car (s)); + Grob *sc = unsmob_grob (ly_car (s)); if (Stem::has_interface (sc)) - m = m >? Stem::beam_count (sc,LEFT) >? Stem::beam_count (sc,RIGHT); + m = m >? Stem::beam_count (sc, LEFT) >? Stem::beam_count (sc, RIGHT); } return m; } -/* - After pre-processing all directions should be set. - Several post-processing routines (stem, slur, script) need stem/beam - direction. - Currenly, this means that beam has set all stem's directions. - [Alternatively, stems could set its own directions, according to - their beam, during 'final-pre-processing'.] - */ -MAKE_SCHEME_CALLBACK (Beam,before_line_breaking,1); +/* After pre-processing all directions should be set. + Several post-processing routines (stem, slur, script) need stem/beam + direction. + Currenly, this means that beam has set all stem's directions. + [Alternatively, stems could set its own directions, according to + their beam, during 'final-pre-processing'.] */ +MAKE_SCHEME_CALLBACK (Beam, before_line_breaking, 1); SCM Beam::before_line_breaking (SCM smob) { - Grob * me = unsmob_grob (smob); - - /* - Beams with less than 2 two stems don't make much sense, but could happen - when you do + Grob *me = unsmob_grob (smob); - [r8 c8 r8]. - + /* Beams with less than 2 two stems don't make much sense, but could happen + when you do + + [r8 c8 r8]. + 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.*/ - - - if (visible_stem_count (me) < 2) + we revert the flag, and move on to The Eternal Engraving Fields. */ + + int count = visible_stem_count (me); + if (count < 2) { me->warning (_ ("beam has less than two visible stems")); SCM stems = me->get_grob_property ("stems"); if (scm_ilength (stems) == 1) { - me->warning (_("Beam has less than two stems. Removing beam.")); + me->warning (_ ("Beam has less than two stems. Removing beam.")); unsmob_grob (gh_car (stems))->remove_grob_property ("beam"); me->suicide (); @@ -108,7 +110,7 @@ Beam::before_line_breaking (SCM smob) return SCM_UNSPECIFIED; } } - if (visible_stem_count (me) >= 1) + if (count >= 1) { if (!Directional_element_interface::get (me)) Directional_element_interface::set (me, get_default_dir (me)); @@ -121,7 +123,7 @@ Beam::before_line_breaking (SCM smob) } Direction -Beam::get_default_dir (Grob*me) +Beam::get_default_dir (Grob *me) { Drul_array total; total[UP] = total[DOWN] = 0; @@ -157,20 +159,16 @@ Beam::get_default_dir (Grob*me) if (gh_number_p (s) && gh_scm2int (s)) return to_dir (s); - /* - If dir is not determined: get default - */ + /* If dir is not determined: get default */ return to_dir (me->get_grob_property ("neutral-direction")); } -/* - Set all stems with non-forced direction to beam direction. - Urg: non-forced should become `without/with unforced' direction, - once stem gets cleaned-up. - */ +/* Set all stems with non-forced direction to beam direction. + Urg: non-forced should become `without/with unforced' direction, + once stem gets cleaned-up. */ void -Beam::set_stem_directions (Grob*me) +Beam::set_stem_directions (Grob *me) { Link_array stems =Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); @@ -181,17 +179,15 @@ Beam::set_stem_directions (Grob*me) Grob *s = stems[i]; SCM force = s->remove_grob_property ("dir-forced"); if (!gh_boolean_p (force) || !gh_scm2bool (force)) - Directional_element_interface ::set (s,d); + Directional_element_interface::set (s, d); } } -/* - Simplistic auto-knees; only consider vertical gap between two - adjacent chords. +/* Simplistic auto-knees; only consider vertical gap between two + adjacent chords. `Forced' stem directions are ignored. If you don't want auto-knees, - don't set, or unset auto-knee-gap. - */ + don't set, or unset auto-knee-gap. */ void Beam::consider_auto_knees (Grob *me) { @@ -255,14 +251,12 @@ Beam::consider_auto_knees (Grob *me) } } -/* - Set stem's shorten property if unset. - TODO: - take some y-position (chord/beam/nearest?) into account - scmify forced-fraction - */ +/* Set stem's shorten property if unset. + TODO: + take some y-position (chord/beam/nearest?) into account + scmify forced-fraction */ void -Beam::set_stem_shorten (Grob*m) +Beam::set_stem_shorten (Grob *m) { Spanner*me = dynamic_cast (m); @@ -277,7 +271,8 @@ Beam::set_stem_shorten (Grob*m) int sz = scm_ilength (shorten); Real staff_space = Staff_symbol_referencer::staff_space (me); - SCM shorten_elt = scm_list_ref (shorten, gh_int2scm (multiplicity set_grob_property ("shorten", gh_double2scm (shorten_f)); } -/* - Call list of y-dy-callbacks, that handle setting of - grob-properties y, dy. - - User may set grob-properties: y-position-hs and height-hs - (to be fixed) that override the calculated y and dy. - - Because y and dy cannot be calculated and quanted separately, we - always calculate both, then check for user override. - */ +/* Call list of y-dy-callbacks, that handle setting of + grob-properties y, dy. + + User may set grob-properties: y-position-hs and height-hs + (to be fixed) that override the calculated y and dy. + + Because y and dy cannot be calculated and quanted separately, we + always calculate both, then check for user override. */ MAKE_SCHEME_CALLBACK (Beam, after_line_breaking, 1); SCM Beam::after_line_breaking (SCM smob) { - Grob * me = unsmob_grob (smob); + Grob *me = unsmob_grob (smob); - me->set_grob_property ("y", gh_double2scm (0)); - me->set_grob_property ("dy", gh_double2scm (0)); + /* Copy to mutable list. */ + SCM s = ly_deep_copy (me->get_grob_property ("positions")); + me->set_grob_property ("positions", s); - /* Hmm, callbacks should be called by, a eh, callback mechanism - somewhere (?), I guess, not by looping here. */ - - SCM list = me->get_grob_property ("y-dy-callbacks"); - for (SCM i = list; gh_pair_p (i); i = ly_cdr (i)) - gh_call1 (ly_car (i), smob); + if (ly_car (s) != SCM_BOOL_F) + return SCM_UNSPECIFIED; - // UGH. Y is not in staff position unit? - // Ik dacht datwe daar juist van weg wilden? - - // Hmm, nu hebben we 3 dimensies, want inmiddels zijn we daar - // weer terug, maar dan / 2 - // (staff-space iso staff-position) - - set_stem_lengths (me); + SCM callbacks = me->get_grob_property ("position-callbacks"); + for (SCM i = callbacks; gh_pair_p (i); i = ly_cdr (i)) + gh_call1 (ly_car (i), smob); return SCM_UNSPECIFIED; } @@ -332,32 +317,33 @@ Beam::least_squares (SCM smob) Grob *me = unsmob_grob (smob); int count = visible_stem_count (me); + Interval pos (0, 0); + if (count <= 1) - return SCM_UNSPECIFIED; - - Real y = 0; - Real dy = 0; + { + me->set_grob_property ("positions", ly_interval2scm (pos)); + return SCM_UNSPECIFIED; + } + Direction dir = Directional_element_interface::get (me); - /* Stem_info, and thus y,dy in this function are corrected for beam-dir */ - Real first_ideal = Stem::calc_stem_info (first_visible_stem (me)).idealy_f_; - if (first_ideal == Stem::calc_stem_info (last_visible_stem (me)).idealy_f_) + Interval ideal (Stem::calc_stem_info (first_visible_stem (me)).idealy_f_, + Stem::calc_stem_info (last_visible_stem (me)).idealy_f_); + if (!ideal.delta ()) { - Real left = Stem::chord_start_f (first_visible_stem (me)); - Real right = Stem::chord_start_f (last_visible_stem (me)); + Interval chord (Stem::chord_start_f (first_visible_stem (me)), + Stem::chord_start_f (last_visible_stem (me))); /* Make simple beam on middle line have small tilt */ - if (!first_ideal && left != right && count == 2) + if (!ideal[LEFT] && chord.delta () && count == 2) { - int d = sign (right - left) * dir; - dy = gh_scm2double (me->get_grob_property ("thickness")) * d; - y = 0; + Direction d = (Direction)(sign (chord.delta ()) * dir); + pos[d] = gh_scm2double (me->get_grob_property ("thickness")) / 2 + * dir; + pos[-d] = - pos[d]; } else - { - y = first_ideal; - dy = 0; - } + pos = ideal; } else { @@ -373,19 +359,19 @@ Beam::least_squares (SCM smob) Item* s = stems[i]; if (Stem::invisible_b (s)) continue; - ideals.push (Offset (s->relative_coordinate (0, X_AXIS) - x0, + ideals.push (Offset (s->relative_coordinate (0, X_AXIS) - x0, Stem::calc_stem_info (s).idealy_f_)); } + Real y; Real dydx; minimise_least_squares (&dydx, &y, ideals); Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; - dy = dydx * dx; + Real dy = dydx * dx; + pos = Interval (y*dir, (y+dy) * dir); } - /* Store true, not dir-corrected values */ - me->set_grob_property ("y", gh_double2scm (y * dir)); - me->set_grob_property ("dy", gh_double2scm (dy * dir)); + me->set_grob_property ("positions", ly_interval2scm (pos)); return SCM_UNSPECIFIED; } @@ -412,12 +398,11 @@ Beam::check_concave (SCM smob) /* Concaveness try #2: Sum distances of inner noteheads that fall outside the interval of the two outer noteheads */ Real concave = 0; - Interval iv = Interval (Stem::chord_start_f (stems[0]), - Stem::chord_start_f (stems.top ())); + Interval iv (Stem::chord_start_f (stems[0]), + Stem::chord_start_f (stems.top ())); if (iv[MAX] < iv[MIN]) - // iv.swap (); - iv = Interval (iv[MAX], iv[MIN]); + iv.swap (); for (int i = 1; i < stems.size () - 1; i++) { @@ -440,24 +425,17 @@ Beam::check_concave (SCM smob) /* TODO: some sort of damping iso -> plain horizontal */ if (concaveness > r) { - Direction dir = Directional_element_interface::get (me); - Real y = gh_scm2double (me->get_grob_property ("y")) * dir; - Real dy = gh_scm2double (me->get_grob_property ("dy")) * dir; - - Real adjusted_y = y + dy / 2; - /* Store true, not dir-corrected values */ - me->set_grob_property ("y", gh_double2scm (adjusted_y * dir)); - me->set_grob_property ("dy", gh_double2scm (0)); + Interval pos = ly_scm2interval (me->get_grob_property ("positions")); + Real r = pos.linear_combination (0); + me->set_grob_property ("positions", ly_interval2scm (Interval (r, r))); } return SCM_UNSPECIFIED; } -/* - This neat trick is by Werner Lemberg, - damped = tanh (slope) - corresponds with some tables in [Wanske] -*/ +/* This neat trick is by Werner Lemberg, + damped = tanh (slope) + corresponds with some tables in [Wanske] CHECKME */ MAKE_SCHEME_CALLBACK (Beam, slope_damping, 1); SCM Beam::slope_damping (SCM smob) @@ -472,10 +450,8 @@ Beam::slope_damping (SCM smob) if (damping) { - /* y,dy in this function are corrected for beam-dir */ - Direction dir = Directional_element_interface::get (me); - Real y = gh_scm2double (me->get_grob_property ("y")) * dir; - Real dy = gh_scm2double (me->get_grob_property ("dy")) * dir; + Interval pos = ly_scm2interval (me->get_grob_property ("positions")); + Real dy = pos.delta (); // ugh -> use commonx Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) @@ -484,149 +460,137 @@ Beam::slope_damping (SCM smob) dydx = 0.6 * tanh (dydx) / damping; Real damped_dy = dydx * dx; - Real adjusted_y = y + (dy - damped_dy) / 2; - /* Store true, not dir-corrected values */ - me->set_grob_property ("y", gh_double2scm (adjusted_y * dir)); - me->set_grob_property ("dy", gh_double2scm (damped_dy * dir)); + pos[LEFT] += (dy - damped_dy) / 2; + pos[RIGHT] -= (dy - damped_dy) / 2; + + me->set_grob_property ("positions", ly_interval2scm (pos)); } return SCM_UNSPECIFIED; } -/* - Quantise dy (height) of beam. - Generalisation of [Ross]. - */ -MAKE_SCHEME_CALLBACK (Beam, quantise_dy, 1); -SCM -Beam::quantise_dy (SCM smob) + +/* Prevent interference from stafflines. */ +Interval +Beam::quantise_interval (Grob *me, Interval pos, Direction quant_dir) { - Grob *me = unsmob_grob (smob); + int multiplicity = get_multiplicity (me); - if (visible_stem_count (me) <= 1) - return SCM_UNSPECIFIED; + Real staff_space = Staff_symbol_referencer::staff_space (me); + Real thick = me->paper_l ()->get_var ("stafflinethickness"); - Array a; - SCM proc = me->get_grob_property ("height-quant-function"); - SCM quants = gh_call2 (proc, me->self_scm (), - gh_double2scm (me->paper_l ()->get_var ("stafflinethickness") - / 1.0)); + /* TODO: + + - left and right should be different, depending on direction and + multiplicity + + -use different left-position-quant-function, + right-position-quant-function for handier slope quanting? */ + SCM proc = me->get_grob_property ("vertical-position-quant-function"); + SCM quants = scm_apply (proc, + me->self_scm (), + scm_list_n (gh_int2scm (multiplicity), + gh_double2scm (1), /* junkme */ + gh_double2scm (thick / staff_space), + /* HUH? */ + SCM_EOL, + SCM_UNDEFINED)); - for (SCM s = quants; gh_pair_p (s); s = ly_cdr (s)) - a.push (gh_scm2double (ly_car (s))); + Array a; + for (SCM i = quants; gh_pair_p (i); i = ly_cdr (i)) + a.push (gh_scm2double (ly_car (i))); - if (a.size () > 1) - { - /* y,dy in this function are corrected for beam-dir */ - Direction dir = Directional_element_interface::get (me); - Real y = gh_scm2double (me->get_grob_property ("y")) * dir; - Real dy = gh_scm2double (me->get_grob_property ("dy")) * dir; + if (a.size () <= 1) + return pos; - Real staff_space = Staff_symbol_referencer::staff_space (me); - - Interval iv = quantise_iv (a, abs (dy)/staff_space) * staff_space; - -#if 0 - Real q = (abs (dy) - iv[SMALLER] <= iv[BIGGER] - abs (dy)) - ? iv[SMALLER] - : iv[BIGGER]; -#else - Real q = (!dy || iv[SMALLER] != 0) ? iv[SMALLER] : iv[BIGGER]; -#endif - - Real quantised_dy = q * (dy != 0 ? sign (dy) : 1); - Real adjusted_y = y + (dy - quantised_dy) * 0.5; - /* Store true, not dir-corrected values */ - me->set_grob_property ("y", gh_double2scm (adjusted_y * dir)); - me->set_grob_property ("dy", gh_double2scm (quantised_dy * dir)); - } - return SCM_UNSPECIFIED; -} + Direction dir = Directional_element_interface::get (me); + Interval left = quantise_iv (a, pos[LEFT]*dir/staff_space) * staff_space; + Interval right = quantise_iv (a, pos[RIGHT]*dir/staff_space) * staff_space; + + Real dy = pos.delta (); + Real ady = abs (dy); -/* It's tricky to have the user override y,dy directly, so we use this - translation func. Also, if our staff_space != 1 (smaller staff, eg), - user will expect staff-position to be discrete values. */ -MAKE_SCHEME_CALLBACK (Beam, user_override, 1); -SCM -Beam::user_override (SCM smob) -{ - Grob *me = unsmob_grob (smob); - Real staff_space = Staff_symbol_referencer::staff_space (me); + // quant direction hints disabled for now + int q = 0;//(int)quant_dir; - SCM s = me->get_grob_property ("staff-position"); - if (gh_number_p (s)) - { - Real y = gh_scm2double (s) * staff_space * 0.5; - me->set_grob_property ("y", gh_double2scm (y)); - } + /* TODO: make smart choice, find best left/right quants pair. - /* Name suggestions? Tilt, slope, vertical-* ? */ - s = me->get_grob_property ("height"); - if (gh_number_p (s)) + Slope should never be steeper than least_squares (before damping) + (save that value?) + Slope should never be reduced to zero. + */ + Interval qpos (0, 20.0 *sign (dy)); + Direction ldir = LEFT; + do { - Real dy = gh_scm2double (s) * staff_space * 0.5; - me->set_grob_property ("dy", gh_double2scm (dy)); + Direction rdir = LEFT; + do + { + Interval i (left[ldir]*dir, right[rdir]*dir); + if ((abs (abs (i.delta ()) - ady) <= abs (abs (qpos.delta ()) - ady) + && sign (i.delta ()) == sign (pos.delta ()) + && (!q + || (i[LEFT]*q >= pos[LEFT]*q && i[RIGHT]*q >= pos[RIGHT]*q)))) + qpos = i; + } + while (flip (&rdir) != LEFT); } + while (flip (&ldir) != LEFT); - return SCM_UNSPECIFIED; + return qpos; } -/* - Ugh, this must be last, after user_override - Assumes directionised y/dy. - */ -MAKE_SCHEME_CALLBACK (Beam, do_quantise_y, 1); + +/* Quantise vertical position (left and right) of beam. + Generalisation of [Ross]. */ +MAKE_SCHEME_CALLBACK (Beam, quantise_position, 1); SCM -Beam::do_quantise_y (SCM smob) +Beam::quantise_position (SCM smob) { Grob *me = unsmob_grob (smob); - /* - If the user set y-position, we shouldn't do quanting. - */ - if (gh_number_p (me->get_grob_property ("y-position-hs"))) - return SCM_UNSPECIFIED; - - Real y = gh_scm2double (me->get_grob_property ("y")); - Real dy = gh_scm2double (me->get_grob_property ("dy")); - - /* we can modify y, so we should quantise y */ - Real half_space = Staff_symbol_referencer::staff_space (me) / 2; - Real y_shift = check_stem_length_f (me, y, dy); - y += y_shift; - y = quantise_y_f (me, y, dy, 0); - - /* - Hmm, this is a bit keyhole operation: we're passing `this' as a - parameter, and member vars as SCM properties. We should decide on - SCM/C/C++ boundary */ - me->set_grob_property ("y", gh_double2scm (y)); + Interval pos = ly_scm2interval (me->get_grob_property ("positions")); + Real y_shift = check_stem_length_f (me, pos); + pos += y_shift; + pos = quantise_interval (me, pos, CENTER); + + me->set_grob_property ("positions", ly_interval2scm (pos)); set_stem_lengths (me); - y = gh_scm2double (me->get_grob_property ("y")); + + pos = ly_scm2interval (me->get_grob_property ("positions")); - y_shift = check_stem_length_f (me, y, dy); + y_shift = check_stem_length_f (me, pos); + Real half_space = Staff_symbol_referencer::staff_space (me) / 2; + /* HMMM */ if (y_shift > half_space / 4) { - y += y_shift; - - /* - for significantly lengthened or shortened stems, - request quanting the other way. - */ + pos += y_shift; int quant_dir = 0; + /* for significantly lengthened or shortened stems, + request quanting the other way. + HMMM */ if (abs (y_shift) > half_space / 2) quant_dir = sign (y_shift) * Directional_element_interface::get (me); - y = quantise_y_f (me, y, dy, quant_dir); + pos = quantise_interval (me, pos, (Direction)quant_dir); } - me->set_grob_property ("y", gh_double2scm (y)); - // me->set_grob_property ("dy", gh_double2scm (dy)); + me->set_grob_property ("positions", ly_interval2scm (pos)); + return SCM_UNSPECIFIED; } +MAKE_SCHEME_CALLBACK (Beam, end_after_line_breaking, 1); +SCM +Beam::end_after_line_breaking (SCM smob) +{ + Grob *me = unsmob_grob (smob); + set_stem_lengths (me); + + return SCM_UNSPECIFIED; +} Real -Beam::calc_stem_y_f (Grob*me,Item* s, Real y, Real dy) +Beam::calc_stem_y_f (Grob *me, Item* s, Interval pos) { int beam_multiplicity = get_multiplicity (me); int stem_multiplicity = (Stem::flag_i (s) - 2) >? 0; @@ -634,32 +598,33 @@ Beam::calc_stem_y_f (Grob*me,Item* s, Real y, Real dy) SCM space_proc = me->get_grob_property ("space-function"); SCM space = gh_call1 (space_proc, gh_int2scm (beam_multiplicity)); - Real thick = gh_scm2double (me->get_grob_property ("thickness")) ; - Real interbeam_f = gh_scm2double (space) ; + Real thick = gh_scm2double (me->get_grob_property ("thickness")); + Real interbeam_f = gh_scm2double (space); // ugh -> use commonx Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; - Real stem_y = (dy && dx ? (s->relative_coordinate (0, X_AXIS) - x0) / dx * dy : 0) + y; + Real dy = pos.delta (); + Real stem_y = (dy && dx + ? (s->relative_coordinate (0, X_AXIS) - x0) / dx + * dy + : 0) + pos[LEFT]; /* knee */ - Direction dir = Directional_element_interface::get (me); - Direction sdir = Directional_element_interface::get (s); - - /* knee */ - if (dir!= sdir) - { - stem_y -= dir - * (thick / 2 + (beam_multiplicity - 1) * interbeam_f); - - + Direction dir = Directional_element_interface::get (me); + Direction sdir = Directional_element_interface::get (s); + + /* knee */ + if (dir!= sdir) + { + stem_y -= dir * (thick / 2 + (beam_multiplicity - 1) * interbeam_f); // huh, why not for first visible? - if (Staff_symbol_referencer::staff_symbol_l (s) - != Staff_symbol_referencer::staff_symbol_l (last_visible_stem (me))) - stem_y += Directional_element_interface::get (me) - * (beam_multiplicity - stem_multiplicity) * interbeam_f; - } + if (Staff_symbol_referencer::staff_symbol_l (s) + != Staff_symbol_referencer::staff_symbol_l (last_visible_stem (me))) + stem_y += Directional_element_interface::get (me) + * (beam_multiplicity - stem_multiplicity) * interbeam_f; + } return stem_y; } @@ -670,7 +635,7 @@ Beam::calc_stem_y_f (Grob*me,Item* s, Real y, Real dy) Optionally (testing): try to lengthen more, to reach more ideal stem lengths */ Real -Beam::check_stem_length_f (Grob *me, Real y, Real dy) +Beam::check_stem_length_f (Grob *me, Interval pos) { Real shorten = 0; Real lengthen = 0; @@ -693,7 +658,7 @@ Beam::check_stem_length_f (Grob *me, Real y, Real dy) knee |= dir != Directional_element_interface::get (s); - Real stem_y = calc_stem_y_f (me, s, y, dy); + Real stem_y = calc_stem_y_f (me, s, pos); stem_y *= dir; Stem_info info = Stem::calc_stem_info (s); @@ -734,91 +699,47 @@ Beam::check_stem_length_f (Grob *me, Real y, Real dy) void Beam::set_stem_lengths (Grob *me) { - if (visible_stem_count (me) <= 1) - return; - - Real y = gh_scm2double (me->get_grob_property ("y")); - Real dy = gh_scm2double (me->get_grob_property ("dy")); - - Real half_space = Staff_symbol_referencer::staff_space (me)/2; Link_array stems= Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); + if (stems.size () <= 1) + return; + Grob *common = me->common_refpoint (stems[0], Y_AXIS); for (int i=1; i < stems.size (); i++) if (!Stem::invisible_b (stems[i])) common = common->common_refpoint (stems[i], Y_AXIS); + Direction dir = Directional_element_interface::get (me); + Interval pos = ly_scm2interval (me->get_grob_property ("positions")); + Real staff_space = Staff_symbol_referencer::staff_space (me); + Real thick = gh_scm2double (me->get_grob_property ("thickness")); + bool ps_testing = to_boolean (ly_symbol2scm ("ps-testing")); for (int i=0; i < stems.size (); i++) { Item* s = stems[i]; if (Stem::invisible_b (s)) continue; - Real stem_y = calc_stem_y_f (me, s, y, dy); + Real stem_y = calc_stem_y_f (me, s, pos); // doesn't play well with dvips - if (scm_definedp (ly_symbol2scm ("ps-testing"), SCM_UNDEFINED) - == SCM_BOOL_T) - if (Stem::get_direction (s) == Directional_element_interface::get (me)) - stem_y += Stem::get_direction (s) - * gh_scm2double (me->get_grob_property ("thickness")) / 2; + if (ps_testing) + if (Stem::get_direction (s) == dir) + stem_y += Stem::get_direction (s) * thick / 2; /* caution: stem measures in staff-positions */ Real id = me->relative_coordinate (common, Y_AXIS) - stems[i]->relative_coordinate (common, Y_AXIS); - Stem::set_stemend (s, (stem_y + id) / half_space); + Stem::set_stemend (s, (stem_y + id) / staff_space * 2); } } -/* - Prevent interference from stafflines and beams. - - We only need to quantise the (left) y of the beam, - since dy is quantised too. - if extend_b then stems must *not* get shorter - */ -Real -Beam::quantise_y_f (Grob*me,Real y, Real dy, int quant_dir) -{ - int multiplicity = get_multiplicity (me); - - Real staff_space = Staff_symbol_referencer::staff_space (me); - Real thick = me->paper_l ()->get_var ("stafflinethickness"); - - - SCM proc = me->get_grob_property ("vertical-position-quant-function"); - SCM quants = scm_apply (proc, - me->self_scm (), - scm_list_n (gh_int2scm (multiplicity), - gh_double2scm (dy/staff_space), - gh_double2scm (thick/staff_space), - SCM_EOL, SCM_UNDEFINED)); - - Array a; - - for (; gh_pair_p (quants); quants = ly_cdr (quants)) - a.push (gh_scm2double (ly_car (quants))); - - if (a.size () <= 1) - return y; - - Real up_y = Directional_element_interface::get (me) * y; - Interval iv = quantise_iv (a, up_y/staff_space) * staff_space; - - Real q = up_y - iv[SMALLER] <= iv[BIGGER] - up_y - ? iv[SMALLER] : iv[BIGGER]; - if (quant_dir) - q = iv[ (Direction)quant_dir]; - - return q * Directional_element_interface::get (me); -} - void -Beam::set_beaming (Grob*me,Beaming_info_list *beaming) +Beam::set_beaming (Grob *me, Beaming_info_list *beaming) { Link_array stems= - Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems"); + Pointer_group_interface__extract_grobs (me, (Grob *)0, "stems"); Direction d = LEFT; for (int i=0; i < stems.size (); i++) @@ -847,32 +768,27 @@ Beam::set_beaming (Grob*me,Beaming_info_list *beaming) FIXME: clean me up. */ Molecule -Beam::stem_beams (Grob*me,Item *here, Item *next, Item *prev, - Real /* dy */ , Real dydx - ) +Beam::stem_beams (Grob *me, Item *here, Item *next, Item *prev, Real dydx) { // ugh -> use commonx - if ((next && ! (next->relative_coordinate (0, X_AXIS) > here->relative_coordinate (0, X_AXIS))) || - (prev && ! (prev->relative_coordinate (0, X_AXIS) < here->relative_coordinate (0, X_AXIS)))) - programming_error ("Beams are not left-to-right"); + if ((next + && !(next->relative_coordinate (0, X_AXIS) + > here->relative_coordinate (0, X_AXIS))) + || (prev + && !(prev->relative_coordinate (0, X_AXIS) + < here->relative_coordinate (0, X_AXIS)))) + programming_error ("Beams are not left-to-right"); int multiplicity = get_multiplicity (me); SCM space_proc = me->get_grob_property ("space-function"); SCM space = gh_call1 (space_proc, gh_int2scm (multiplicity)); - Real thick = gh_scm2double (me->get_grob_property ("thickness")) ; - Real interbeam_f = gh_scm2double (space) ; + Real thick = gh_scm2double (me->get_grob_property ("thickness")); + Real interbeam_f = gh_scm2double (space); Real bdy = interbeam_f; -#if 0 - // ugh -> use commonx - Real dx = visible_stem_count (me) ? - last_visible_stem (me)->relative_coordinate (0, X_AXIS) - first_visible_stem (me)->relative_coordinate (0, X_AXIS) - : 0.0; -#endif - Molecule leftbeams; Molecule rightbeams; @@ -898,12 +814,13 @@ Beam::stem_beams (Grob*me,Item *here, Item *next, Item *prev, /* half beams extending to the left. */ if (prev) { - int lhalfs= lhalfs = Stem::beam_count (here,LEFT) - Stem::beam_count (prev,RIGHT); - int lwholebeams= Stem::beam_count (here,LEFT) relative_coordinate (0, X_AXIS) @@ -928,10 +845,10 @@ Beam::stem_beams (Grob*me,Item *here, Item *next, Item *prev, if (next) { - int rhalfs = Stem::beam_count (here,RIGHT) - - Stem::beam_count (next,LEFT); - int rwholebeams= Stem::beam_count (here,RIGHT) - relative_coordinate (0, X_AXIS) - here->relative_coordinate (0, X_AXIS); @@ -992,28 +909,26 @@ Beam::stem_beams (Grob*me,Item *here, Item *next, Item *prev, } leftbeams.add_molecule (rightbeams); - /* - Does beam quanting think of the asymetry of beams? - Refpoint is on bottom of symbol. (FIXTHAT) --hwn. - */ + /* Does beam quanting think of the asymetry of beams? + Refpoint is on bottom of symbol. (FIXTHAT) --hwn. */ return leftbeams; } -MAKE_SCHEME_CALLBACK (Beam,brew_molecule,1); +MAKE_SCHEME_CALLBACK (Beam, brew_molecule, 1); SCM Beam::brew_molecule (SCM smob) { - Grob * me =unsmob_grob (smob); + Grob *me =unsmob_grob (smob); Molecule mol; if (!gh_pair_p (me->get_grob_property ("stems"))) return SCM_EOL; - Real x0,dx; + Real x0, dx; Link_arraystems = Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); if (visible_stem_count (me)) { - // ugh -> use commonx + // ugh -> use commonx x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; } @@ -1022,40 +937,33 @@ Beam::brew_molecule (SCM smob) x0 = stems[0]->relative_coordinate (0, X_AXIS); dx = stems.top ()->relative_coordinate (0, X_AXIS) - x0; } - - - /* - TODO: the naming of the grob properties sucks. - */ - SCM dy_s = me->get_grob_property ("dy"); - SCM y_s = me->get_grob_property ("y"); - - - Real dy = gh_number_p (dy_s) ? gh_scm2double (dy_s) : 0.0; + Interval pos = ly_scm2interval (me->get_grob_property ("positions")); + Real dy = pos.delta (); Real dydx = dy && dx ? dy/dx : 0; - Real y = gh_number_p (y_s) ? gh_scm2double (y_s) : 0.0; - - for (int j=0; j 0)? stems[j-1] : 0; - Item * next = (j < stems.size ()-1) ? stems[j+1] :0; + Item *item = stems[i]; + Item *prev = (i > 0)? stems[i-1] : 0; + Item *next = (i < stems.size ()-1) ? stems[i+1] :0; - Molecule sb = stem_beams (me, i, next, prev, dy, dydx); - Real x = i->relative_coordinate (0, X_AXIS)-x0; - sb.translate (Offset (x, x * dydx + y)); + Molecule sb = stem_beams (me, item, next, prev, dydx); + Real x = item->relative_coordinate (0, X_AXIS) - x0; + sb.translate (Offset (x, x * dydx + pos[LEFT])); mol.add_molecule (sb); } + mol.translate_axis (x0 - - dynamic_cast (me)->get_bound (LEFT)->relative_coordinate (0, X_AXIS), X_AXIS); + - dynamic_cast (me) + ->get_bound (LEFT)->relative_coordinate (0, X_AXIS), + X_AXIS); return mol.smobbed_copy (); } int -Beam::forced_stem_count (Grob*me) +Beam::forced_stem_count (Grob *me) { Link_arraystems = Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); @@ -1067,7 +975,7 @@ Beam::forced_stem_count (Grob*me) if (Stem::invisible_b (s)) continue; - if (( (int)Stem::chord_start_f (s)) + if (((int)Stem::chord_start_f (s)) && (Stem::get_direction (s) != Stem::get_default_dir (s))) f++; } @@ -1081,7 +989,7 @@ Beam::forced_stem_count (Grob*me) use filter and standard list functions. */ int -Beam::visible_stem_count (Grob*me) +Beam::visible_stem_count (Grob *me) { Link_arraystems = Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); @@ -1095,7 +1003,7 @@ Beam::visible_stem_count (Grob*me) } Item* -Beam::first_visible_stem (Grob*me) +Beam::first_visible_stem (Grob *me) { Link_arraystems = Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); @@ -1109,7 +1017,7 @@ Beam::first_visible_stem (Grob*me) } Item* -Beam::last_visible_stem (Grob*me) +Beam::last_visible_stem (Grob *me) { Link_arraystems = Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); @@ -1131,7 +1039,7 @@ Beam::last_visible_stem (Grob*me) rest -> stem -> beam -> interpolate_y_position () */ -MAKE_SCHEME_CALLBACK (Beam,rest_collision_callback,2); +MAKE_SCHEME_CALLBACK (Beam, rest_collision_callback, 2); SCM Beam::rest_collision_callback (SCM element_smob, SCM axis) { @@ -1140,40 +1048,38 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis) assert (a == Y_AXIS); - Grob * st = unsmob_grob (rest->get_grob_property ("stem")); - Grob * stem = st; + Grob *st = unsmob_grob (rest->get_grob_property ("stem")); + Grob *stem = st; if (!stem) return gh_double2scm (0.0); - Grob * beam = unsmob_grob (stem->get_grob_property ("beam")); - if (!beam || !Beam::has_interface (beam) || !Beam::visible_stem_count (beam)) + Grob *beam = unsmob_grob (stem->get_grob_property ("beam")); + if (!beam + || !Beam::has_interface (beam) + || !Beam::visible_stem_count (beam)) return gh_double2scm (0.0); // make callback for rest from this. - Real beam_dy = 0; - Real beam_y = 0; + // todo: make sure this calced already. + // Interval pos = ly_scm2interval (beam->get_grob_property ("positions")); + Interval pos (0, 0); + SCM s = beam->get_grob_property ("positions"); + if (gh_pair_p (s) && gh_number_p (ly_car (s))) + pos = ly_scm2interval (s); - // todo: make sure this calced already. - SCM s = beam->get_grob_property ("dy"); - if (gh_number_p (s)) - beam_dy = gh_scm2double (s); - - s = beam->get_grob_property ("y"); - if (gh_number_p (s)) - beam_y = gh_scm2double (s); - + Real dy = pos.delta (); // ugh -> use commonx Real x0 = first_visible_stem (beam)->relative_coordinate (0, X_AXIS); Real dx = last_visible_stem (beam)->relative_coordinate (0, X_AXIS) - x0; - Real dydx = beam_dy && dx ? beam_dy/dx : 0; - + Real dydx = dy && dx ? dy/dx : 0; + Direction d = Stem::get_direction (stem); - Real beamy = (stem->relative_coordinate (0, X_AXIS) - x0) * dydx + beam_y; + Real beamy = (stem->relative_coordinate (0, X_AXIS) - x0) * dydx + pos[LEFT]; Real staff_space = Staff_symbol_referencer::staff_space (rest); - Real rest_dim = rest->extent (rest, Y_AXIS)[d]*2.0 / staff_space ; // refp?? + Real rest_dim = rest->extent (rest, Y_AXIS)[d]*2.0 / staff_space; // refp?? Real minimum_dist = gh_scm2double (rest->get_grob_property ("minimum-beam-collision-distance")); @@ -1194,7 +1100,7 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis) bool -Beam::has_interface (Grob*me) +Beam::has_interface (Grob *me) { return me->has_interface (ly_symbol2scm ("beam-interface")); } diff --git a/lily/include/beam.hh b/lily/include/beam.hh index 35dfbeb8aa..c0c7c28933 100644 --- a/lily/include/beam.hh +++ b/lily/include/beam.hh @@ -28,28 +28,26 @@ public: DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM )); DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM )); + DECLARE_SCHEME_CALLBACK (end_after_line_breaking, (SCM)); - /* - y-dy callbacks - */ + /* position callbacks */ DECLARE_SCHEME_CALLBACK (least_squares, (SCM)); DECLARE_SCHEME_CALLBACK (check_concave, (SCM)); DECLARE_SCHEME_CALLBACK (slope_damping, (SCM)); - DECLARE_SCHEME_CALLBACK (quantise_dy, (SCM)); - DECLARE_SCHEME_CALLBACK (user_override, (SCM)); - DECLARE_SCHEME_CALLBACK (do_quantise_y, (SCM)); + DECLARE_SCHEME_CALLBACK (quantise_position, (SCM)); - static Molecule stem_beams (Grob*,Item *here, Item *next, Item *prev, Real, Real); + static Molecule stem_beams (Grob*,Item *here, Item *next, Item *prev, + Real dydx); private: static Direction get_default_dir (Grob*); static void set_stem_directions (Grob*); static void consider_auto_knees (Grob*); static void set_stem_shorten (Grob*); - static Real calc_stem_y_f (Grob*, Item* s, Real y, Real dy); - static Real check_stem_length_f (Grob*, Real y, Real dy); + static Real calc_stem_y_f (Grob*, Item* s, Interval pos); + static Real check_stem_length_f (Grob*, Interval pos); static void set_stem_lengths (Grob*); - static Real quantise_y_f (Grob*, Real y, Real dy, int quant_dir); + static Interval quantise_interval (Grob*, Interval pos, Direction quant_dir); static int forced_stem_count (Grob*); }; diff --git a/scm/beam.scm b/scm/beam.scm index 6d5cbbc676..efcc28835e 100644 --- a/scm/beam.scm +++ b/scm/beam.scm @@ -1,14 +1,18 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; BEAMS -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; +;;;; beam.scm -- Beam scheme stuff +;;;; +;;;; source file of the GNU LilyPond music typesetter +;;;; +;;;; (c) 2000--2001 Jan Nieuwenhuizen +;;;; (define (default-beam-space-function multiplicity) (if (<= multiplicity 3) 0.816 0.844) ) -; -; width in staff space. -; +;; +;; width in staff space. +;; (define (default-beam-flag-width-function type) (cond ((eq? type 1) 1.98) @@ -17,8 +21,8 @@ )) -; This is a mess : global namespace pollution. We should wait -; till guile has proper toplevel environment support. +;; This is a mess : global namespace pollution. We should wait +;; till guile has proper toplevel environment support. ;; Beams should be prevented to conflict with the stafflines, @@ -34,25 +38,11 @@ ;; inter seems to be a modern quirk, we don't use that - -;; Note: quanting period is take as quants.top () - quants[0], -;; which should be 1 (== 1 interline) - (define (mean a b) (* 0.5 (+ a b))) -(define (default-beam-dy-quants beam stafflinethick) - (let ((thick (ly-get-grob-property beam 'thickness))) - ;; amazing. this is wrong: - (list 0 (mean thick stafflinethick) (+ thick stafflinethick) 1) - ;; it should be this: but the visual effect is even uglier, - ;; because dy quants are not synchronised with left y - ;; (list 0 (/ (- thick stafflinethick) 2) (- thick stafflinethick) 1) - )) - ;; two popular veritcal beam quantings ;; see params.ly: #'beam-vertical-quants -; (todo: merge these 2 funcs ? ) -(define (default-beam-y-quants beam multiplicity dy staff-line) +(define (default-beam-pos-quants beam multiplicity dy staff-line) (let* ((beam-straddle 0) (thick (ly-get-grob-property beam 'thickness)) (beam-sit (/ (- thick staff-line) 2)) @@ -64,10 +54,10 @@ (set! quants (cons beam-sit quants))) (if (or (<= multiplicity 2) (>= (abs dy) (/ staff-line 2))) (set! quants (cons beam-straddle quants))) - ;; period: 1 (interline) + ;; period: 1 (staff-space) (append quants (list (+ 1 (car quants)))))) -(define (beam-traditional-y-quants beam multiplicity dy staff-line) +(define (beam-traditional-pos-quants beam multiplicity dy staff-line) (let* ((beam-straddle 0) (thick (ly-get-grob-property beam 'thickness)) (beam-sit (/ (- thick staff-line) 2)) @@ -80,7 +70,7 @@ (set! quants (cons beam-sit quants))) (if (or (<= multiplicity 2) (>= (abs dy) (/ staff-line 2))) (set! quants (cons beam-straddle quants))) - ;; period: 1 (interline) + ;; period: 1 (staff-space) (append quants (list (+ 1 (car quants)))))) diff --git a/scm/slur.scm b/scm/slur.scm index 28d1eb0cf1..d632839023 100644 --- a/scm/slur.scm +++ b/scm/slur.scm @@ -1,10 +1,10 @@ -;;; -;;; slur.scm -- Slur scheme stuff -;;; -;;; source file of the GNU LilyPond music typesetter -;;; -;;; (c) 2000--2001 Jan Nieuwenhuizen -;;; +;;;; +;;;; slur.scm -- Slur scheme stuff +;;;; +;;;; source file of the GNU LilyPond music typesetter +;;;; +;;;; (c) 2000--2001 Jan Nieuwenhuizen +;;;; (define (attached-to-stem slur dir) (let* ((note-columns (ly-get-grob-property slur 'note-columns)) -- 2.39.5