+
+ 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));
+ }
+ return SCM_UNSPECIFIED;
+}
+
+/*
+ Quantise dy (height) of beam.
+ Generalisation of [Ross].
+ */
+MAKE_SCHEME_CALLBACK (Beam, quantise_dy, 1);
+SCM
+Beam::quantise_dy (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+
+ if (visible_stem_count (me) <= 1)
+ return SCM_UNSPECIFIED;
+
+ Array<Real> a;
+ 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)
+ {
+ /* 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;
+
+ 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))
+ ? iv[SMALLER]
+ : iv[BIGGER];
+
+ Real quantised_dy = q * sign (dy);
+ Real adjusted_y = y + (dy - quantised_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 (quantised_dy * dir));
+ }
+ return SCM_UNSPECIFIED;
+}
+
+/* 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);
+
+ 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));