--- /dev/null
+\version "2.15.30"
+
+\header {
+
+ texinfo = "
+Subdivision works properly for tuplets
+ "
+}
+
+\relative c'' {
+ \set subdivideBeams = ##t
+ \set baseMoment = #(ly:make-moment 1 8)
+ \set beatStructure = #'(2 2 2 2)
+ \repeat unfold 8 {
+ \times 2/3 { c16 e d }
+ }
+}
grouping_->add_stem (now - beam_start_moment_ + beam_start_location_,
durlog - 2,
Stem::is_invisible (stem),
- stem_duration->factor ());
+ stem_duration->factor (),
+ (stem->get_property ("tuplet-start") == SCM_BOOL_T));
stems_->push_back (stem);
last_add_mom_ = now;
extend_mom_ = max (extend_mom_, now) + get_event_length (ev, now);
beam_info_->add_stem (stem_location,
max (durlog - 2, 0),
Stem::is_invisible (stem),
- stem_duration->factor ());
+ stem_duration->factor (),
+ (stem->get_property ("tuplet-start") == SCM_BOOL_T));
Beam::add_stem (beam_, stem);
}
beam_count_drul_[RIGHT] = 0;
invisible_ = false;
factor_ = Rational (1);
-
+ tuplet_start_ = false;
}
-Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv, Rational factor)
+Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv,
+ Rational factor, bool tuplet_start)
{
start_moment_ = m;
rhythmic_importance_ = 0;
beam_count_drul_[RIGHT] = i;
invisible_ = inv;
factor_ = factor;
+ tuplet_start_ = tuplet_start;
}
void
Moment tuplet_dt = infos_[i].start_moment_ - tuplet_start_moment;
tuplet_number = tuplet.den ();
// set the beat end (if not in a tuplet) and increment the next beat
- if (tuplet_number == 1 && infos_[i].start_moment_ == next_beat_pos)
+ if (infos_[i].start_moment_ == next_beat_pos)
{
- infos_[i].rhythmic_importance_ = -1;
- next_beat_pos += options.base_moment_;
+ if (tuplet_number == 1)
+ {
+ infos_[i].rhythmic_importance_ = -1;
+ next_beat_pos += options.base_moment_;
+ }
+ if (infos_[i].tuplet_start_)
+ infos_[i].rhythmic_importance_ = -1;
}
// The rhythmic importance of a stem between beats depends on its fraction
// of a beat: those stems with a lower denominator are deemed more
}
void
-Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor)
+Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor, bool tuplet_start)
{
- infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor));
+ infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor, tuplet_start));
}
Beaming_pattern::Beaming_pattern ()
return infos_.at (i).factor_;
}
+bool
+Beaming_pattern::tuplet_start (int i) const
+{
+ return infos_.at (i).tuplet_start_;
+}
+
/*
Split a beaming pattern at index i and return a new
Beaming_pattern containing the removed elements
new_pattern->add_stem (start_moment (j),
count,
invisibility (j),
- factor (j));
+ factor (j),
+ tuplet_start (j));
}
for (vsize j = i + 1; j < infos_.size ();)
infos_.pop_back ();
Rational factor_;
- Beam_rhythmic_element (Moment, int, bool, Rational);
+ bool tuplet_start_;
+
+ Beam_rhythmic_element (Moment, int, bool, Rational, bool);
Beam_rhythmic_element ();
int count (Direction d) const;
void beamify (Beaming_options const &);
void de_grace ();
- void add_stem (Moment d, int beams, bool invisible, Rational factor);
+ void add_stem (Moment d, int beams, bool invisible, Rational factor, bool tuplet_starrt);
int beamlet_count (int idx, Direction d) const;
bool invisibility (int idx) const;
Rational factor (int idx) const;
+ bool tuplet_start (int idx) const;
Moment start_moment (int idx) const;
Moment end_moment (int idx) const;
Beaming_pattern *split_pattern (int idx);
vector <Grob *> maybe_flags_;
Stream_event *rhythmic_ev_;
Stream_event *tremolo_ev_;
+ bool tuplet_start_;
TRANSLATOR_DECLARATIONS (Stem_engraver);
protected:
- void make_stem (Grob_info);
+ void make_stem (Grob_info, bool);
DECLARE_TRANSLATOR_LISTENER (tremolo);
+ DECLARE_TRANSLATOR_LISTENER (tuplet_span);
DECLARE_ACKNOWLEDGER (rhythmic_head);
void stop_translation_timestep ();
void finalize ();
stem_ = 0;
tremolo_ = 0;
rhythmic_ev_ = 0;
+ tuplet_start_ = false;
}
void
-Stem_engraver::make_stem (Grob_info gi)
+Stem_engraver::make_stem (Grob_info gi, bool tuplet_start)
{
/* Announce the cause of the head as cause of the stem. The
stem needs a rhythmic structure to fit it into a beam. */
stem_ = make_item ("Stem", gi.grob ()->self_scm ());
+ if (tuplet_start)
+ stem_->set_property ("tuplet-start", SCM_BOOL_T);
(void) make_item ("StemStub", gi.grob ()->self_scm ());
if (tremolo_ev_)
{
return;
if (!stem_)
- make_stem (gi);
+ make_stem (gi, tuplet_start_);
+
int ds = Stem::duration_log (stem_);
int dc = d->duration_log ();
stem_->set_object ("flag", flag->self_scm ());
maybe_flags_.push_back (flag);
}
+ if (tuplet_start_)
+ stem_->set_property ("tuplet-start", SCM_BOOL_T);
}
void
}
stem_ = 0;
}
+ tuplet_start_ = false;
tremolo_ev_ = 0;
}
+IMPLEMENT_TRANSLATOR_LISTENER (Stem_engraver, tuplet_span);
+void
+Stem_engraver::listen_tuplet_span (Stream_event *ev)
+{
+ Direction dir = to_dir (ev->get_property ("span-direction"));
+ if (dir == START)
+ {
+ // set stem property if stem already exists
+ if (stem_)
+ stem_->set_property ("tuplet-start", SCM_BOOL_T);
+ tuplet_start_ = true; // stash the value for use in later creation
+ }
+}
+
IMPLEMENT_TRANSLATOR_LISTENER (Stem_engraver, tremolo);
void
Stem_engraver::listen_tremolo (Stream_event *ev)
"stemlet-length "
"thickness "
"tremolo-flag "
+ "tuplet-start "
);
/****************************************************************/
(ties ,ly:grob-array? "A grob array of @code{Tie} objects.")
(tremolo-flag ,ly:grob? "The tremolo object on a stem.")
(tuplet-number ,ly:grob? "The number for a bracket.")
+ (tuplet-start ,boolean? "Is stem at the start of a tuplet?")
(tuplets ,ly:grob-array? "An array of smaller tuplet brackets.")
(X-colliding-grobs ,ly:grob-array? "Grobs that can collide
with a self-aligned grob on the X-axis.")