source file of the GNU LilyPond music typesetter
- (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ (c) 1997--2008 Han-Wen Nienhuys <hanwen@xs4all.nl>
Jan Nieuwenhuizen <janneke@gnu.org>
*/
Grob *stem = first_normal_stem (me);
/*
- ugh: stems[0] case happens for chord tremolo.
+ This happens for chord tremolos.
*/
- dir = to_dir ((stem ? stem : stems[0])->get_property ("default-direction"));
+ if (!stem)
+ stem = stems[0];
+
+ if (is_direction (stem->get_property_data ("direction")))
+ dir = to_dir (stem->get_property_data ("direction"));
+ else
+ dir = to_dir (stem->get_property ("default-direction"));
}
}
Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
Slice ranks;
-
for (vsize i = 0; i < stems.size (); i++)
{
Grob *stem = stems[i];
Beam_stem_segment seg;
seg.stem_ = stem;
seg.stem_x_ = stem_x;
- seg.rank_ = 2 * i + (d+1)/2;
+ seg.rank_ = 2 * i + (d+1)/2;
seg.width_ = stem_width;
seg.stem_index_ = i;
seg.dir_ = d;
Direction event_dir = LEFT;
do
{
- bool on_bound = (event_dir == LEFT) ? j == 0 :
+ bool on_line_bound = (segs[j].dir_ == LEFT) ? segs[j].stem_index_ == 0
+ : segs[j].stem_index_ == stems.size() - 1;
+ bool on_beam_bound = (event_dir == LEFT) ? j == 0 :
j == segs.size () - 1;
-
bool inside_stem = (event_dir == LEFT)
- ? segs[j].stem_index_ > 0
- : segs[j].stem_index_ + 1 < stems.size () ;
+ ? segs[j].stem_index_ > 0
+ : segs[j].stem_index_ + 1 < stems.size () ;
- bool event = on_bound
+ bool event = on_beam_bound
|| abs (segs[j].rank_ - segs[j+event_dir].rank_) > 1
|| (abs (vertical_count) >= segs[j].max_connect_
|| abs (vertical_count) >= segs[j + event_dir].max_connect_);
current.horizontal_[event_dir] = segs[j].stem_x_;
if (segs[j].dir_ == event_dir)
{
- if (on_bound
+ if (on_line_bound
&& me->get_bound (event_dir)->break_status_dir ())
{
current.horizontal_[event_dir]
- = (me->get_bound (event_dir)->extent (commonx, X_AXIS)[RIGHT]
+ = (robust_relative_extent (me->get_bound (event_dir),
+ commonx, X_AXIS)[RIGHT]
+ event_dir * break_overshoot[event_dir]);
}
else
if (inside_stem)
{
Grob *neighbor_stem = stems[segs[j].stem_index_ + event_dir];
- Real neighbor_stem_x = neighbor_stem->relative_coordinate (commonx, X_AXIS);
+ Real neighbor_stem_x
+ = neighbor_stem->relative_coordinate (commonx, X_AXIS);
notehead_width = min (notehead_width,
- fabs (neighbor_stem_x - segs[j].stem_x_)/2);
+ fabs (neighbor_stem_x - segs[j].stem_x_)/2.5);
}
current.horizontal_[event_dir] += event_dir * notehead_width;
}
{
current.horizontal_[event_dir] += event_dir * segs[j].width_/2;
if (segs[j].gapped_)
- current.horizontal_[event_dir] -= event_dir * gap_length;
+ {
+ current.horizontal_[event_dir] -= event_dir * gap_length;
+
+ if (Stem::is_invisible (segs[j].stem_))
+ {
+ /*
+ Need to do this in case of whole notes. We don't want the
+ heads to collide with the beams.
+ */
+ extract_grob_set (segs[j].stem_, "note-heads", heads);
+
+ for (vsize k = 0; k < heads.size (); k ++)
+ current.horizontal_[event_dir]
+ = event_dir * min (event_dir * current.horizontal_[event_dir],
+ - gap_length/2
+ + event_dir
+ * heads[k]->extent (commonx,
+ X_AXIS)[-event_dir]);
+ }
+ }
}
if (event_dir == RIGHT)
}
#if (DEBUG_BEAM_SCORING)
- SCM quant_score = me->get_property ("quant-score");
- SCM debug = me->layout ()->lookup_variable (ly_symbol2scm ("debug-beam-scoring"));
- if (to_boolean (debug) && scm_is_string (quant_score))
+ SCM annotation = me->get_property ("annotation");
+ if (!scm_is_string (annotation))
+ {
+ SCM debug = me->layout ()->lookup_variable (ly_symbol2scm ("debug-beam-scoring"));
+ if (to_boolean (debug))
+ annotation = me->get_property ("quant-score");
+ }
+
+ if (scm_is_string (annotation))
{
extract_grob_set (me, "stems", stems);
Direction stem_dir = stems.size () ? to_dir (stems[0]->get_property ("direction")) : UP;
Stencil score = *unsmob_stencil (Text_interface::interpret_markup
- (me->layout ()->self_scm (), properties, quant_score));
+ (me->layout ()->self_scm (), properties, annotation));
if (!score.is_empty ())
- the_beam.add_at_edge (Y_AXIS, stem_dir, score, 1.0);
+ {
+ score.translate_axis (me->relative_coordinate(commonx, X_AXIS), X_AXIS);
+ the_beam.add_at_edge (Y_AXIS, stem_dir, score, 1.0);
+ }
}
#endif
}
+Interval
+Beam::no_visible_stem_positions (Grob *me, Interval default_value)
+{
+ extract_grob_set (me, "stems", stems);
+ if (stems.empty ())
+ return default_value;
+
+ Interval head_positions;
+ Slice multiplicity;
+ for (vsize i = 0; i < stems.size(); i++)
+ {
+ head_positions.unite (Stem::head_positions (stems[i]));
+ multiplicity.unite (Stem::beam_multiplicity (stems[i]));
+ }
+
+ Direction dir = get_grob_direction (me);
+ Real y = head_positions[dir]
+ * 0.5 * Staff_symbol_referencer::staff_space (me)
+ + dir * get_beam_translation (me) * (multiplicity.length () + 1);
+
+ y /= Staff_symbol_referencer::staff_space (me);
+ return Interval (y,y);
+}
+
/*
Compute a first approximation to the beam slope.
int count = normal_stem_count (me);
Interval pos (0,0);
if (count < 1)
- return ly_interval2scm (pos);
+ return ly_interval2scm (no_visible_stem_positions (me, pos));
vector<Real> x_posns;
extract_grob_set (me, "normal-stems", stems);
in POS for stem S. This Y position is relative to S. */
Real
Beam::calc_stem_y (Grob *me, Grob *stem, Grob **common,
- Real xl, Real xr,
+ Real xl, Real xr, Direction feather_dir,
Drul_array<Real> pos, bool french)
{
Real beam_translation = get_beam_translation (me);
+ Direction stem_dir = get_grob_direction (stem);
- Real r = stem->relative_coordinate (common[X_AXIS], X_AXIS) - xl;
- Real dy = pos[RIGHT] - pos[LEFT];
Real dx = xr - xl;
- Real stem_y_beam0 = (dy && dx
- ? r / dx
- * dy
- : 0) + pos[LEFT];
+ Real relx = dx ? (stem->relative_coordinate (common[X_AXIS], X_AXIS) - xl)/dx : 0;
+ Real xdir = 2*relx-1;
+
+ Real stem_y = linear_combination(pos, xdir);
- Direction my_dir = get_grob_direction (stem);
SCM beaming = stem->get_property ("beaming");
- Real stem_y = stem_y_beam0;
- if (french)
- {
- Slice bm = where_are_the_whole_beams (beaming);
- if (!bm.is_empty ())
- stem_y += beam_translation * bm[-my_dir];
- }
- else
- {
- Slice bm = Stem::beam_multiplicity (stem);
- if (!bm.is_empty ())
- stem_y += bm[my_dir] * beam_translation;
- }
+ Slice beam_slice (french
+ ? where_are_the_whole_beams (beaming)
+ : Stem::beam_multiplicity (stem));
+ if (beam_slice.is_empty ())
+ beam_slice = Slice (0,0);
+ Interval beam_multiplicity(beam_slice[LEFT],
+ beam_slice[RIGHT]);
+ /*
+ feather dir = 1 , relx 0->1 : factor 0 -> 1
+ feather dir = 0 , relx 0->1 : factor 1 -> 1
+ feather dir = -1, relx 0->1 : factor 1 -> 0
+ */
+ Real feather_factor = 1;
+ if (feather_dir > 0)
+ feather_factor = relx;
+ else if (feather_dir < 0)
+ feather_factor = 1 - relx;
+
+ stem_y += feather_factor * beam_translation
+ * beam_multiplicity[Direction(((french) ? DOWN : UP)*stem_dir)];
Real id = me->relative_coordinate (common[Y_AXIS], Y_AXIS)
- stem->relative_coordinate (common[Y_AXIS], Y_AXIS);
Real xl = fvs ? fvs->relative_coordinate (common[X_AXIS], X_AXIS) : 0.0;
Real xr = lvs ? lvs->relative_coordinate (common[X_AXIS], X_AXIS) : 0.0;
+ Direction feather_dir = to_dir (me->get_property ("grow-direction"));
for (vsize i = 0; i < stems.size (); i++)
{
bool french = to_boolean (s->get_property ("french-beaming"));
Real stem_y = calc_stem_y (me, s, common,
- xl, xr,
+ xl, xr, feather_dir,
pos, french && s != lvs && s!= fvs);
/*
for normal beams, but for tremolo beams it looks silly otherwise.
*/
if (gap
- && !Stem::is_invisible (s))
+ && !Stem::is_invisible (s))
stem_y += thick * 0.5 * get_grob_direction (s);
/*
return false;
}
-MAKE_SCHEME_CALLBACK (Beam, cross_staff, 1)
+MAKE_SCHEME_CALLBACK (Beam, calc_cross_staff, 1)
SCM
-Beam::cross_staff (SCM smob)
+Beam::calc_cross_staff (SCM smob)
{
return scm_from_bool (is_cross_staff (unsmob_grob (smob)));
}
}
ADD_INTERFACE (Beam,
-
- "A beam. \n\n"
- "The @code{thickness} property is the weight of beams, "
- "measured in staffspace. The @code{direction} "
- "property is not user-serviceable. Use "
- "the @code{direction} property of @code{Stem} instead. "
-
- ,
+ "A beam.\n"
+ "\n"
+ "The @code{thickness} property is the weight of beams,"
+ " measured in staffspace. The @code{direction} property is"
+ " not user-serviceable. Use the @code{direction} property"
+ " of @code{Stem} instead.",
/* properties */
+ "annotation "
"auto-knee-gap "
"beamed-stem-shorten "
"beaming "
"concaveness "
"damping "
"details "
- "direction "
+ "direction "
"gap "
"gap-count "
"grow-direction "