Jan Nieuwenhuizen <janneke@gnu.org>
TODO: This is way too hairy
+
+ TODO: fix naming.
+
+ Stem-end, chord-start, etc. is all confusing naming.
*/
-#include <math.h> // m_pi
+#include <math.h> // rint
#include "lookup.hh"
#include "directional-element-interface.hh"
#include "note-head.hh"
#include "stem.hh"
-#include "debug.hh"
+#include "warn.hh"
#include "paper-def.hh"
#include "rhythmic-head.hh"
#include "font-interface.hh"
#include "staff-symbol-referencer.hh"
#include "spanner.hh"
#include "side-position-interface.hh"
+#include "dot-column.hh"
void
-Stem::set_beaming (Grob*me ,int i, Direction d)
+Stem::set_beaming (Grob*me, int beam_count, Direction d)
{
SCM pair = me->get_grob_property ("beaming");
if (!gh_pair_p (pair))
{
- pair = gh_cons (gh_int2scm (-1),gh_int2scm (-1));
- me-> set_grob_property ("beaming", pair);
+ pair = gh_cons (SCM_EOL, SCM_EOL);
+ me->set_grob_property ("beaming", pair);
}
- index_set_cell (pair, d, gh_int2scm (i));
-}
-int
-Stem::beam_count (Grob*me,Direction d)
-{
- SCM p=me->get_grob_property ("beaming");
- if (gh_pair_p (p))
- return gh_scm2int (index_cell (p,d));
- else
- return -1;
+ SCM l = index_get_cell (pair, d);
+ for( int i = 0; i< beam_count; i++)
+ {
+ l = gh_cons (gh_int2scm (i), l);
+ }
+ index_set_cell (pair, d, l);
}
+
Interval
Stem::head_positions (Grob*me)
{
- if (!heads_i (me))
+ if (!head_count (me))
{
Interval iv;
return iv;
Drul_array<Grob*> e (extremal_heads (me));
- return Interval (Staff_symbol_referencer::position_f (e[DOWN]),
- Staff_symbol_referencer::position_f (e[UP]));
+ return Interval (Staff_symbol_referencer::get_position (e[DOWN]),
+ Staff_symbol_referencer::get_position (e[UP]));
}
Real
-Stem::chord_start_f (Grob*me)
+Stem::chord_start_y (Grob*me)
{
return head_positions (me)[get_direction (me)]
* Staff_symbol_referencer::staff_space (me)/2.0;
me->set_grob_property ("stem-end-position", gh_double2scm (se));
}
-int
-Stem::type_i (Grob*me)
-{
- return first_head (me) ? Rhythmic_head::balltype_i (first_head (me)) : 2;
-}
/*
Note head that determines hshift for upstems
Grob * nh = unsmob_grob (h);
if (nh)
return nh;
- else if (heads_i (me) == 1)
+ else if (head_count (me) == 1)
{
/*
UGH.
*/
- return unsmob_grob (ly_car (me->get_grob_property ("heads")));
+ return unsmob_grob (ly_car (me->get_grob_property ("note-heads")));
}
else
return first_head (me);
int
-Stem::heads_i (Grob*me)
+Stem::head_count (Grob*me)
{
- return Pointer_group_interface::count (me, "heads");
+ return Pointer_group_interface::count (me, "note-heads");
}
/*
Grob*
Stem::first_head (Grob*me)
{
- return extremal_heads (me)[-get_direction (me)];
+ Direction d = get_direction (me);
+ if (!d)
+ return 0;
+ return extremal_heads (me)[-d];
+}
+
+/*
+ The note head opposite to the first head.
+ */
+Grob*
+Stem::last_head (Grob*me)
+{
+ Direction d = get_direction (me);
+ if (!d)
+ return 0;
+ return extremal_heads (me)[d];
}
/*
Drul_array<Grob *> exthead;
exthead[LEFT] = exthead[RIGHT] =0;
- for (SCM s = me->get_grob_property ("heads"); gh_pair_p (s); s = ly_cdr (s))
+ for (SCM s = me->get_grob_property ("note-heads"); gh_pair_p (s); s = ly_cdr (s))
{
Grob * n = unsmob_grob (ly_car (s));
- int p = int (Staff_symbol_referencer::position_f (n));
+ int p = int (Staff_symbol_referencer::get_position (n));
Direction d = LEFT;
do {
Stem::note_head_positions (Grob *me)
{
Array<int> ps ;
- for (SCM s = me->get_grob_property ("heads"); gh_pair_p (s); s = ly_cdr (s))
+ for (SCM s = me->get_grob_property ("note-heads"); gh_pair_p (s); s = ly_cdr (s))
{
Grob * n = unsmob_grob (ly_car (s));
- int p = int (Staff_symbol_referencer::position_f (n));
+ int p = int (Staff_symbol_referencer::get_position (n));
ps.push (p);
}
if (Note_head::has_interface (n))
{
- Pointer_group_interface::add_grob (me, ly_symbol2scm ("heads"), n);
- }
- else
- {
- n->set_grob_property ("rest", n->self_scm ());
+ Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-heads"), n);
}
}
bool
Stem::invisible_b (Grob*me)
{
- return ! (heads_i (me) && Rhythmic_head::balltype_i (support_head (me)) >= 1);
-}
-
-int
-Stem::get_center_distance (Grob*me, Direction d)
-{
- int staff_center = 0;
- int distance = (int) (d* (head_positions (me)[d] - staff_center));
- return distance >? 0;
+ return ! (head_count (me) && Note_head::get_balltype (support_head (me)) >= 1);
}
Direction
Stem::get_default_dir (Grob*me)
{
- int du = get_center_distance (me,UP);
- int dd = get_center_distance (me,DOWN);
-
- if (sign (dd - du))
- return Direction (sign (dd -du));
+ int staff_center = 0;
+ Interval hp = head_positions (me);
+ if (hp.empty_b())
+ {
+ return CENTER;
+ }
+
+ int udistance = (int) (UP * hp[UP] - staff_center);
+ int ddistance = (int) (DOWN* hp[DOWN] - staff_center);
+
+ if (sign (ddistance - udistance))
+ return Direction (sign (ddistance -udistance));
return to_dir (me->get_grob_property ("neutral-direction"));
}
Real
Stem::get_default_stem_end_position (Grob*me)
{
+ SCM up_to_staff = me->get_grob_property ("up-to-staff");
+ if (to_boolean(up_to_staff))
+ {
+ int line_count = Staff_symbol_referencer::line_count (me);
+
+ Direction dir = get_direction (me);
+
+ return dir* (line_count + 3.5);
+ }
+
bool grace_b = to_boolean (me->get_grob_property ("grace"));
SCM s;
Array<Real> a;
- Real length_f = 0.;
+ Real length_f = 3.5;
SCM scm_len = me->get_grob_property ("length");
if (gh_number_p (scm_len))
{
else
{
s = me->get_grob_property ("lengths");
- for (SCM q = s; q != SCM_EOL; q = ly_cdr (q))
- a.push (gh_scm2double (ly_car (q)));
-
- // stem uses half-spaces
- length_f = a[ ((flag_i (me) - 2) >? 0) <? (a.size () - 1)] * 2;
+ if (gh_pair_p (s))
+ {
+ length_f = 2* gh_scm2double (robust_list_ref (duration_log(me) -2, s));
+ }
}
- a.clear ();
- s = me->get_grob_property ("stem-shorten");
- for (SCM q = s; gh_pair_p (q); q = ly_cdr (q))
- a.push (gh_scm2double (ly_car (q)));
-
-
- // stem uses half-spaces
-
- // fixme: use scm_list_n_ref () iso. array[]
- Real shorten_f = a[ ((flag_i (me) - 2) >? 0) <? (a.size () - 1)] * 2;
+ Real shorten_f = 0.0;
+
+ SCM sshorten = me->get_grob_property ("stem-shorten");
+ if (gh_pair_p (sshorten))
+ {
+ shorten_f = 2* gh_scm2double (robust_list_ref ((duration_log (me) - 2) >? 0, sshorten));
+ }
/* On boundary: shorten only half */
- if (abs (chord_start_f (me)) == 0.5)
+ if (abs (chord_start_y (me)) == 0.5)
shorten_f *= 0.5;
/* URGURGURG
/* stems in unnatural (forced) direction should be shortened,
according to [Roush & Gourlay] */
- if (chord_start_f (me)
+ if (chord_start_y (me)
&& (get_direction (me) != get_default_dir (me)))
length_f -= shorten_f;
Interval hp = head_positions (me);
Real st = hp[dir] + dir * length_f;
-
-
+ bool no_extend_b = to_boolean (me->get_grob_property ("no-stem-extend"));
+ if (!grace_b && !no_extend_b && dir * st < 0) // junkme?
+ st = 0.0;
/*
- Make a little room if we have a flag and there is a dot.
-
- TODO:
-
- maybe we should consider moving the dot to the right?
+ Make a little room if we have a upflag and there is a dot.
+ previous approach was to lengthen the stem. This is not
+ good typesetting practice.
+
*/
- if (!beam_l (me)
- && flag_i (me))
+ if (!get_beam (me) && dir == UP
+ && duration_log (me) > 2)
{
Grob * closest_to_flag = extremal_heads (me)[dir];
Grob * dots = closest_to_flag
- ? Rhythmic_head::dots_l (closest_to_flag ) : 0;
+ ? Rhythmic_head::get_dots (closest_to_flag ) : 0;
if (dots)
{
- Real dp = Staff_symbol_referencer::position_f (dots);
- Real flagy = flag (me).extent (Y_AXIS)[-dir] * 2; // should divide by staffspace
+ Real dp = Staff_symbol_referencer::get_position (dots);
+ Real flagy = flag (me).extent (Y_AXIS)[-dir] * 2
+ / Staff_symbol_referencer::staff_space (me);
/*
Very gory: add myself to the X-support of the parent,
which should be a dot-column.
*/
if (dir * (st + flagy - dp) < 0.5)
- Side_position_interface::add_support (dots->get_parent (X_AXIS), me);
-
- /*
- previous approach was to lengthen the stem. This is not
- good typesetting practice. */
+ {
+ Grob *par = dots->get_parent (X_AXIS);
+
+ if (Dot_column::has_interface (par))
+ {
+ Side_position_interface::add_support (par, me);
+
+ /*
+ TODO: apply some better logic here. The flag is
+ curved inwards, so this will typically be too
+ much.
+ */
+ }
+ }
}
}
- bool no_extend_b = to_boolean (me->get_grob_property ("no-stem-extend"));
- if (!grace_b && !no_extend_b && dir * st < 0) // junkme?
- st = 0.0;
-
return st;
}
/*
- Number of hooks on the flag, ie. the log of the duration.
+
+ the log of the duration (Number of hooks on the flag minus two)
*/
int
-Stem::flag_i (Grob*me)
+Stem::duration_log (Grob*me)
{
SCM s = me->get_grob_property ("duration-log");
return (gh_number_p (s)) ? gh_scm2int (s) : 2;
void
Stem::position_noteheads (Grob*me)
{
- if (!heads_i (me))
+ if (!head_count (me))
return;
Link_array<Grob> heads =
- Pointer_group_interface__extract_grobs (me, (Grob*)0, "heads");
+ Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-heads");
heads.sort (compare_position);
Direction dir =get_direction (me);
heads.reverse ();
+ bool invisible = invisible_b (me);
+ Real thick = 0.0;
+ if (invisible)
+ thick = gh_scm2double (me->get_grob_property ("thickness"))
+ * me->get_paper ()->get_var ("linethickness");
+
+
Grob *hed = support_head (me);
Real w = Note_head::head_extent (hed,X_AXIS)[dir];
for (int i=0; i < heads.size (); i++)
}
bool parity= true; // todo: make me settable.
- int lastpos = int (Staff_symbol_referencer::position_f (heads[0]));
+ int lastpos = int (Staff_symbol_referencer::get_position (heads[0]));
for (int i=1; i < heads.size (); i ++)
{
- Real p = Staff_symbol_referencer::position_f (heads[i]);
+ Real p = Staff_symbol_referencer::get_position (heads[i]);
int dy =abs (lastpos- (int)p);
if (dy <= 1)
{
Real l = Note_head::head_extent (heads[i], X_AXIS).length ();
- heads[i]->translate_axis (l * get_direction (me), X_AXIS);
+ Direction d = get_direction (me);
+ heads[i]->translate_axis (l * d, X_AXIS);
+
+ if (invisible_b(me))
+ heads[i]->translate_axis (-thick *2* d , X_AXIS);
+
+
+ /* TODO:
+
+ For some cases we should kern some more: when the
+ distance between the next or prev note is too large, we'd
+ get large white gaps, eg.
+
+ |
+ X|
+ |X <- kern this.
+ |
+ X
+
+ */
}
parity = !parity;
}
Stem::before_line_breaking (SCM smob)
{
Grob*me = unsmob_grob (smob);
- stem_end_position (me); // ugh. Trigger direction calc.
- position_noteheads (me);
- if (invisible_b (me))
+
+ /*
+ Do the calculations for visible stems, but also for invisible stems
+ with note heads (i.e. half notes.)
+ */
+ if (head_count (me))
+ {
+ stem_end_position (me); // ugh. Trigger direction calc.
+ position_noteheads (me);
+ }
+ else
{
me->remove_grob_property ("molecule-callback");
- // suicide ();
}
return SCM_UNSPECIFIED;
}
bool adjust = to_boolean (me->get_grob_property ("adjust-if-on-staffline"));
- if (String::compare_i (style, "mensural") == 0)
+ if (String::compare (style, "mensural") == 0)
/* Mensural notation: For notes on staff lines, use different
flags than for notes between staff lines. The idea is that
flags are always vertically aligned with the staff lines,
looks slightly misplaced, but that will usually be the
programmer's fault (e.g. when trying to attach multiple
note heads to a single stem in mensural notation). */
+
+ /*
+ perhaps the detection whether this correction is needed should
+ happen in a different place to avoid the recursion.
+
+ --hwn.
+ */
Grob *first = first_head(me);
int sz = Staff_symbol_referencer::line_count (me)-1;
- int p = (int)rint (Staff_symbol_referencer::position_f (first));
+ int p = (int)rint (Staff_symbol_referencer::get_position (first));
staffline_offs = (((p ^ sz) & 0x1) == 0) ? "1" : "0";
}
else
staffline_offs = "";
}
char c = (get_direction (me) == UP) ? 'u' : 'd';
- String index_str
- = String ("flags-") + style + to_str (c) + staffline_offs + to_str (flag_i (me));
+ String index_string
+ = String ("flags-") + style + to_string (c) + staffline_offs + to_string (duration_log (me));
Molecule m
- = Font_interface::get_default_font (me)->find_by_name (index_str);
+ = Font_interface::get_default_font (me)->find_by_name (index_string);
if (!fstyle.empty_b ())
- m.add_molecule (Font_interface::get_default_font (me)->find_by_name (String ("flags-") + to_str (c) + fstyle));
+ m.add_molecule (Font_interface::get_default_font (me)->find_by_name (String ("flags-") + to_string (c) + fstyle));
return m;
}
assert (a == X_AXIS);
Grob *se = unsmob_grob (e);
Interval r (0, 0);
- if (unsmob_grob (se->get_grob_property ("beam")) || abs (flag_i (se)) <= 2)
+ if (unsmob_grob (se->get_grob_property ("beam")) || abs (duration_log (se)) <= 2)
; // TODO!
else
{
Direction d = get_direction (me);
- Real y1 = Staff_symbol_referencer::position_f (first_head (me));
+
+ Real y1;
+
+ /*
+ This is required to avoid stems passing in tablature chords...
+ */
+
+
+ /*
+ TODO: make the stem start a direction ?
+ */
+
+
+
+ if (to_boolean (me->get_grob_property ("avoid-note-head")))
+ {
+ Grob * lh = last_head (me);
+ if (!lh)
+ return SCM_EOL;
+ y1 = Staff_symbol_referencer::get_position (lh);
+ }
+ else
+ {
+ Grob * lh = first_head (me);
+ if (!lh)
+ return SCM_EOL;
+ y1 = Staff_symbol_referencer::get_position (lh);
+ }
+
Real y2 = stem_end_position (me);
Interval stem_y (y1 <? y2,y2 >? y1);
{
Real stem_width = gh_scm2double (me->get_grob_property ("thickness"))
// URG
- * me->paper_l ()->get_var ("stafflinethickness");
+ * me->get_paper ()->get_var ("linethickness");
Molecule ss =Lookup::filledbox (Box (Interval (-stem_width/2, stem_width/2),
Interval (stem_y[DOWN]*dy, stem_y[UP]*dy)));
mol.add_molecule (ss);
}
- if (!beam_l (me) && abs (flag_i (me)) > 2)
+ if (!get_beam (me) && abs (duration_log (me)) > 2)
{
Molecule fl = flag (me);
fl.translate_axis (stem_y[d]*dy, Y_AXIS);
Grob *me = unsmob_grob (element_smob);
Real r=0;
+
+ if (head_count (me) == 0)
+ {
+ return gh_double2scm (0.0);
+ }
+
if (Grob * f = first_head (me))
{
Interval head_wid = Note_head::head_extent(f, X_AXIS);
- Real attach =
- Note_head::stem_attachment_coordinate(f, X_AXIS);
+
+ Real attach =0.0;
+
+ if (invisible_b (me))
+ {
+ attach = 0.0;
+ }
+ else
+ attach = Note_head::stem_attachment_coordinate(f, X_AXIS);
Direction d = get_direction (me);
{
Real rule_thick
= gh_scm2double (me->get_grob_property ("thickness"))
- * me->paper_l ()->get_var ("stafflinethickness");
+ * me->get_paper ()->get_var ("linethickness");
r += - d * rule_thick * 0.5;
Grob*
-Stem::beam_l (Grob*me)
+Stem::get_beam (Grob*me)
{
SCM b= me->get_grob_property ("beam");
return unsmob_grob (b);
}
-
// ugh still very long.
Stem_info
Stem::calc_stem_info (Grob*me)
{
+ SCM up_to_staff = me->get_grob_property ("up-to-staff");
+ if (gh_scm2bool(up_to_staff)) {
+
+ // Up-to-staff : the stem end out of the staff.
+
+ /*
+ FIXME: duplicate code.
+ */
+ int line_count = Staff_symbol_referencer::line_count (me);
+
+ Stem_info si ;
+
+ Direction dir = get_direction (me);
+
+ si.ideal_y_ = dir* (line_count + 1.5);
+ si.dir_ = dir;
+ si.shortest_y_ = si.ideal_y_;
+
+ return si;
+ }
+
SCM scm_info = me->get_grob_property ("stem-info");
if (gh_pair_p (scm_info ))
{
Stem_info si ;
- si.ideal_y = gh_scm2double (gh_car (scm_info));
- si.max_y = gh_scm2double (gh_cadr (scm_info));
- si.min_y = gh_scm2double (gh_caddr (scm_info));
+ si.dir_ = Directional_element_interface::get(me);
+ si.ideal_y_ = gh_scm2double (gh_car (scm_info));
+ si.shortest_y_ = gh_scm2double (gh_cadr (scm_info));
return si;
}
-
- Grob * beam = beam_l (me);
-
- Direction beam_dir = Directional_element_interface::get (beam);
- if (!beam_dir)
- {
- programming_error ("Beam dir not set.");
- beam_dir = UP;
- }
-
+ Direction mydir = Directional_element_interface::get (me);
Real staff_space = Staff_symbol_referencer::staff_space (me);
Real half_space = staff_space / 2;
-
- int multiplicity = Beam::get_multiplicity (beam);
- Real interbeam_f = Beam::get_interbeam (beam);
+ Grob * beam = get_beam (me);
+ int beam_count = beam_multiplicity(me).length()+1;
+ Real beam_translation= Beam::get_beam_translation (beam);
Real thick = gh_scm2double (beam->get_grob_property ("thickness"));
- Stem_info info;
- info.ideal_y = chord_start_f (me);
-
- // for simplicity, we calculate as if dir == UP
- info.ideal_y *= beam_dir;
- SCM grace_prop = me->get_grob_property ("grace");
-
- bool grace_b = to_boolean (grace_prop);
+ Real note_start = chord_start_y (me);
- Array<Real> a;
- SCM s;
+ /* from here on, calculate as if dir == UP */
+ note_start *= mydir;
+
+ SCM grace_prop = me->get_grob_property ("grace");
- 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)));
+ bool grace_b = to_boolean (grace_prop);
+ SCM bml = robust_list_ref ( beam_count ,
+ me->get_grob_property ("beamed-minimum-lengths"));
+ Real minimum_length = gh_scm2double(bml)*staff_space;
+ SCM bl = robust_list_ref ( beam_count ,
+ me->get_grob_property ("beamed-lengths"));
+ Real stem_length = gh_scm2double(bl) * staff_space;
- 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)));
+ /*
+ stem goes to center of beam, hence 0.5
+ */
+ Real beam_lengthen = beam_translation* (beam_count - 1)
+ + ((beam_count > 0) ? thick : 0) - 0.5 * thick;
- Real stem_length = a[multiplicity <? (a.size () - 1)] * staff_space;
+ Real shortest_y = note_start + minimum_length + beam_lengthen;
+ Real ideal_y = stem_length + note_start + beam_lengthen;
- if (!beam_dir || (beam_dir == Directional_element_interface::get (me)))
- /* normal beamed stem */
- {
- if (multiplicity)
- {
- info.ideal_y += thick + (multiplicity - 1) * interbeam_f;
- }
- info.min_y = info.ideal_y;
- info.max_y = 1000; // INT_MAX;
+ /*
+ lowest beam of (UP) beam must never be lower than second staffline
- info.ideal_y += stem_length;
- info.min_y += minimum_length;
+ Hmm, reference (Wanske?)
- /*
- lowest beam of (UP) beam must never be lower than second staffline
+ 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.
- 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.min_y =
- info.min_y >? 0
- >? (- 2 * half_space - thick
- + (multiplicity > 0) * thick
- + interbeam_f * (multiplicity - 1));
- }
- }
- else
- /* knee */
+ Add: not for knees. Not sure if that's is a good thing.
+ */
+ bool no_extend_b = to_boolean (me->get_grob_property ("no-stem-extend"));
+ bool knee_b = to_boolean (beam->get_grob_property ("knee"));
+ if (!grace_b && !no_extend_b && !knee_b)
{
- info.ideal_y -= thick;
- info.max_y = info.ideal_y;
- info.min_y = - 1000 ; // INT_MAX;
-
- info.ideal_y -= stem_length;
- info.max_y -= minimum_length;
+ /* highest beam of (UP) beam must never be lower than middle
+ staffline
+ lowest beam of (UP) beam must never be lower than second staffline
+ */
+ ideal_y =
+ ideal_y >? 0
+ >? (- 2 * half_space - thick + beam_lengthen);
}
+
- info.ideal_y = (info.max_y <? info.ideal_y) >? info.min_y;
-
- s = beam->get_grob_property ("shorten");
+ // ideal_y = ideal_y >? shortest_y;
+ SCM s = beam->get_grob_property ("shorten");
if (gh_number_p (s))
- info.ideal_y -= gh_scm2double (s);
+ ideal_y -= 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.ideal_y += interstaff_f;
- info.min_y += interstaff_f;
- info.max_y += interstaff_f ;
-
+ ideal_y *= mydir;
+ shortest_y *= mydir;
+
me->set_grob_property ("stem-info",
- scm_list_n (gh_double2scm (info.ideal_y),
- gh_double2scm (info.max_y),
- gh_double2scm (info.min_y),
+ scm_list_n (gh_double2scm (ideal_y),
+ gh_double2scm (shortest_y),
SCM_UNDEFINED));
+
+ Stem_info si;
+ si.dir_ = mydir;
+ si.shortest_y_ = shortest_y;
+ si.ideal_y_ = ideal_y;
- return info;
+ return si;
}
-bool
-Stem::has_interface (Grob*m)
+
+// move to stem?
+Slice
+Stem::beam_multiplicity (Grob *stem)
{
- return m && m->has_interface (ly_symbol2scm ("stem-interface"));
-}
+ SCM beaming= stem->get_grob_property ("beaming");
+ Slice l = int_list_to_slice (gh_car (beaming));
+ Slice r = int_list_to_slice (gh_cdr (beaming));
+ l.unite (r);
-void
-Stem::set_interface (Grob*me)
-{
- me->set_interface (ly_symbol2scm ("stem-interface"));
+ return l;
}
+
+
+ADD_INTERFACE (Stem,"stem-interface",
+ "A stem",
+ "up-to-staff avoid-note-head adjust-if-on-staffline thickness stem-info beamed-lengths beamed-minimum-lengths lengths beam stem-shorten duration-log beaming neutral-direction stem-end-position support-head note-heads direction length style no-stem-extend flag-style dir-forced");
+
+