X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbeam.cc;h=44e6da1dbdda491ea0bb74c83776da725314eb66;hb=8f3edf3cc6aab40cd2aedde70c75ad01f6a34d5e;hp=108f543bc6a022b2f488b5aaacebf8a5f4a62eb3;hpb=76f13ab50fc726c89fa7c96f3deed519d2d773dc;p=lilypond.git diff --git a/lily/beam.cc b/lily/beam.cc index 108f543bc6..44e6da1dbd 100644 --- a/lily/beam.cc +++ b/lily/beam.cc @@ -10,20 +10,21 @@ /* [TODO] + * shorter! (now +- 1000 lines) * less hairy code * move paper vars to scm - remove *-hs variables. + remove *-hs variables, and do all y-position stuff in staff-space. */ #include // tanh. + +#include "molecule.hh" #include "directional-element-interface.hh" #include "beaming.hh" -#include "dimensions.hh" #include "beam.hh" #include "misc.hh" -#include "debug.hh" #include "least-squares.hh" #include "stem.hh" #include "paper-def.hh" @@ -31,44 +32,33 @@ #include "group-interface.hh" #include "staff-symbol-referencer.hh" #include "cross-staff.hh" - -Beam::Beam (SCM s) - : Spanner (s) -{ - Pointer_group_interface g (this, "stems"); - g.set_interface (); - - set_elt_property ("height", gh_int2scm (0)); // ugh. - set_elt_property ("y-position" ,gh_int2scm (0)); -} +#include "item.hh" +#include "spanner.hh" +#include "warn.hh" void -Beam::add_stem (Stem*s) +Beam::add_stem (Grob*me, Grob*s) { - Pointer_group_interface gi (this, "stems"); - gi.add_element (s); + Pointer_group_interface:: add_element(me, "stems", s); - s->add_dependency (this); + s->add_dependency (me); - assert (!s->beam_l ()); - s->set_elt_pointer ("beam", self_scm_); + assert (!Stem::beam_l (s)); + s->set_grob_property ("beam", me->self_scm ()); - if (!get_bound (LEFT)) - set_bound (LEFT,s); - else - set_bound (RIGHT,s); + add_bound_item (dynamic_cast (me), dynamic_cast (s)); } int -Beam::get_multiplicity () const +Beam::get_multiplicity (Grob*me) { int m = 0; - for (SCM s = get_elt_pointer ("stems"); gh_pair_p (s); s = gh_cdr (s)) + for (SCM s = me->get_grob_property ("stems"); gh_pair_p (s); s = gh_cdr (s)) { - Score_element * sc = unsmob_element (gh_car (s)); + Grob * sc = unsmob_grob (gh_car (s)); - if (Stem * st = dynamic_cast (sc)) - m = m >? st->beam_count (LEFT) >? st->beam_count (RIGHT); + if (Stem::has_interface (sc)) + m = m >? Stem::beam_count (sc,LEFT) >? Stem::beam_count (sc,RIGHT); } return m; } @@ -81,29 +71,30 @@ Beam::get_multiplicity () const [Alternatively, stems could set its own directions, according to their beam, during 'final-pre-processing'.] */ -void -Beam::before_line_breaking () +MAKE_SCHEME_CALLBACK(Beam,before_line_breaking,1); +SCM +Beam::before_line_breaking (SCM smob) { + Grob * me = unsmob_grob (smob); + // Why? - if (visible_stem_count () < 2) + if (visible_stem_count (me) < 2) { warning (_ ("beam has less than two stems")); - // set_elt_property ("transparent", SCM_BOOL_T); } - if (!directional_element (this).get ()) - directional_element (this).set (get_default_dir ()); + if (!Directional_element_interface::get (me)) + Directional_element_interface::set (me, get_default_dir (me)); + + auto_knees (me); + set_stem_directions (me); + set_stem_shorten (me); - auto_knees (); - set_stem_directions (); - set_stem_shorten (); + return SCM_EOL; } -/* - FIXME - */ Direction -Beam::get_default_dir () const +Beam::get_default_dir (Grob*me) { Drul_array total; total[UP] = total[DOWN] = 0; @@ -111,12 +102,15 @@ Beam::get_default_dir () const count[UP] = count[DOWN] = 0; Direction d = DOWN; - for (int i=0; i stems= + Pointer_group_interface__extract_elements (me, (Item*)0, "stems"); + + for (int i=0; i get_center_distance ((Direction)-d); + : Stem::get_center_distance (s, (Direction)-d); if (current) { @@ -126,21 +120,20 @@ Beam::get_default_dir () const } while (flip(&d) != DOWN); + SCM func = me->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]))); - SCM s = scm_eval (gh_list (ly_symbol2scm ("beam-dir-algorithm"), - ly_quote_scm (gh_cons (gh_int2scm (count[UP]), - gh_int2scm (count[DOWN]))), - ly_quote_scm (gh_cons (gh_int2scm (total[UP]), - gh_int2scm (total[DOWN]))), - SCM_UNDEFINED)); if (gh_number_p (s) && gh_scm2int (s)) return to_dir (s); /* - If dir is not determined: get from paper + If dir is not determined: get default */ - return (Direction)(int) - paper_l ()->get_var ("stem_default_neutral_direction"); + return to_dir (me->get_grob_property ("default-neutral-direction")); } @@ -150,23 +143,26 @@ Beam::get_default_dir () const once stem gets cleaned-up. */ void -Beam::set_stem_directions () +Beam::set_stem_directions (Grob*me) { - Direction d = directional_element (this).get (); - for (int i=0; i stems + =Pointer_group_interface__extract_elements (me, (Item*) 0, "stems"); + Direction d = Directional_element_interface::get (me); + + for (int i=0; i remove_elt_property ("dir-forced"); + Grob *s = stems[i]; + SCM force = s->remove_grob_property ("dir-forced"); if (!gh_boolean_p (force) || !gh_scm2bool (force)) - directional_element (s).set (d); + Directional_element_interface ::set (s,d); } } void -Beam::auto_knees () +Beam::auto_knees (Grob*me) { - if (!auto_knee ("auto-interstaff-knee-gap", true)) - auto_knee ("auto-knee-gap", false); + if (!auto_knee (me,"auto-interstaff-knee-gap", true)) + auto_knee (me, "auto-knee-gap", false); } /* @@ -177,24 +173,30 @@ Beam::auto_knees () don't set, or unset autoKneeGap/autoInterstaffKneeGap. */ bool -Beam::auto_knee (String gap_str, bool interstaff_b) +Beam::auto_knee (Grob*me, String gap_str, bool interstaff_b) { bool knee_b = false; int knee_y = 0; - SCM gap = get_elt_property (gap_str); - Direction d = directional_element (this).get (); + SCM gap = me->get_grob_property (gap_str.ch_C()); + + Direction d = Directional_element_interface::get (me); + Link_array stems= + Pointer_group_interface__extract_elements (me, (Item*)0, "stems"); if (gh_number_p (gap)) { + Spanner*sp = dynamic_cast (me); int auto_gap_i = gh_scm2int (gap); - for (int i=1; i < stem_count (); i++) + for (int i=1; i < stems.size (); i++) { - bool is_b = (bool)(calc_interstaff_dist (stem (i), this) - - calc_interstaff_dist (stem (i-1), this)); - int l_y = (int)(stem (i-1)->head_positions()[d]) - + (int)calc_interstaff_dist (stem (i-1), this); - int r_y = (int)(stem (i)->head_positions()[d]) - + (int)calc_interstaff_dist (stem (i), this); + bool is_b = (bool)(calc_interstaff_dist (stems[i], sp) + - calc_interstaff_dist (stems[i-1], sp)); + int l_y = (int)(Stem::head_positions(stems[i-1])[d]); + int l_i = (int)calc_interstaff_dist (stems[i-1], sp); + l_y -= l_i; + int r_y = (int)(Stem::head_positions(stems[i])[d]); + int r_i = (int)calc_interstaff_dist (stems[i], sp); + r_y -= r_i; int gap_i = r_y - l_y; if ((abs (gap_i) >= auto_gap_i) && (!interstaff_b || is_b)) @@ -207,12 +209,15 @@ Beam::auto_knee (String gap_str, bool interstaff_b) } if (knee_b) { - for (int i=0; i < stem_count (); i++) + for (int i=0; i < stems.size (); i++) { - int y = (int)(stem (i)->head_positions()[d]) - + (int)calc_interstaff_dist (stem (i), this); - directional_element (stem (i)).set (y < knee_y ? UP : DOWN); - stem (i)->set_elt_property ("dir-forced", SCM_BOOL_T); + Item *s = stems[i]; + int y = (int)(Stem::head_positions(s)[d]); + int y_i = (int)calc_interstaff_dist (s, dynamic_cast (me)); + y -= y_i; + + Directional_element_interface::set (s,y < knee_y ? UP : DOWN); + s->set_grob_property ("dir-forced", SCM_BOOL_T); } } return knee_b; @@ -225,41 +230,42 @@ Beam::auto_knee (String gap_str, bool interstaff_b) scmify forced-fraction */ void -Beam::set_stem_shorten () +Beam::set_stem_shorten (Grob*m) { - if (!visible_stem_count ()) + Spanner*me = dynamic_cast (m); + if (!visible_stem_count (me)) return; - Real forced_fraction = forced_stem_count () / visible_stem_count (); + Real forced_fraction = forced_stem_count (me) / visible_stem_count (me); if (forced_fraction < 0.5) return; - int multiplicity = get_multiplicity (); - - // grace stems? - SCM shorten = scm_eval (ly_symbol2scm ("beamed-stem-shorten")); + int multiplicity = get_multiplicity (me); + SCM shorten = me->get_grob_property ("beamed-stem-shorten"); if (shorten == SCM_EOL) return; int sz = scm_ilength (shorten); - Staff_symbol_referencer_interface st (this); - Real staff_space = st.staff_space (); + Real staff_space = Staff_symbol_referencer::staff_space (me); SCM shorten_elt = scm_list_ref (shorten, gh_int2scm (multiplicity stems= + Pointer_group_interface__extract_elements (me, (Item*)0, "stems"); + + for (int i=0; i < stems.size (); i++) { - Stem* s = stem (i); - if (s->invisible_b ()) + Item* s = stems[i]; + if (Stem::invisible_b (s)) continue; - if (gh_number_p (s->get_elt_property ("shorten"))) - s->set_elt_property ("shorten", gh_double2scm (shorten_f)); + if (gh_number_p (s->get_grob_property ("shorten"))) + s->set_grob_property ("shorten", gh_double2scm (shorten_f)); } } @@ -267,19 +273,22 @@ Beam::set_stem_shorten () Set elt properties height and y-position if not set. Adjust stem lengths to reach beam. */ -void -Beam::after_line_breaking () +MAKE_SCHEME_CALLBACK(Beam,after_line_breaking,1); +SCM +Beam::after_line_breaking (SCM smob) { + Grob * me = unsmob_grob (smob); + /* first, calculate y, dy */ Real y, dy; - calc_default_position_and_height (&y, &dy); - if (visible_stem_count ()) + calc_default_position_and_height (me, &y, &dy); + if (visible_stem_count (me)) { - if (suspect_slope_b (y, dy)) + if (suspect_slope_b (me, y, dy)) dy = 0; - Real damped_dy = calc_slope_damping_f (dy); - Real quantised_dy = quantise_dy_f (damped_dy); + Real damped_dy = calc_slope_damping_f (me, dy); + Real quantised_dy = quantise_dy_f (me, damped_dy); y += (dy - quantised_dy) / 2; dy = quantised_dy; @@ -287,22 +296,26 @@ Beam::after_line_breaking () /* until here, we used only stem_info, which acts as if dir=up */ - y *= directional_element (this).get (); - dy *= directional_element (this).get (); + y *= Directional_element_interface::get (me); + dy *= Directional_element_interface::get (me); + - Staff_symbol_referencer_interface st (this); - Real half_space = st.staff_space () / 2; + Real half_space = Staff_symbol_referencer::staff_space (me) / 2; + /* weird: why do we do calc_position_and_height () ? regardless of + this setting? + + */ /* check for user-override of dy */ - SCM s = remove_elt_property ("height-hs"); + SCM s = me->remove_grob_property ("height-hs"); if (gh_number_p (s)) { dy = gh_scm2double (s) * half_space; } - set_elt_property ("height", gh_double2scm (dy)); + me->set_grob_property ("height", gh_double2scm (dy)); /* check for user-override of y */ - s = remove_elt_property ("y-position-hs"); + s = me->remove_grob_property ("y-position-hs"); if (gh_number_p (s)) { y = gh_scm2double (s) * half_space; @@ -310,11 +323,11 @@ Beam::after_line_breaking () else { /* we can modify y, so we should quantise y */ - Real y_shift = check_stem_length_f (y, dy); + Real y_shift = check_stem_length_f (me, y, dy); y += y_shift; - y = quantise_y_f (y, dy, 0); - set_stem_length (y, dy); - y_shift = check_stem_length_f (y, dy); + y = quantise_y_f (me,y, dy, 0); + set_stem_length (me, y, dy); + y_shift = check_stem_length_f (me, y, dy); if (y_shift > half_space / 4) { @@ -326,29 +339,31 @@ Beam::after_line_breaking () */ int quant_dir = 0; if (abs (y_shift) > half_space / 2) - quant_dir = sign (y_shift) * directional_element (this).get (); - y = quantise_y_f (y, dy, quant_dir); + quant_dir = sign (y_shift) * Directional_element_interface::get (me); + y = quantise_y_f (me, y, dy, quant_dir); } } // UGH. Y is not in staff position unit? // Ik dacht datwe daar juist van weg wilden? - set_stem_length (y, dy); - set_elt_property ("y-position", gh_double2scm (y)); + set_stem_length (me, y, dy); + me->set_grob_property ("y-position", gh_double2scm (y)); + + return SCM_UNSPECIFIED; } /* See Documentation/tex/fonts.doc */ void -Beam::calc_default_position_and_height (Real* y, Real* dy) const +Beam::calc_default_position_and_height (Grob*me,Real* y, Real* dy) { *y = 0; *dy = 0; - if (visible_stem_count () <= 1) + if (visible_stem_count (me) <= 1) return; - Real first_ideal = first_visible_stem ()->calc_stem_info ().idealy_f_; - if (first_ideal == last_visible_stem ()->calc_stem_info ().idealy_f_) + 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_) { *dy = 0; *y = first_ideal; @@ -356,35 +371,41 @@ Beam::calc_default_position_and_height (Real* y, Real* dy) const } Array ideals; - Real x0 = first_visible_stem ()->relative_coordinate (0, X_AXIS); - for (int i=0; i < stem_count (); i++) + + // ugh -> use commonx + Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); + Link_array stems= + Pointer_group_interface__extract_elements (me, (Item*)0, "stems"); + + for (int i=0; i < stems.size (); i++) { - Stem* s = stem (i); - if (s->invisible_b ()) + Item* s = stems[i]; + if (Stem::invisible_b (s)) continue; ideals.push (Offset (s->relative_coordinate (0, X_AXIS) - x0, - s->calc_stem_info ().idealy_f_)); + Stem::calc_stem_info (s).idealy_f_)); } Real dydx; minimise_least_squares (&dydx, y, ideals); // duh, takes references - Real dx = last_visible_stem ()->relative_coordinate (0, X_AXIS) - x0; + Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; *dy = dydx * dx; } bool -Beam::suspect_slope_b (Real y, Real dy) const +Beam::suspect_slope_b (Grob*me, Real y, Real dy) { /* first, calculate y, dy */ /* steep slope running against lengthened stem is suspect */ - Real first_ideal = first_visible_stem ()->calc_stem_info ().idealy_f_; - Real last_ideal = last_visible_stem ()->calc_stem_info ().idealy_f_; - Real lengthened = paper_l ()->get_var ("beam_lengthened"); - Real steep = paper_l ()->get_var ("beam_steep_slope"); + Real first_ideal = Stem::calc_stem_info (first_visible_stem (me)).idealy_f_; + Real last_ideal = Stem::calc_stem_info (last_visible_stem (me)).idealy_f_; + Real lengthened = gh_scm2double (me->get_grob_property ("outer-stem-length-limit")); + Real steep = gh_scm2double (me->get_grob_property ("slope-limit")); - Real dx = last_visible_stem ()->relative_coordinate (0, X_AXIS) - first_visible_stem ()->relative_coordinate (0, X_AXIS); + // 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; if (((y - first_ideal > lengthened) && (dydx > steep)) @@ -401,17 +422,16 @@ Beam::suspect_slope_b (Real y, Real dy) const corresponds with some tables in [Wanske] */ Real -Beam::calc_slope_damping_f (Real dy) const +Beam::calc_slope_damping_f (Grob*me,Real dy) { - SCM damp = get_elt_property ("damping"); // remove? - int damping = 1; // ugh. - if (gh_number_p (damp)) - damping = gh_scm2int (damp); + SCM damp = me->get_grob_property ("damping"); + int damping = gh_scm2int (damp); if (damping) { - Real dx = last_visible_stem ()->relative_coordinate (0, X_AXIS) - - first_visible_stem ()->relative_coordinate (0, X_AXIS); + // 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; return dydx * dx; @@ -420,22 +440,25 @@ Beam::calc_slope_damping_f (Real dy) const } Real -Beam::calc_stem_y_f (Stem* s, Real y, Real dy) const +Beam::calc_stem_y_f (Grob*me,Item* s, Real y, Real dy) { - Real thick = gh_scm2double (get_elt_property ("beam-thickness")); - thick *= paper_l ()->get_var ("staffspace"); - - int beam_multiplicity = get_multiplicity (); - int stem_multiplicity = (s->flag_i () - 2) >? 0; + int beam_multiplicity = get_multiplicity (me); + int stem_multiplicity = (Stem::flag_i (s) - 2) >? 0; - Real interbeam_f = paper_l ()->interbeam_f (beam_multiplicity); - Real x0 = first_visible_stem ()->relative_coordinate (0, X_AXIS); - Real dx = last_visible_stem ()->relative_coordinate (0, X_AXIS) - x0; + 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 stem_y = (dy && dx ? (s->relative_coordinate (0, X_AXIS) - x0) / dx * dy : 0) + y; /* knee */ - Direction dir = directional_element(this).get (); - Direction sdir = directional_element (s).get (); + Direction dir = Directional_element_interface::get (me); + Direction sdir = Directional_element_interface::get (s); /* knee */ if (dir!= sdir) @@ -443,35 +466,38 @@ Beam::calc_stem_y_f (Stem* s, Real y, Real dy) const stem_y -= dir * (thick / 2 + (beam_multiplicity - 1) * interbeam_f); - Staff_symbol_referencer_interface me (s); - Staff_symbol_referencer_interface last (last_visible_stem ()); + // huh, why not for first visible? - if (//(s != first_visible_stem ()) && - me.staff_symbol_l () != last.staff_symbol_l ()) - stem_y += directional_element (this).get () - * (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; } Real -Beam::check_stem_length_f (Real y, Real dy) const +Beam::check_stem_length_f (Grob*me,Real y, Real dy) { Real shorten = 0; Real lengthen = 0; - Direction dir = directional_element (this).get (); - - for (int i=0; i < stem_count (); i++) + Direction dir = Directional_element_interface::get (me); + + Link_array stems= + Pointer_group_interface__extract_elements (me, (Item*)0, "stems"); + + for (int i=0; i < stems.size(); i++) { - Stem* s = stem (i); - if (s->invisible_b ()) + Item* s = stems[i]; + if (Stem::invisible_b (s)) continue; - Real stem_y = calc_stem_y_f (s, y, dy); + Real stem_y = calc_stem_y_f (me, s, y, dy); stem_y *= dir; - Stem_info info = s->calc_stem_info (); + Stem_info info = Stem::calc_stem_info (s); // if (0 > info.maxy_f_ - stem_y) shorten = shorten stems= + Pointer_group_interface__extract_elements (me, (Item*)0, "stems"); + + + for (int i=0; i < stems.size (); i++) { - Stem* s = stem (i); - if (s->invisible_b ()) + Item* s = stems[i]; + if (Stem::invisible_b (s)) continue; - Real stem_y = calc_stem_y_f (s, y, dy); + Real stem_y = calc_stem_y_f (me, s, y, dy); /* caution: stem measures in staff-positions */ - s->set_stemend ((stem_y + calc_interstaff_dist (s, this)) / half_space); + Stem::set_stemend (s,(stem_y + calc_interstaff_dist (s, dynamic_cast (me))) / half_space); } } @@ -517,17 +546,23 @@ Beam::set_stem_length (Real y, Real dy) + n * staff_space */ Real -Beam::quantise_dy_f (Real dy) const +Beam::quantise_dy_f (Grob*me,Real dy) { Array a; - for (SCM s = scm_eval (ly_symbol2scm ("beam-height-quants")); s !=SCM_EOL; s = gh_cdr (s)) + + SCM proc = me->get_grob_property ("height-quants"); + SCM quants = gh_call2 (proc, me->self_scm (), + gh_double2scm (me->paper_l ()->get_var ("stafflinethickness") + / 1.0)); + + + for (SCM s = quants; gh_pair_p (s); s = gh_cdr (s)) a.push (gh_scm2double (gh_car (s))); if (a.size () <= 1) return dy; - Staff_symbol_referencer_interface st (this); - Real staff_space = st.staff_space (); + Real staff_space = Staff_symbol_referencer::staff_space (me); Interval iv = quantise_iv (a, abs (dy)/staff_space) * staff_space; Real q = (abs (dy) - iv[SMALLER] <= iv[BIGGER] - abs (dy)) @@ -546,25 +581,31 @@ Beam::quantise_dy_f (Real dy) const if extend_b then stems must *not* get shorter */ Real -Beam::quantise_y_f (Real y, Real dy, int quant_dir) +Beam::quantise_y_f (Grob*me,Real y, Real dy, int quant_dir) { - int multiplicity = get_multiplicity (); - Staff_symbol_referencer_interface st (this); - Real staff_space = st.staff_space (); - SCM quants = scm_eval (gh_list (ly_symbol2scm ("beam-vertical-position-quants"), - gh_int2scm (multiplicity), - gh_double2scm (dy/staff_space), - SCM_UNDEFINED)); + 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 (), + gh_list (gh_int2scm (multiplicity), + gh_double2scm (dy/staff_space), + gh_double2scm (thick/staff_space), + SCM_EOL, SCM_UNDEFINED)); + Array a; - for (; quants != SCM_EOL; quants = gh_cdr (quants)) + for (; gh_pair_p (quants); quants = gh_cdr (quants)) a.push (gh_scm2double (gh_car (quants))); if (a.size () <= 1) return y; - Real up_y = directional_element (this).get () * 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 @@ -572,19 +613,29 @@ Beam::quantise_y_f (Real y, Real dy, int quant_dir) if (quant_dir) q = iv[(Direction)quant_dir]; - return q * directional_element (this).get (); + return q * Directional_element_interface::get (me); } void -Beam::set_beaming (Beaming_info_list *beaming) +Beam::set_beaming (Grob*me,Beaming_info_list *beaming) { + Link_array stems= + Pointer_group_interface__extract_elements (me, (Grob*)0, "stems"); + Direction d = LEFT; - for (int i=0; i < stem_count (); i++) + for (int i=0; i < stems.size(); i++) { do { - if (stem (i)->beam_count (d) == 0) - stem (i)->set_beaming ( beaming->infos_.elem (i).beams_i_drul_[d],d); + /* Don't overwrite user override (?) */ + if (Stem::beam_count (stems[i], d) == 0 + /* 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); } @@ -595,55 +646,57 @@ Beam::set_beaming (Beaming_info_list *beaming) /* beams to go with one stem. - BURP - clean me up. + FIXME: clean me up. */ Molecule -Beam::stem_beams (Stem *here, Stem *next, Stem *prev) const +Beam::stem_beams (Grob*me,Item *here, Item *next, Item *prev) { + // 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"); - Real staffline_f = paper_l ()->get_var ("stafflinethickness"); - int multiplicity = get_multiplicity (); + Real staffline_f = me->paper_l ()->get_var ("stafflinethickness"); + int multiplicity = get_multiplicity (me); + SCM space_proc = me->get_grob_property ("space-function"); + SCM space = gh_call1 (space_proc, gh_int2scm (multiplicity)); - Real interbeam_f = paper_l ()->interbeam_f (multiplicity); - Real thick = gh_scm2double (get_elt_property ("beam-thickness")); - thick *= paper_l ()->get_var ("staffspace"); + Real thick = gh_scm2double (me->get_grob_property ("thickness")) ; + Real interbeam_f = gh_scm2double (space) ; Real bdy = interbeam_f; Real stemdx = staffline_f; - Real dx = visible_stem_count () ? - last_visible_stem ()->relative_coordinate (0, X_AXIS) - first_visible_stem ()->relative_coordinate (0, X_AXIS) + // 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; - Real dy = gh_scm2double (get_elt_property ("height")); + Real dy = gh_scm2double (me->get_grob_property ("height")); Real dydx = dy && dx ? dy/dx : 0; Molecule leftbeams; Molecule rightbeams; - // UGH Real nw_f; - if (!here->first_head ()) + if (!Stem::first_head (here)) nw_f = 0; - else if (here->type_i ()== 1) - nw_f = paper_l ()->get_var ("wholewidth"); - else if (here->type_i () == 2) - nw_f = paper_l ()->get_var ("notewidth") * 0.8; - else - nw_f = paper_l ()->get_var ("quartwidth"); + 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 (this).get (); + Direction dir = Directional_element_interface::get (me); /* half beams extending to the left. */ if (prev) { - int lhalfs= lhalfs = here->beam_count (LEFT) - prev->beam_count (RIGHT); - int lwholebeams= here->beam_count (LEFT) beam_count (RIGHT) ; + int lhalfs= lhalfs = Stem::beam_count (here,LEFT) - Stem::beam_count (prev,RIGHT); + int lwholebeams= Stem::beam_count (here,LEFT) beam (dydx, w, thick); + a = Lookup::beam (dydx, w, thick); a.translate (Offset (-w, -w * dydx)); for (int j = 0; j < lhalfs; j++) { @@ -664,16 +717,16 @@ Beam::stem_beams (Stem *here, Stem *next, Stem *prev) const if (next) { - int rhalfs = here->beam_count (RIGHT) - next->beam_count (LEFT); - int rwholebeams= here->beam_count (RIGHT) beam_count (LEFT) ; + 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); - Molecule a = lookup_l ()->beam (dydx, w + stemdx, thick); + Molecule a = Lookup::beam (dydx, w + stemdx, thick); a.translate_axis( - stemdx/2, X_AXIS); int j = 0; Real gap_f = 0; - SCM gap = get_elt_property ("beam-gap"); + SCM gap = me->get_grob_property ("gap"); if (gh_number_p (gap)) { int gap_i = gh_scm2int ( (gap)); @@ -688,19 +741,19 @@ Beam::stem_beams (Stem *here, Stem *next, Stem *prev) const // TODO: notehead widths differ for different types gap_f = nw_f / 2; w -= 2 * gap_f; - a = lookup_l ()->beam (dydx, w + stemdx, thick); + a = Lookup::beam (dydx, w + stemdx, thick); } for (; j < rwholebeams; j++) { Molecule b (a); - b.translate (Offset (here->invisible_b () ? 0 : gap_f, -dir * bdy * j)); + b.translate (Offset (Stem::invisible_b (here) ? 0 : gap_f, -dir * bdy * j)); rightbeams.add_molecule (b); } w = w/2 beam (dydx, w, thick); + a = Lookup::beam (dydx, w, thick); for (; j < rwholebeams + rhalfs; j++) { @@ -719,122 +772,209 @@ Beam::stem_beams (Stem *here, Stem *next, Stem *prev) const return leftbeams; } +/* + TODO: it would be nice to introduce y-position via callbacks. + */ -Molecule -Beam::do_brew_molecule () const +MAKE_SCHEME_CALLBACK(Beam,brew_molecule,1); +SCM +Beam::brew_molecule (SCM smob) { + Grob * me =unsmob_grob (smob); + Molecule mol; - if (!stem_count ()) - return mol; + if (!gh_pair_p (me->get_grob_property ("stems"))) + return SCM_EOL; Real x0,dx; - if (visible_stem_count ()) + Link_arraystems = + Pointer_group_interface__extract_elements (me, (Item*) 0, "stems"); + if (visible_stem_count (me)) { - x0 = first_visible_stem ()->relative_coordinate (0, X_AXIS); - dx = last_visible_stem ()->relative_coordinate (0, X_AXIS) - x0; + // 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 = stem (0)->relative_coordinate (0, X_AXIS); - dx = stem_top ()->relative_coordinate (0, X_AXIS) - x0; + x0 = stems[0]->relative_coordinate (0, X_AXIS); + dx = stems.top()->relative_coordinate (0, X_AXIS) - x0; } - Real dy = gh_scm2double (get_elt_property ("height")); + Real dy = gh_scm2double (me->get_grob_property ("height")); Real dydx = dy && dx ? dy/dx : 0; - Real y = gh_scm2double (get_elt_property ("y-position")); - for (int j=0; j get_grob_property ("y-position")); + + + for (int j=0; j 0)? stem (j-1) : 0; - Stem * next = (j < stem_count ()-1) ? stem (j+1) :0; + Item *i = stems[j]; + Item * prev = (j > 0)? stems[j-1] : 0; + Item * next = (j < stems.size()-1) ? stems[j+1] :0; - Molecule sb = stem_beams (i, next, prev); + Molecule sb = stem_beams (me, i, next, prev); Real x = i->relative_coordinate (0, X_AXIS)-x0; sb.translate (Offset (x, x * dydx + y)); mol.add_molecule (sb); } mol.translate_axis (x0 - - 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; + return mol.smobbed_copy (); } int -Beam::forced_stem_count () const +Beam::forced_stem_count (Grob*me) { + Link_arraystems = + Pointer_group_interface__extract_elements ( me, (Item*) 0, "stems"); int f = 0; - for (int i=0; i < stem_count (); i++) + for (int i=0; i < stems.size (); i++) { - Stem *s = stem (i); + Item *s = stems[i]; - if (s->invisible_b ()) + if (Stem::invisible_b (s)) continue; - if (((int)s->chord_start_f ()) - && (s->get_direction () != s->get_default_dir ())) + if (((int)Stem::chord_start_f (s)) + && (Stem::get_direction (s ) != Stem::get_default_dir (s ))) f++; } return f; } -/* - TODO: Fix this class. This is wildly inefficient. - And it sux. Yet another array/list 'interface'. - */ -Stem * -Beam::stem (int i) const -{ - return Pointer_group_interface__extract_elements ((Beam*) this, (Stem*) 0, "stems")[i]; -} -int -Beam::stem_count () const -{ - Pointer_group_interface gi (this, "stems"); - return gi.count (); -} -Stem* -Beam::stem_top () const -{ - SCM s = get_elt_pointer ("stems"); - - return gh_pair_p (s) ? dynamic_cast (unsmob_element (gh_car (s))) : 0; -} -/* burp */ +/* TODO: + use filter and standard list functions. + */ int -Beam::visible_stem_count () const +Beam::visible_stem_count (Grob*me) { + Link_arraystems = + Pointer_group_interface__extract_elements (me, (Item*) 0, "stems"); int c = 0; - for (int i = 0; i < stem_count (); i++) + for (int i = stems.size (); i--;) { - if (!stem (i)->invisible_b ()) + if (!Stem::invisible_b (stems[i])) c++; } return c; } -Stem* -Beam::first_visible_stem () const +Item* +Beam::first_visible_stem(Grob*me) { - for (int i = 0; i < stem_count (); i++) + Link_arraystems = + Pointer_group_interface__extract_elements ( me, (Item*) 0, "stems"); + + for (int i = 0; i < stems.size (); i++) { - Stem* s = stem (i); - if (!s->invisible_b ()) - return s; + if (!Stem::invisible_b (stems[i])) + return stems[i]; } return 0; } -Stem* -Beam::last_visible_stem () const +Item* +Beam::last_visible_stem(Grob*me) { - for (int i = stem_count (); i > 0; i--) + Link_arraystems = + Pointer_group_interface__extract_elements ( me, (Item*) 0, "stems"); + for (int i = stems.size (); i--;) { - Stem* s = stem (i - 1); - if (!s->invisible_b ()) - return s; + 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(Beam,rest_collision_callback,2); +SCM +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 || !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. + SCM s = beam->get_grob_property ("height"); + if (gh_number_p (s)) + beam_dy = gh_scm2double (s); + + s = beam->get_grob_property ("y-position"); + if (gh_number_p (s)) + beam_y = gh_scm2double (s); + + // 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; + + Direction d = Stem::get_direction (stem); + Real beamy = (stem->relative_coordinate (0, X_AXIS) - x0) * dydx + beam_y; + + 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 +Beam::has_interface (Grob*me) +{ + return me->has_interface (ly_symbol2scm ("beam-interface")); +} + +void +Beam::set_interface (Grob*me) +{ + /* + why the init? No way to tell difference between default and user + override. */ + me->set_grob_property ("height", gh_int2scm (0)); // ugh. + me->set_grob_property ("y-position" ,gh_int2scm (0)); + me->set_interface (ly_symbol2scm("beam-interface")); +}