2 tuplet-engraver.cc -- implement Tuplet_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "tuplet-bracket.hh"
10 #include "note-column.hh"
12 #include "engraver.hh"
15 #include "translator.icc"
17 struct Tuplet_description
29 static int compare (Tuplet_description const &a, Tuplet_description const &b)
31 return ::compare (a.length_, b.length_);
35 class Tuplet_engraver : public Engraver
38 TRANSLATOR_DECLARATIONS (Tuplet_engraver);
41 Array<Tuplet_description> tuplets_;
42 Link_array<Spanner> last_tuplets_;
43 DECLARE_ACKNOWLEDGER (note_column);
44 virtual bool try_music (Music *r);
45 virtual void finalize ();
46 void start_translation_timestep ();
47 void process_music ();
51 Tuplet_engraver::try_music (Music *music)
53 if (music->is_mus_type ("time-scaled-music"))
55 Music *el = unsmob_music (music->get_property ("element"));
56 if (el && !el->is_mus_type ("event-chord"))
60 d.length_ = music->get_length ().main_part_;
61 d.stop_ = now_mom ().main_part_ + d.length_;
62 d.span_stop_ = d.stop_;
64 SCM s = get_property ("tupletSpannerDuration");
65 if (unsmob_moment (s))
66 d.span_stop_ = min (d.span_stop_, (now_mom () + *unsmob_moment (s)).main_part_);
76 Tuplet_engraver::process_music ()
78 if (!tuplets_.size ())
81 tuplets_.sort (&Tuplet_description::compare);
82 for (int i = 0; i < tuplets_.size (); i++)
84 if (tuplets_[i].spanner_)
87 Spanner *spanner = make_spanner ("TupletBracket",
88 tuplets_[i].music_->self_scm ());
89 tuplets_[i].spanner_ = spanner;
91 if (i > 0 && tuplets_[i - 1].spanner_)
92 Tuplet_bracket::add_tuplet_bracket (tuplets_[i].spanner_, tuplets_[i - 1].spanner_);
93 if (i < tuplets_.size () - 1 && tuplets_[i + 1].spanner_)
94 Tuplet_bracket::add_tuplet_bracket (tuplets_[i + 1].spanner_, tuplets_[i].spanner_);
96 SCM proc = get_property ("tupletNumberFormatFunction");
97 if (ly_is_procedure (proc))
99 SCM t = scm_apply_0 (proc, scm_list_1 (tuplets_[i].music_->self_scm ()));
100 spanner->set_property ("text", t);
106 Tuplet_engraver::acknowledge_note_column (Grob_info i)
108 for (int j = 0; j < tuplets_.size (); j++)
109 if (tuplets_[j].spanner_)
110 Tuplet_bracket::add_column (tuplets_[j].spanner_,
111 dynamic_cast<Item *> (i.grob ()));
115 Tuplet_engraver::start_translation_timestep ()
117 Moment now = now_mom ();
119 last_tuplets_.clear ();
120 if (tuplets_.is_empty ())
123 Moment tsdmom = robust_scm2moment (get_property ("tupletSpannerDuration"), Moment (0));
124 bool full_length = to_boolean (get_property ("tupletFullLength"));
126 for (int i = tuplets_.size (); i--;)
128 Rational tsd = tsdmom.main_part_;
130 if (now.main_part_ >= tuplets_[i].span_stop_)
132 if (tuplets_[i].spanner_)
136 Item *col = unsmob_item (get_property ("currentMusicalColumn"));
138 tuplets_[i].spanner_->set_bound (RIGHT, col);
140 else if (!tuplets_[i].spanner_->get_bound (RIGHT))
141 tuplets_[i].spanner_->set_bound (RIGHT,
142 tuplets_[i].spanner_->get_bound (LEFT));
144 last_tuplets_.push (tuplets_[i].spanner_);
145 tuplets_[i].spanner_ = 0;
149 tuplets_[i].span_stop_ += tsd;
152 if (now.main_part_ >= tuplets_[i].stop_)
158 Tuplet_engraver::finalize ()
160 if (to_boolean (get_property ("tupletFullLength")))
162 for (int i = 0; i < last_tuplets_.size (); i++)
164 Item *col = unsmob_item (get_property ("currentCommandColumn"));
165 last_tuplets_[i]->set_bound (RIGHT, col);
170 Tuplet_engraver::Tuplet_engraver ()
174 ADD_ACKNOWLEDGER (Tuplet_engraver, note_column);
175 ADD_TRANSLATOR (Tuplet_engraver,
176 /* doc */ "Catch Time_scaled_music and generate appropriate bracket ",
177 /* create */ "TupletBracket",
178 /* accept */ "time-scaled-music",
179 /* read */ "tupletNumberFormatFunction tupletSpannerDuration tupletFullLength",