From 764c49729f95f421d9d6cc8eee5386706039a2c7 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Fri, 15 Mar 2002 10:16:18 +0100 Subject: [PATCH] patch::: 1.5.40.jcn1 2002-03-15 Jan Nieuwenhuizen * lily/include/new-beam.hh: Previously new-beam.hh * lily/beam.cc: Previously new-beam.cc (least_squares): Bugfix: don't barf on beams with less than two visible stems (tremolos). * scm/beam.scm: * scm/grob-description.scm (Beam): Junk old beam stuff. --- ChangeLog | 11 + VERSION | 2 +- 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 +- lily/include/new-beam.hh | 55 -- lily/new-beam.cc | 1096 ----------------------------- scm/beam.scm | 42 +- scm/grob-description.scm | 28 +- scm/grob-property-description.scm | 1 + scm/slur.scm | 14 +- 14 files changed, 375 insertions(+), 1609 deletions(-) create mode 100644 input/test/beam-second.ly create mode 100644 input/test/knee-sym.ly diff --git a/ChangeLog b/ChangeLog index c34771be21..ea09fe446f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2002-03-15 Jan Nieuwenhuizen + + * lily/include/new-beam.hh: Previously new-beam.hh + * lily/beam.cc: Previously new-beam.cc + (least_squares): Bugfix: don't barf on beams with less than two + visible stems (tremolos). + + * scm/beam.scm: + * scm/grob-description.scm (Beam): Junk old beam stuff. + + 2002-03-14 Han-Wen Nienhuys * mf/feta-eindelijk.mf: new 8th rest. diff --git a/VERSION b/VERSION index 2b6cecc096..be46e1e7bc 100644 --- a/VERSION +++ b/VERSION @@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=1 MINOR_VERSION=5 PATCH_LEVEL=40 -MY_PATCH_LEVEL= +MY_PATCH_LEVEL=jcn1 # use the above to send patches: MY_PATCH_LEVEL is always empty for a # released version. 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/lily/include/new-beam.hh b/lily/include/new-beam.hh index 660ec8e249..e69de29bb2 100644 --- a/lily/include/new-beam.hh +++ b/lily/include/new-beam.hh @@ -1,55 +0,0 @@ -/* - beam.hh -- part of GNU LilyPond - - (c) 1996--2002 Han-Wen Nienhuys -*/ - -#ifndef NEW_BEAM_HH -#define NEW_BEAM_HH - -#include "lily-proto.hh" -#include "lily-guile.hh" - - - -class New_beam -{ -public: - static int visible_stem_count (Grob*); - static Item* first_visible_stem (Grob*); - static Item* last_visible_stem (Grob*); - static bool has_interface (Grob*); - DECLARE_SCHEME_CALLBACK (rest_collision_callback, (SCM element, SCM axis)); - New_beam (SCM); - static void add_stem (Grob*,Grob*); - static void set_beaming (Grob*,Beaming_info_list *); - static void set_stemlens (Grob*); - static int get_multiplicity (Grob*me); - 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)); - - /* position callbacks */ - DECLARE_SCHEME_CALLBACK (least_squares, (SCM)); - DECLARE_SCHEME_CALLBACK (check_concave, (SCM)); - DECLARE_SCHEME_CALLBACK (slope_damping, (SCM)); - DECLARE_SCHEME_CALLBACK (quantise_position, (SCM)); - - 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, Interval pos); - static Real check_stem_length_f (Grob*, Interval pos); - static void set_stem_lengths (Grob*); - static Interval quantise_interval (Grob*, Interval pos, Direction quant_dir); - static int forced_stem_count (Grob*); -}; - -#endif /* NEW_BEAM_HH */ - diff --git a/lily/new-beam.cc b/lily/new-beam.cc index fd7efea054..e69de29bb2 100644 --- a/lily/new-beam.cc +++ b/lily/new-beam.cc @@ -1,1096 +0,0 @@ -/* - beam.cc -- implement Beam - - source file of the GNU LilyPond music typesetter - - (c) 1997--2002 Han-Wen Nienhuys - Jan Nieuwenhuizen - -*/ - -/* - [TODO] - - * different left/right quanting: slope, multiplicity - - * Fix TODO - - * Junk stem_info. - - * Remove #'direction from beam. A beam has no direction per se. - It may only set directions for stems. - - * Rewrite stem_beams. - - */ - - -#include // tanh. - -#include "molecule.hh" -#include "directional-element-interface.hh" -#include "beaming.hh" -#include "new-beam.hh" -#include "misc.hh" -#include "least-squares.hh" -#include "stem.hh" -#include "paper-def.hh" -#include "lookup.hh" -#include "group-interface.hh" -#include "staff-symbol-referencer.hh" -#include "item.hh" -#include "spanner.hh" -#include "warn.hh" - -void -New_beam::add_stem (Grob *me, Grob *s) -{ - Pointer_group_interface::add_grob (me, ly_symbol2scm ("stems"), s); - - s->add_dependency (me); - - assert (!Stem::beam_l (s)); - s->set_grob_property ("beam", me->self_scm ()); - - add_bound_item (dynamic_cast (me), dynamic_cast (s)); -} - -int -New_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)); - - if (Stem::has_interface (sc)) - 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 (New_beam, before_line_breaking, 1); -SCM -New_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 - - [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. */ - - 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.")); - - unsmob_grob (gh_car (stems))->remove_grob_property ("beam"); - me->suicide (); - - return SCM_UNSPECIFIED; - } - else if (scm_ilength (stems) == 0) - { - me->suicide (); - return SCM_UNSPECIFIED; - } - } - if (count >= 1) - { - if (!Directional_element_interface::get (me)) - Directional_element_interface::set (me, get_default_dir (me)); - - consider_auto_knees (me); - set_stem_directions (me); - set_stem_shorten (me); - } - return SCM_EOL; -} - -Direction -New_beam::get_default_dir (Grob *me) -{ - Drul_array total; - total[UP] = total[DOWN] = 0; - Drul_array count; - count[UP] = count[DOWN] = 0; - Direction d = DOWN; - - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - for (int i=0; i get_grob_property ("dir-function"); - SCM s = gh_call2 (func, - gh_cons (gh_int2scm (count[UP]), - gh_int2scm (count[DOWN])), - gh_cons (gh_int2scm (total[UP]), - gh_int2scm (total[DOWN]))); - - if (gh_number_p (s) && gh_scm2int (s)) - return to_dir (s); - - /* 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. */ -void -New_beam::set_stem_directions (Grob *me) -{ - Link_array stems - =Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - Direction d = Directional_element_interface::get (me); - - for (int i=0; i remove_grob_property ("dir-forced"); - if (!gh_boolean_p (force) || !gh_scm2bool (force)) - Directional_element_interface::set (s, d); - } -} - -/* 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. */ -void -New_beam::consider_auto_knees (Grob *me) -{ - SCM scm = me->get_grob_property ("auto-knee-gap"); - - if (gh_number_p (scm)) - { - bool knee_b = false; - Real knee_y = 0; - Real staff_space = Staff_symbol_referencer::staff_space (me); - Real gap = gh_scm2double (scm) / staff_space; - - Direction d = Directional_element_interface::get (me); - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - 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); - - int l = 0; - for (int i=1; i < stems.size (); i++) - { - if (!Stem::invisible_b (stems[i-1])) - l = i - 1; - if (Stem::invisible_b (stems[l])) - continue; - if (Stem::invisible_b (stems[i])) - continue; - - Real left = Stem::extremal_heads (stems[l])[d] - ->relative_coordinate (common, Y_AXIS); - Real right = Stem::extremal_heads (stems[i])[-d] - ->relative_coordinate (common, Y_AXIS); - - Real dy = right - left; - - if (abs (dy) >= gap) - { - knee_y = (right + left) / 2; - knee_b = true; - break; - } - } - - if (knee_b) - { - for (int i=0; i < stems.size (); i++) - { - if (Stem::invisible_b (stems[i])) - continue; - Item *s = stems[i]; - Real y = Stem::extremal_heads (stems[i])[d] - ->relative_coordinate (common, Y_AXIS); - - Directional_element_interface::set (s, y < knee_y ? UP : DOWN); - s->set_grob_property ("dir-forced", SCM_BOOL_T); - } - } - } -} - -/* Set stem's shorten property if unset. - TODO: - take some y-position (chord/beam/nearest?) into account - scmify forced-fraction */ -void -New_beam::set_stem_shorten (Grob *m) -{ - Spanner*me = dynamic_cast (m); - - Real forced_fraction = forced_stem_count (me) / visible_stem_count (me); - - int multiplicity = get_multiplicity (me); - - SCM shorten = me->get_grob_property ("beamed-stem-shorten"); - if (shorten == SCM_EOL) - return; - - 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. */ -MAKE_SCHEME_CALLBACK (New_beam, after_line_breaking, 1); -SCM -New_beam::after_line_breaking (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - /* Copy to mutable list. */ - SCM s = ly_deep_copy (me->get_grob_property ("position")); - me->set_grob_property ("position", s); - - if (ly_car (s) != SCM_BOOL_F) - return SCM_UNSPECIFIED; - - 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; -} - - -MAKE_SCHEME_CALLBACK (New_beam, least_squares, 1); -SCM -New_beam::least_squares (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - int count = visible_stem_count (me); - if (count <= 1) - return SCM_UNSPECIFIED; - - Direction dir = Directional_element_interface::get (me); - - Interval pos (0, 0); - 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 ()) - { - 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 (!ideal[LEFT] && chord.delta () && count == 2) - { - Direction d = (Direction)(sign (chord.delta ()) * dir); - pos[d] = gh_scm2double (me->get_grob_property ("thickness")) / 2 - * dir; - pos[-d] = - pos[d]; - } - else - pos = ideal; - } - else - { - Array ideals; - - // ugh -> use commonx - Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - for (int i=0; i < stems.size (); i++) - { - Item* s = stems[i]; - if (Stem::invisible_b (s)) - continue; - 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; - Real dy = dydx * dx; - pos = Interval (y*dir, (y+dy) * dir); - } - - me->set_grob_property ("position", ly_interval2scm (pos)); - return SCM_UNSPECIFIED; -} - -MAKE_SCHEME_CALLBACK (New_beam, check_concave, 1); -SCM -New_beam::check_concave (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - Link_array stems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - - for (int i = 0; i < stems.size ();) - { - if (Stem::invisible_b (stems[i])) - stems.del (i); - else - i++; - } - - if (stems.size () < 3) - return SCM_UNSPECIFIED; - - /* Concaveness try #2: Sum distances of inner noteheads that - fall outside the interval of the two outer noteheads */ - Real concave = 0; - Interval iv (Stem::chord_start_f (stems[0]), - Stem::chord_start_f (stems.top ())); - - if (iv[MAX] < iv[MIN]) - iv.swap (); - - for (int i = 1; i < stems.size () - 1; i++) - { - Real c = 0; - Real f = Stem::chord_start_f (stems[i]); - if ((c = f - iv[MAX]) > 0) - concave += c; - else if ((c = f - iv[MIN]) < 0) - concave += c; - } - concave *= Directional_element_interface::get (me); - - Real concaveness = concave / (stems.size () - 2); - /* ugh: this is the a kludge to get input/regression/beam-concave.ly - to behave as baerenreiter. */ - concaveness /= (stems.size () - 2); - - Real r = gh_scm2double (me->get_grob_property ("concaveness-threshold")); - - /* TODO: some sort of damping iso -> plain horizontal */ - if (concaveness > r) - { - Interval pos = ly_scm2interval (me->get_grob_property ("position")); - Real r = pos.linear_combination (0); - me->set_grob_property ("position", ly_interval2scm (Interval (r, r))); - } - - return SCM_UNSPECIFIED; -} - -/* This neat trick is by Werner Lemberg, - damped = tanh (slope) - corresponds with some tables in [Wanske] CHECKME */ -MAKE_SCHEME_CALLBACK (New_beam, slope_damping, 1); -SCM -New_beam::slope_damping (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - if (visible_stem_count (me) <= 1) - return SCM_UNSPECIFIED; - - SCM s = me->get_grob_property ("damping"); - int damping = gh_scm2int (s); - - if (damping) - { - Interval pos = ly_scm2interval (me->get_grob_property ("position")); - Real dy = pos.delta (); - - // ugh -> use commonx - Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - - first_visible_stem (me)->relative_coordinate (0, X_AXIS); - Real dydx = dy && dx ? dy/dx : 0; - dydx = 0.6 * tanh (dydx) / damping; - - Real damped_dy = dydx * dx; - pos[LEFT] += (dy - damped_dy) / 2; - pos[RIGHT] -= (dy - damped_dy) / 2; - - me->set_grob_property ("position", ly_interval2scm (pos)); - } - return SCM_UNSPECIFIED; -} - - -/* Prevent interference from stafflines. */ -Interval -New_beam::quantise_interval (Grob *me, Interval pos, Direction 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 (1), /* junkme */ - gh_double2scm (thick / staff_space), - /* HUH? */ - SCM_EOL, - SCM_UNDEFINED)); - - 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) - return pos; - - 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); - - // quant direction hints disabled for now - int q = 0;//(int)quant_dir; - - /* TODO: make smart choice, find best left/right quants pair. - - 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 - { - 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 qpos; -} - - -/* Quantise vertical position (left and right) of beam. - Generalisation of [Ross]. */ -MAKE_SCHEME_CALLBACK (New_beam, quantise_position, 1); -SCM -New_beam::quantise_position (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - Interval pos = ly_scm2interval (me->get_grob_property ("position")); - Real y_shift = check_stem_length_f (me, pos); - pos += y_shift; - pos = quantise_interval (me, pos, CENTER); - - me->set_grob_property ("position", ly_interval2scm (pos)); - set_stem_lengths (me); - - pos = ly_scm2interval (me->get_grob_property ("position")); - - 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) - { - 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); - pos = quantise_interval (me, pos, (Direction)quant_dir); - } - - me->set_grob_property ("position", ly_interval2scm (pos)); - - return SCM_UNSPECIFIED; -} - -MAKE_SCHEME_CALLBACK (New_beam, end_after_line_breaking, 1); -SCM -New_beam::end_after_line_breaking (SCM smob) -{ - Grob *me = unsmob_grob (smob); - set_stem_lengths (me); - - return SCM_UNSPECIFIED; -} - -Real -New_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; - - 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); - - // 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 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); - - // 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; - } - - return stem_y; -} - -/* Make very sure that we don't have stems that are too short. - Try our best not to have stems that are too long (think: knees). - - Optionally (testing): try to lengthen more, to reach more ideal - stem lengths */ -Real -New_beam::check_stem_length_f (Grob *me, Interval pos) -{ - Real shorten = 0; - Real lengthen = 0; - Direction dir = Directional_element_interface::get (me); - - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - bool knee = false; - int ideal_lengthen_count = 0; - Real ideal_lengthen = 0; - int ideal_shorten_count = 0; - Real ideal_shorten = 0; - - for (int i=0; i < stems.size (); i++) - { - Item* s = stems[i]; - if (Stem::invisible_b (s)) - continue; - - knee |= dir != Directional_element_interface::get (s); - - Real stem_y = calc_stem_y_f (me, s, pos); - - stem_y *= dir; - Stem_info info = Stem::calc_stem_info (s); - - shorten = shorten ? info.miny_f_ - stem_y; - - if (info.idealy_f_ - stem_y > 0) - { - ideal_lengthen += info.idealy_f_ - stem_y; - ideal_lengthen_count++; - } - else if (info.idealy_f_ - stem_y < 0) - { - ideal_shorten += info.idealy_f_ - stem_y; - ideal_shorten_count++; - } - } - - if (lengthen && shorten) - me->warning (_ ("weird beam vertical offset")); - - if (ideal_lengthen_count) - lengthen = (ideal_lengthen / ideal_lengthen_count) >? lengthen; - if (knee && ideal_shorten_count) - shorten = (ideal_shorten / ideal_shorten_count) 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 ("position")); - 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, pos); - - // doesn't play well with dvips - 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) / staff_space * 2); - } -} - -void -New_beam::set_beaming (Grob *me, Beaming_info_list *beaming) -{ - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Grob *)0, "stems"); - - Direction d = LEFT; - for (int i=0; i < stems.size (); i++) - { - do - { - /* Don't overwrite user override (?) */ - if (Stem::beam_count (stems[i], d) == -1 - /* Don't set beaming for outside of outer stems */ - && ! (d == LEFT && i == 0) - && ! (d == RIGHT && i == stems.size () -1)) - { - int b = beaming->infos_.elem (i).beams_i_drul_[d]; - Stem::set_beaming (stems[i], b, d); - } - } - while (flip (&d) != LEFT); - } -} - - - -/* - beams to go with one stem. - - FIXME: clean me up. - */ -Molecule -New_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"); - - 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 bdy = interbeam_f; - - Molecule leftbeams; - Molecule rightbeams; - - Real nw_f; - if (!Stem::first_head (here)) - nw_f = 0; - else { - int t = Stem::type_i (here); - - SCM proc = me->get_grob_property ("flag-width-function"); - SCM result = gh_call1 (proc, gh_int2scm (t)); - nw_f = gh_scm2double (result); - } - - - Direction dir = Directional_element_interface::get (me); - - /* [Tremolo] beams on whole notes may not have direction set? */ - if (dir == CENTER) - dir = Directional_element_interface::get (here); - - - /* 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) - - prev->relative_coordinate (0, X_AXIS); - Real stem_w = gh_scm2double (prev->get_grob_property ("thickness")) - // URG - * me->paper_l ()->get_var ("stafflinethickness"); - - w = w/2 relative_coordinate (0, X_AXIS) - - here->relative_coordinate (0, X_AXIS); - - Real stem_w = gh_scm2double (next->get_grob_property ("thickness")) - // URG - * me->paper_l ()->get_var ("stafflinethickness"); - - Molecule a = Lookup::beam (dydx, w + stem_w, thick); - a.translate_axis (- stem_w/2, X_AXIS); - int j = 0; - Real gap_f = 0; - - SCM gap = me->get_grob_property ("gap"); - if (gh_number_p (gap)) - { - int gap_i = gh_scm2int ((gap)); - int nogap = rwholebeams - gap_i; - - for (; j < nogap; j++) - { - Molecule b (a); - b.translate_axis (-dir * bdy * j, Y_AXIS); - rightbeams.add_molecule (b); - } - if (Stem::invisible_b (here)) - gap_f = nw_f; - else - gap_f = nw_f / 2; - w -= 2 * gap_f; - a = Lookup::beam (dydx, w + stem_w, thick); - } - - for (; j < rwholebeams; j++) - { - Molecule b (a); - Real tx = 0; - if (Stem::invisible_b (here)) - // ugh, see chord-tremolo.ly - tx = (-dir + 1) / 2 * nw_f * 1.5 + gap_f/4; - else - tx = gap_f; - b.translate (Offset (tx, -dir * bdy * j)); - rightbeams.add_molecule (b); - } - - w = w/2 get_grob_property ("stems"))) - return SCM_EOL; - Real x0, dx; - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - if (visible_stem_count (me)) - { - // ugh -> use commonx - x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); - dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; - } - else - { - x0 = stems[0]->relative_coordinate (0, X_AXIS); - dx = stems.top ()->relative_coordinate (0, X_AXIS) - x0; - } - - Interval pos = ly_scm2interval (me->get_grob_property ("position")); - Real dy = pos.delta (); - Real dydx = dy && dx ? dy/dx : 0; - - for (int i=0; i < stems.size (); i++) - { - 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, 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); - - return mol.smobbed_copy (); -} - -int -New_beam::forced_stem_count (Grob *me) -{ - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - int f = 0; - for (int i=0; i < stems.size (); i++) - { - Item *s = stems[i]; - - if (Stem::invisible_b (s)) - continue; - - if (((int)Stem::chord_start_f (s)) - && (Stem::get_direction (s) != Stem::get_default_dir (s))) - f++; - } - return f; -} - - - - -/* TODO: - use filter and standard list functions. - */ -int -New_beam::visible_stem_count (Grob *me) -{ - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - int c = 0; - for (int i = stems.size (); i--;) - { - if (!Stem::invisible_b (stems[i])) - c++; - } - return c; -} - -Item* -New_beam::first_visible_stem (Grob *me) -{ - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - - for (int i = 0; i < stems.size (); i++) - { - if (!Stem::invisible_b (stems[i])) - return stems[i]; - } - return 0; -} - -Item* -New_beam::last_visible_stem (Grob *me) -{ - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - for (int i = stems.size (); i--;) - { - if (!Stem::invisible_b (stems[i])) - return stems[i]; - } - return 0; -} - - -/* - [TODO] - handle rest under beam (do_post: beams are calculated now) - what about combination of collisions and rest under beam. - - Should lookup - - rest -> stem -> beam -> interpolate_y_position () -*/ -MAKE_SCHEME_CALLBACK (New_beam, rest_collision_callback, 2); -SCM -New_beam::rest_collision_callback (SCM element_smob, SCM axis) -{ - Grob *rest = unsmob_grob (element_smob); - Axis a = (Axis) gh_scm2int (axis); - - assert (a == Y_AXIS); - - 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 - || !New_beam::has_interface (beam) - || !New_beam::visible_stem_count (beam)) - return gh_double2scm (0.0); - - // make callback for rest from this. - // todo: make sure this calced already. - - // Interval pos = ly_scm2interval (beam->get_grob_property ("position")); - Interval pos (0, 0); - SCM s = beam->get_grob_property ("position"); - if (gh_pair_p (s)) - pos = ly_scm2interval (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 = dy && dx ? dy/dx : 0; - - Direction d = Stem::get_direction (stem); - 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 minimum_dist - = gh_scm2double (rest->get_grob_property ("minimum-beam-collision-distance")); - Real dist = - minimum_dist + -d * (beamy - rest_dim) >? 0; - - int stafflines = Staff_symbol_referencer::line_count (rest); - - // move discretely by half spaces. - int discrete_dist = int (ceil (dist)); - - // move by whole spaces inside the staff. - if (discrete_dist < stafflines+1) - discrete_dist = int (ceil (discrete_dist / 2.0)* 2.0); - - return gh_double2scm (-d * discrete_dist); -} - - -bool -New_beam::has_interface (Grob *me) -{ - return me->has_interface (ly_symbol2scm ("beam-interface")); -} - 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/grob-description.scm b/scm/grob-description.scm index 78a8fad338..405e280dbc 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -97,31 +97,21 @@ . ( ;; todo: clean this up a bit: the list is getting ;; rather long. - ;(molecule-callback . ,Beam::brew_molecule) - (molecule-callback . ,New_beam::brew_molecule) + (molecule-callback . ,Beam::brew_molecule) (concaveness-threshold . 0.08) - (position . (#f . #f)) - (y-dy-callbacks . (,Beam::least_squares - ,Beam::check_concave - ,Beam::slope_damping - ,Beam::quantise_dy - ,Beam::user_override - ,Beam::do_quantise_y)) - - (position-callbacks . (,New_beam::least_squares - ,New_beam::check_concave - ,New_beam::slope_damping - ,New_beam::quantise_position)) + (positions . (#f . #f)) + (position-callbacks . (,Beam::least_squares + ,Beam::check_concave + ,Beam::slope_damping + ,Beam::quantise_position)) (thickness . 0.48) ; in staff-space (before-line-breaking-callback . ,Beam::before_line_breaking) - ;;(after-line-breaking-callback . ,Beam::after_line_breaking) - (after-line-breaking-callback . (,New_beam::after_line_breaking - ,New_beam::end_after_line_breaking)) + (after-line-breaking-callback . (,Beam::after_line_breaking + ,Beam::end_after_line_breaking)) (neutral-direction . -1) (dir-function . ,beam-dir-majority) - (height-quant-function . ,default-beam-dy-quants) - (vertical-position-quant-function . ,default-beam-y-quants) + (vertical-position-quant-function . ,default-beam-pos-quants) (beamed-stem-shorten . (1.0 0.5)) (outer-stem-length-limit . 0.2) (slope-limit . 0.2) diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm index ddce2affcc..a171dc3db2 100644 --- a/scm/grob-property-description.scm +++ b/scm/grob-property-description.scm @@ -279,6 +279,7 @@ as a real penalty.") (grob-property-description 'pitches list? "list of musical-pitch.") (grob-property-description 'porrectus-width number? "width of the porrectus ligature measured in staff space.") +(grob-property-description 'positions pair? "cons of staff positions (LEFT . RIGHT") (grob-property-description 'raise number? "height for text to be raised (a negative value lowers the text.") (grob-property-description 'right-padding number? "space right of accs.") (grob-property-description 'right-trim-amount number? "shortening of the lyric extender on the right.") 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