2006-05-22 Han-Wen Nienhuys <hanwen@lilypond.org>
+ * input/regression/beam-single-stem.ly: new file.
+
+ * lily/stem.cc (set_beaming): use #f as signaling value for
+ beamcount 0.
+
+ * lily/beam-engraver.cc (typeset_beam): set right bound if unset.
+
+ * lily/beam.cc (set_beaming): read clip-edges property.
+ (calc_direction): don't suicide for single stem.
+
+ * lily/beaming-info.cc (best_splitpoint_index): take bool*
+ argument, remove 1<<15 hack. Remove clip_edges()
+
* lily/hairpin.cc (print): only do padding for nonmusical bounds
2006-05-21 Graham Percival <gpermus@gmail.com>
--- /dev/null
+\header {
+
+ texidoc = "Single stem beams are also allowed. For such beams,
+ clip-edges is switched off automatically."
+
+}
+\version "2.9.6"
+
+\relative c' {
+ d16[]
+ \set stemRightBeamCount = #0
+ d32[]
+}
+
+\layout {
+ ragged-right = ##t
+}
}
stems_ = new vector<Item*>;
- grouping_ = new Beaming_info_list;
+ grouping_ = make_beaming_info_list (context ());
beam_settings_ = updated_grob_properties (context (), ly_symbol2scm ("Beam"));
beam_start_moment_ = now_mom ();
beam_start_location_
= robust_scm2moment (get_property ("measurePosition"), Moment (0));
- subdivide_beams_ = ly_scm2bool (get_property ("subdivideBeams"));
- beat_length_ = robust_scm2moment (get_property ("beatLength"), Moment (1, 4));
}
void
{
if (finished_beam_)
{
- finished_grouping_->beamify (beat_length_, subdivide_beams_);
+ if (!finished_beam_->get_bound (RIGHT))
+ finished_beam_->set_bound (RIGHT, finished_beam_->get_bound (LEFT));
+
+ finished_grouping_->beamify ();
Beam::set_beaming (finished_beam_, finished_grouping_);
finished_beam_ = 0;
beam_start_location_ = mp;
beam_start_mom_ = now_mom ();
- beam_info_ = new Beaming_info_list;
-
+ beam_info_ = make_beaming_info_list (context ());
/* urg, must copy to Auto_beam_engraver too */
}
}
{
if (finished_beam_)
{
- finished_beam_info_->beamify (beat_length_, subdivide_beams_);
+ if (!finished_beam_->get_bound (RIGHT))
+ finished_beam_->set_bound (RIGHT, finished_beam_->get_bound (LEFT));
+
+ finished_beam_info_->beamify ();
Beam::set_beaming (finished_beam_, finished_beam_info_);
delete finished_beam_info_;
if (beam_)
{
set_melisma (true);
-
- subdivide_beams_ = to_boolean (get_property ("subdivideBeams"));
- beat_length_ = robust_scm2moment (get_property ("beatLength"), Moment (1, 4));
}
}
ADD_ACKNOWLEDGER (Beam_engraver, rest);
ADD_TRANSLATOR (Beam_engraver,
- /* doc */ "Handles Beam events by engraving Beams. If omitted, then notes will be "
+ /* doc */
+
+ "Handles Beam events by engraving Beams. If omitted, then notes will be "
"printed with flags instead of beams.",
+
/* create */ "Beam",
/* accept */ "beam-event",
- /* read */ "beamMelismaBusy beatLength subdivideBeams",
- /* write */ "forbidBreak");
+
+ /* read */
+ "beamMelismaBusy "
+ "beatLength "
+ "subdivideBeams "
+ ,
+ /* write */
+ "forbidBreak");
class Grace_beam_engraver : public Beam_engraver
{
ADD_ACKNOWLEDGER (Grace_beam_engraver, stem);
ADD_ACKNOWLEDGER (Grace_beam_engraver, rest);
+
ADD_TRANSLATOR (Grace_beam_engraver,
- /* doc */ "Handles Beam events by engraving Beams. If omitted, then notes will "
+
+ /* doc */
+
+ "Handles Beam events by engraving Beams. If omitted, then notes will "
"be printed with flags instead of beams. Only engraves beams when we "
" are at grace points in time. ",
+
/* create */ "Beam",
/* accept */ "beam-event",
- /* read */ "beamMelismaBusy beatLength allowBeamBreak subdivideBeams",
+ /* read */
+ "beamMelismaBusy "
+ "beatLength "
+ "allowBeamBreak "
+ "subdivideBeams "
+ ,
/* write */ "");
For a beam that only has one stem, we try to do some disappearance magic:
we revert the flag, and move on to The Eternal Engraving Fields. */
- Direction d = CENTER;
+ Direction dir = CENTER;
int count = visible_stem_count (me);
if (count < 2)
{
extract_grob_set (me, "stems", stems);
- if (stems.size () == 1)
+ if (stems.size () == 0)
{
- me->warning (_ ("removing beam with less than two stems"));
-
- stems[0]->set_object ("beam", SCM_EOL);
+ me->warning (_ ("removing beam with no stems"));
me->suicide ();
- return SCM_UNSPECIFIED;
- }
- else if (stems.size () == 0)
- {
- me->suicide ();
return SCM_UNSPECIFIED;
}
else
/*
ugh: stems[0] case happens for chord tremolo.
*/
- d = to_dir ((stem ? stem : stems[0])->get_property ("default-direction"));
+ dir = to_dir ((stem ? stem : stems[0])->get_property ("default-direction"));
}
}
if (count >= 1)
{
- if (!d)
- d = get_default_dir (me);
+ if (!dir)
+ dir = get_default_dir (me);
consider_auto_knees (me);
}
- if (d)
+ if (dir)
{
- set_stem_directions (me, d);
+ set_stem_directions (me, dir);
}
- return scm_from_int (d);
+ return scm_from_int (dir);
}
&& Stem::is_invisible (stem))
count = min (count, beaming->infos_.at (i).beam_count_drul_[-d]);
+ if ( ((i == 0 && d == LEFT)
+ || (i == stems.size ()-1 && d == RIGHT))
+ && stems.size () > 1
+ && to_boolean (me->get_property ("clip-edges")))
+ count = 0;
+
Stem::set_beaming (stem, count, d);
}
}
"beamed-stem-shorten "
"beaming "
"break-overshoot "
+ "clip-edges "
"concaveness "
"damping "
"details "
*/
#include "beaming.hh"
+#include "context.hh"
Beaming_info::Beaming_info ()
{
beam_count_drul_[RIGHT] = i;
}
-const int at_beat = 1 << 15; // WTF is this.
-
int
-Beaming_info_list::best_splitpoint_index (Moment &beat_length,
- bool subdivide) const
+Beaming_info_list::best_splitpoint_index (Moment beat_length,
+ bool subdivide_beams,
+ bool *at_beat_subdivide) const
{
int min_denominator = INT_MAX;
int min_index = -1;
beat_pos = infos_[i].start_moment_ / beat_length;
int den = beat_pos.den ();
if (infos_[i].beam_count_drul_[LEFT] == infos_[i - 1].beam_count_drul_[RIGHT]
- && !subdivide)
+ && !subdivide_beams)
den *= 2;
if (den < min_denominator)
}
}
- return min_index | (min_denominator == 1 && subdivide ? at_beat : 0);
+ *at_beat_subdivide = (min_denominator == 1 && subdivide_beams);
+
+ return min_index;
}
int
}
void
-Beaming_info_list::beamify (Moment &beat_length, bool subdivide)
+Beaming_info_list::beamify ()
+{
+ bool subdivide_beams = to_boolean (context_->get_property ("subdivideBeams"));
+ Moment beat_length = robust_scm2moment (context_->get_property ("beatLength"), Moment (1, 4));
+
+ beamify (beat_length, subdivide_beams);
+}
+
+
+
+Beaming_info_list *
+make_beaming_info_list (Context *context)
+{
+ Beaming_info_list *l = new Beaming_info_list;
+ l->context_ = context;
+ return l;
+}
+
+
+void
+Beaming_info_list::beamify (Moment beat_length,
+ bool subdivide_beams)
{
if (infos_.size () <= 1)
return;
- Drul_array<Beaming_info_list> splits;
+
+ Drul_array<Beaming_info_list> splits (*this, *this);
- int m = best_splitpoint_index (beat_length, subdivide);
- bool split = subdivide && (m & at_beat);
- m = m & ~at_beat;
+ bool split = false;
+ int m = best_splitpoint_index (beat_length, subdivide_beams, &split);
splits[LEFT].infos_ = vector<Beaming_info> (infos_.begin (),
infos_.begin () + m);
do
{
- splits[d].beamify (beat_length, subdivide);
+ splits[d].beamify (beat_length, subdivide_beams);
}
while (flip (&d) != LEFT);
infos_.insert (infos_.end (),
splits[RIGHT].infos_.begin (),
splits[RIGHT].infos_.end ());
-
- clip_edges ();
}
+
+
void
Beaming_info_list::add_stem (Moment m, int b)
{
infos_.push_back (Beaming_info (m, b));
}
-void
-Beaming_info_list::clip_edges ()
+
+Beaming_info_list::Beaming_info_list ()
{
- if (infos_.size ())
- {
- infos_[0].beam_count_drul_[LEFT] = 0;
- infos_.back ().beam_count_drul_[RIGHT] = 0;
- }
+ context_ = 0;
}
+
+
else
{
x_points[d] = e[d];
- if (me->get_bound (d)->is_non_musical ())
+ Item *bound = me->get_bound (d);
+ if (bound->is_non_musical (bound))
x_points[d] -= d * padding;
}
}
#include "std-vector.hh"
#include "moment.hh"
+#include "lily-proto.hh"
struct Beaming_info
{
Drul_array<int> beam_count_drul_;
Beaming_info (Moment, int);
- int count (Direction d);
Beaming_info ();
+
+ int count (Direction d);
};
/*
struct Beaming_info_list
{
vector<Beaming_info> infos_;
+ Context *context_;
+ Beaming_info_list ();
+
int beam_extend_count (Direction) const;
- int best_splitpoint_index (Moment &beat_length, bool subdivide) const;
- void beamify (Moment &beat_length, bool subdivide);
+ int best_splitpoint_index (Moment, bool, bool *split) const;
+ void beamify ();
+ void beamify (Moment, bool);
void add_stem (Moment d, int beams);
- void clip_edges ();
};
+Beaming_info_list *make_beaming_info_list (Context *);
+
#endif /* BEAMING_HH */
Moment *measpos = unsmob_moment (get_property ("measurePosition"));
Rational mp = measpos->main_part_;
- Moment *beatlen = unsmob_moment (get_property ("beatLength"));
- Rational bl = beatlen->main_part_;
+ Moment *beatlen_mom = unsmob_moment (get_property ("beatLength"));
+ Rational beat_length = beatlen_mom->main_part_;
Rational where (0);
for (SCM s = grouping; scm_is_pair (s);
- where += Rational ((int) scm_to_int (scm_car (s))) * bl,
+ where += Rational ((int) scm_to_int (scm_car (s))) * beat_length,
s = scm_cdr (s))
{
int grouplen = scm_to_int (scm_car (s));
grouping_ = make_spanner ("MeasureGrouping", SCM_EOL);
grouping_->set_bound (LEFT, unsmob_grob (get_property ("currentMusicalColumn")));
- stop_grouping_mom_ = now.main_part_ + Rational (grouplen - 1) * bl;
+ stop_grouping_mom_ = now.main_part_ + Rational (grouplen - 1) * beat_length;
get_global_context ()->add_moment_to_process (Moment (stop_grouping_mom_));
if (grouplen == 3)
ADD_ACKNOWLEDGER (Measure_grouping_engraver, note_column);
ADD_TRANSLATOR (Measure_grouping_engraver,
- /* doc */ "Creates MeasureGrouping to indicate beat subdivision.",
- /* create */ "MeasureGrouping",
- /* accept */ "",
- /* read */ "beatGrouping beatLength measurePosition currentMusicalColumn",
- /* write */ "");
+ /* doc */
+ "Creates MeasureGrouping to indicate beat subdivision.",
+ /* create */
+ "MeasureGrouping",
+ /* accept */
+ "",
+ /* read */
+ "beatLength "
+ "currentMusicalColumn "
+ "measurePosition "
+ "beatGrouping "
+ ,
+ /* write */
+ "");
}
SCM lst = index_get_cell (pair, d);
- for (int i = 0; i < beam_count; i++)
- lst = scm_cons (scm_from_int (i), lst);
+ if (beam_count)
+ for (int i = 0; i < beam_count; i++)
+ lst = scm_cons (scm_from_int (i), lst);
+ else
+ lst = SCM_BOOL_F;
+
index_set_cell (pair, d, lst);
}
(shorten-pair ,number-pair? "The lengths to shorten a
text-spanner on both sides, for example a pedal bracket")
+ (clip-edges ,boolean? "Allow outward pointing beamlets at the edges of beams?")
(common-shortest-duration ,ly:moment?
"The most common shortest note length.
This is used in spacing. Enlarging this will set the score tighter.")
(shorten . ,ly:beam::calc-stem-shorten)
(beaming . ,ly:beam::calc-beaming)
(stencil . ,ly:beam::print)
-
+ (clip-edges . #t)
+
;; TODO: should be in SLT.
(thickness . 0.48) ; in staff-space
(neutral-direction . ,DOWN)