+
+
+ Real staff_space = Staff_symbol_referencer::staff_space (me);
+ Real half_space = staff_space / 2;
+ int multiplicity = Beam::get_multiplicity (beam);
+
+
+ SCM space_proc = beam->get_grob_property ("space-function");
+ SCM space = gh_call1 (space_proc, gh_int2scm (multiplicity));
+ Real interbeam_f = gh_scm2double (space) * staff_space;
+
+ Real thick = gh_scm2double (beam->get_grob_property ("thickness"));
+ Stem_info info;
+ info.idealy_f_ = chord_start_f (me);
+
+ // for simplicity, we calculate as if dir == UP
+ info.idealy_f_ *= beam_dir;
+ SCM grace_prop = me->get_grob_property ("grace");
+
+ bool grace_b = to_boolean (grace_prop);
+
+ Array<Real> a;
+ SCM s;
+
+ s = me->get_grob_property ("beamed-minimum-lengths");
+ a.clear ();
+ for (SCM q = s; q != SCM_EOL; q = ly_cdr (q))
+ a.push (gh_scm2double (ly_car (q)));
+
+
+ Real minimum_length = a[multiplicity <? (a.size () - 1)] * staff_space;
+ s = me->get_grob_property ("beamed-lengths");
+
+ a.clear ();
+ for (SCM q = s; q != SCM_EOL; q = ly_cdr (q))
+ a.push (gh_scm2double (ly_car (q)));
+
+ Real stem_length = a[multiplicity <? (a.size () - 1)] * staff_space;
+
+ if (!beam_dir || (beam_dir == Directional_element_interface::get (me)))
+ /* normal beamed stem */
+ {
+ if (multiplicity)
+ {
+ info.idealy_f_ += thick + (multiplicity - 1) * interbeam_f;
+ }
+ info.miny_f_ = info.idealy_f_;
+ info.maxy_f_ = INT_MAX;
+
+ info.idealy_f_ += stem_length;
+ info.miny_f_ += minimum_length;
+
+ /*
+ lowest beam of (UP) beam must never be lower than second staffline
+
+ Hmm, reference (Wanske?)
+
+ Although this (additional) rule is probably correct,
+ I expect that highest beam (UP) should also never be lower
+ than middle staffline, just as normal stems.
+
+ */
+ bool no_extend_b = to_boolean (me->get_grob_property ("no-stem-extend"));
+ if (!grace_b && !no_extend_b)
+ {
+ /* highest beam of (UP) beam must never be lower than middle
+ staffline
+ lowest beam of (UP) beam must never be lower than second staffline
+ */
+ info.miny_f_ =
+ info.miny_f_ >? 0
+ >? (- 2 * half_space - thick
+ + (multiplicity > 0) * thick
+ + interbeam_f * (multiplicity - 1));
+ }
+ }
+ else
+ /* knee */
+ {
+ info.idealy_f_ -= thick;
+ info.maxy_f_ = info.idealy_f_;
+ info.miny_f_ = -INT_MAX;
+
+ info.idealy_f_ -= stem_length;
+ info.maxy_f_ -= minimum_length;
+ }
+
+ info.idealy_f_ = (info.maxy_f_ <? info.idealy_f_) >? info.miny_f_;
+
+ s = beam->get_grob_property ("shorten");
+ if (gh_number_p (s))
+ info.idealy_f_ -= gh_scm2double (s);
+
+ Grob *common = me->common_refpoint (beam, Y_AXIS);
+ Real interstaff_f = beam_dir *
+ (me->relative_coordinate (common, Y_AXIS)
+ - beam->relative_coordinate (common, Y_AXIS));
+
+ info.idealy_f_ += interstaff_f;
+ info.miny_f_ += interstaff_f;
+ info.maxy_f_ += interstaff_f ;
+
+ return info;
+}
+
+bool
+Stem::has_interface (Grob*m)
+{
+ return m && m->has_interface (ly_symbol2scm ("stem-interface"));
+}
+
+void
+Stem::set_interface (Grob*me)
+{
+ me->set_interface (ly_symbol2scm ("stem-interface"));