/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Copyright (C) 1997--2014 Han-Wen Nienhuys <hanwen@xs4all.nl>
Jan Nieuwenhuizen <janneke@gnu.org>
LilyPond is free software: you can redistribute it and/or modify
dir = to_dir (stem->get_property_data ("direction"));
else
dir = to_dir (stem->get_property ("default-direction"));
+
+ extract_grob_set (stem, "note-heads", heads);
+ /* default position of Kievan heads with beams is down
+ placing this here avoids warnings downstream */
+ if (heads.size())
+ {
+ if (heads[0]->get_property ("style") == ly_symbol2scm ("kievan"))
+ {
+ if (dir == CENTER)
+ dir = DOWN;
+ }
+ }
}
}
last_dir ? last_dir : this_dir,
this_dir);
- Direction d = LEFT;
Slice new_slice;
- do
+ for (LEFT_and_RIGHT (d))
{
new_slice.set_empty ();
SCM s = index_get_cell (this_beaming, d);
scm_set_car_x (s, scm_from_int (new_beam_pos));
}
}
- while (flip (&d) != LEFT);
if (!new_slice.is_empty ())
last_int = new_slice;
extract_grob_set (me, "stems", stems);
Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS);
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
commonx = me->get_bound (d)->common_refpoint (commonx, X_AXIS);
- while (flip (&d) != LEFT);
int gap_count = robust_scm2int (me->get_property ("gap-count"), 0);
Real gap_length = robust_scm2double (me->get_property ("gap"), 0.0);
Real stem_x = stem->relative_coordinate (commonx, X_AXIS);
SCM beaming = stem->get_property ("beaming");
- do
+ for (LEFT_and_RIGHT (d))
{
// Find the maximum and minimum beam ranks.
// Given that RANKS is never reset to empty, the interval will always be
stem_segments[beam_rank].push_back (seg);
}
}
- while (flip (&d) != LEFT);
}
Drul_array<Real> break_overshoot
// we are currently looking at (ie. if segs[j].dir_ == event_dir then we
// are looking at that edge of the beam segment that is furthest from its
// stem).
- Direction event_dir = LEFT;
Beam_stem_segment const &seg = segs[j];
- do
+ for (LEFT_and_RIGHT (event_dir))
{
Beam_stem_segment const &neighbor_seg = segs[j + event_dir];
// TODO: make names clearer? --jneem
current = Beam_segment ();
}
}
- while (flip (&event_dir) != LEFT);
}
}
SCM segments_scm = SCM_EOL;
- SCM *tail = &segments_scm;
- for (vsize i = 0; i < segments.size (); i++)
+ for (vsize i = segments.size (); i--;)
{
- *tail = scm_cons (scm_list_2 (scm_cons (ly_symbol2scm ("vertical-count"),
- scm_from_int (segments[i].vertical_count_)),
- scm_cons (ly_symbol2scm ("horizontal"),
- ly_interval2scm (segments[i].horizontal_))),
- SCM_EOL);
- tail = SCM_CDRLOC (*tail);
+ segments_scm = scm_cons (scm_list_2 (scm_cons (ly_symbol2scm ("vertical-count"),
+ scm_from_int (segments[i].vertical_count_)),
+ scm_cons (ly_symbol2scm ("horizontal"),
+ ly_interval2scm (segments[i].horizontal_))),
+ segments_scm);
}
return segments_scm;
{
extract_grob_set (me, "stems", stems);
Grob *common_x = common_refpoint_of_array (stems, me, X_AXIS);
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
x_positions[d] = me->relative_coordinate (common_x, X_AXIS);
- while (flip (&d) != LEFT);
}
return ly_interval2scm (x_positions);
}
*/
extract_grob_set (me, "stems", stems);
Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS);
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
commonx = me->get_bound (d)->common_refpoint (commonx, X_AXIS);
- while (flip (&d) != LEFT);
vector<Beam_segment> segments = get_beam_segments (me);
Interval placements = robust_scm2interval (me->get_property ("normalized-endpoints"), Interval (0.0, 0.0));
Stencil the_beam;
- int extreme = (segments[0].vertical_count_ == 0
- ? segments[0].vertical_count_
- : segments.back ().vertical_count_);
+ vsize extreme = (segments[0].vertical_count_ == 0
+ ? segments[0].vertical_count_
+ : segments.back ().vertical_count_);
for (vsize i = 0; i < segments.size (); i++)
{
// we need two translations: the normal one and
// the one of the lowest segment
- int idx[] = {i, extreme};
+ size_t idx[] = {i, extreme};
Real translations[2];
for (int j = 0; j < 2; j++)
for (iterof (s, stems); s != stems.end (); s++)
{
Interval positions = Stem::head_positions (*s);
- Direction d = DOWN;
- do
+ for (DOWN_and_UP (d))
{
if (sign (positions[d]) == d)
extremes[d] = d * max (d * positions[d], d * extremes[d]);
}
- while (flip (&d) != DOWN);
}
Drul_array<int> total (0, 0);
if (!scm_is_number (scm))
return;
- Interval_set gaps;
-
- gaps.set_full ();
+ vector<Interval> forbidden_intervals;
extract_grob_set (me, "normal-stems", stems);
}
head_extents_array.push_back (head_extents);
- gaps.remove_interval (head_extents);
+ forbidden_intervals.push_back (head_extents);
}
Interval max_gap;
Real max_gap_len = 0.0;
- for (vsize i = gaps.allowed_regions_.size () - 1; i != VPOS; i--)
+ vector<Interval> allowed_regions
+ = Interval_set::interval_union (forbidden_intervals).complement ().intervals ();
+ for (vsize i = allowed_regions.size () - 1; i != VPOS; i--)
{
- Interval gap = gaps.allowed_regions_[i];
+ Interval gap = allowed_regions[i];
/*
the outer gaps are not knees.
{
extract_grob_set (me, "stems", stems);
- Direction d = LEFT;
for (vsize i = 0; i < stems.size (); i++)
{
/*
Don't overwrite user settings.
*/
- do
+ for (LEFT_and_RIGHT (d))
{
Grob *stem = stems[i];
SCM beaming_prop = stem->get_property ("beaming");
Stem::set_beaming (stem, count, d);
}
}
- while (flip (&d) != LEFT);
}
}
Drul_array<Real> pos (robust_scm2drul (beam->get_property ("positions"),
Drul_array<Real> (0, 0)));
- Direction dir = LEFT;
- do
+ for (LEFT_and_RIGHT (dir))
pos[dir] += beam->relative_coordinate (common_y, Y_AXIS);
- while (flip (&dir) != LEFT);
Real staff_space = Staff_symbol_referencer::staff_space (rest);
+ (beam_count - 1) * beam_translation;
Real beam_y = stem_y - d * height_of_my_beams;
-
Interval rest_extent = rest->extent (rest, Y_AXIS);
rest_extent.translate (offset + rest->get_parent (Y_AXIS)->relative_coordinate (common_y, Y_AXIS));
Real shift = d * min (d * (beam_y - d * minimum_distance - rest_dim), 0.0);
shift /= staff_space;
- Real rad = Staff_symbol_referencer::line_count (rest) * staff_space / 2;
/* Always move discretely by half spaces */
shift = ceil (fabs (shift * 2.0)) / 2.0 * sign (shift);
+ Interval staff_span = Staff_symbol_referencer::staff_span (rest);
+ staff_span *= staff_space / 2;
+
/* Inside staff, move by whole spaces*/
- if ((rest_extent[d] + staff_space * shift) * d
- < rad
- || (rest_extent[-d] + staff_space * shift) * -d
- < rad)
+ if (staff_span.contains (rest_extent[d] + staff_space * shift)
+ || staff_span.contains (rest_extent[-d] + staff_space * shift))
shift = ceil (fabs (shift)) * sign (shift);
return scm_from_double (offset + staff_space * shift);
}
+/*
+ Estimate the position of a rest under a beam,
+ as the average position of its neighboring heads.
+*/
MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Beam, pure_rest_collision_callback, 4, 1, "");
SCM
Beam::pure_rest_collision_callback (SCM smob,
- SCM, /* prev_offset */
SCM, /* start */
- SCM /* end */)
+ SCM, /* end */
+ SCM prev_offset)
{
- Real amount = 0.0;
+ Real previous = robust_scm2double (prev_offset, 0.0);
Grob *me = unsmob_grob (smob);
Grob *stem = unsmob_grob (me->get_object ("stem"));
if (!stem)
- return scm_from_double (amount);
+ return scm_from_double (previous);
Grob *beam = unsmob_grob (stem->get_object ("beam"));
if (!beam
|| !Beam::normal_stem_count (beam)
|| !is_direction (beam->get_property_data ("direction")))
- return scm_from_double (amount);
+ return scm_from_double (previous);
Real ss = Staff_symbol_referencer::staff_space (me);
/*
This gives the extrema of rest positions.
- In general, beams are never typeset more than one staff space away
- from the staff in either direction.
+ Even with noteheads on ledgers, beams typically remain within the staff,
+ and push rests at most one staff-space (2 positions) from the staff.
*/
Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
Interval rest_max_pos = staff ? Staff_symbol::line_span (staff) : Interval (0.0, 0.0);
- rest_max_pos.widen (1);
- rest_max_pos *= ss / 2;
+ rest_max_pos.widen (2);
extract_grob_set (beam, "stems", stems);
vector<Grob *> my_stems;
Grob *right;
if (idx == (vsize) - 1 || my_stems.size () == 1)
- return scm_from_double (amount);
+ return scm_from_double (previous);
else if (idx == 0)
left = right = my_stems[1];
else if (idx == my_stems.size () - 1)
left = my_stems[idx - 1];
right = my_stems[idx + 1];
}
- Direction beamdir = get_grob_direction (beam);
- /*
- Take the position between the two bounding head_positions,
- then bound it by the minimum and maximum positions outside the staff.
- 4.0 = 2.0 to get out of staff space * 2.0 for the average
- */
- amount = min (max ((Stem::head_positions (left)[beamdir] + Stem::head_positions (right)[beamdir]) / 4.0, rest_max_pos[DOWN]), rest_max_pos[UP]);
- return scm_from_double (amount);
+ /* In stems with several heads, use the one closest to the beam. */
+ Direction beamdir = get_grob_direction (beam);
+ Real shift = min (max ( (Stem::head_positions (left)[beamdir]
+ + Stem::head_positions (right)[beamdir]) / 2.0,
+ rest_max_pos[DOWN]),
+ rest_max_pos[UP]
+ ) * ss / 2.0
+ - previous;
+
+ // So that ceil below kicks in for rests that would otherwise brush
+ // up against a beam quanted to a ledger line, add a bit of space
+ // between the beam and the rest.
+ shift += (0.01 * beamdir);
+
+ /* Always move by a whole number of staff spaces */
+ shift = ceil (fabs (shift / ss)) * ss * sign (shift);
+
+ return scm_from_double (previous + shift);
}
bool