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_);
37 class Tuplet_engraver : public Engraver
40 TRANSLATOR_DECLARATIONS (Tuplet_engraver);
43 Array<Tuplet_description> tuplets_;
44 Link_array<Spanner> last_tuplets_;
45 DECLARE_ACKNOWLEDGER (note_column);
46 virtual bool try_music (Music *r);
47 virtual void finalize ();
48 void start_translation_timestep ();
49 void process_music ();
53 Tuplet_engraver::try_music (Music *music)
55 if (music->is_mus_type ("time-scaled-music"))
57 Music *el = unsmob_music (music->get_property ("element"));
58 if (el && !el->is_mus_type ("event-chord"))
62 d.length_ = music->get_length ().main_part_;
63 d.stop_ = now_mom ().main_part_ + d.length_;
64 d.span_stop_ = d.stop_;
66 SCM s = get_property ("tupletSpannerDuration");
67 if (unsmob_moment (s))
68 d.span_stop_ = min (d.span_stop_, (now_mom () + *unsmob_moment (s)).main_part_);
78 Tuplet_engraver::process_music ()
80 if (!tuplets_.size ())
84 tuplets_.sort (&Tuplet_description::compare);
85 for (int i = 0; i < tuplets_.size (); i++)
87 if (tuplets_[i].spanner_)
90 Spanner *spanner = make_spanner ("TupletBracket",
91 tuplets_[i].music_->self_scm ());
92 tuplets_[i].spanner_ = spanner;
94 if (i > 0 && tuplets_[i-1].spanner_)
95 Tuplet_bracket::add_tuplet_bracket (tuplets_[i].spanner_, tuplets_[i-1].spanner_);
96 if (i < tuplets_.size()-1 && tuplets_[i+1].spanner_)
97 Tuplet_bracket::add_tuplet_bracket (tuplets_[i+1].spanner_, tuplets_[i].spanner_);
99 SCM proc = get_property ("tupletNumberFormatFunction");
100 if (ly_is_procedure (proc))
102 SCM t = scm_apply_0 (proc, scm_list_1 (tuplets_[i].music_->self_scm ()));
103 spanner->set_property ("text", t);
109 Tuplet_engraver::acknowledge_note_column (Grob_info i)
111 for (int j = 0; j < tuplets_.size (); j++)
112 if (tuplets_[j].spanner_)
113 Tuplet_bracket::add_column (tuplets_[j].spanner_,
114 dynamic_cast<Item *> (i.grob ()));
118 Tuplet_engraver::start_translation_timestep ()
120 Moment now = now_mom ();
122 last_tuplets_.clear ();
123 if (tuplets_.is_empty())
126 Moment tsdmom = robust_scm2moment (get_property ("tupletSpannerDuration"), Moment (0));
127 bool full_length = to_boolean (get_property ("tupletFullLength"));
129 for (int i = tuplets_.size (); i--;)
131 Rational tsd = tsdmom.main_part_;
133 if (now.main_part_ >= tuplets_[i].span_stop_)
135 if (tuplets_[i].spanner_)
139 Item * col = unsmob_item (get_property ("currentMusicalColumn"));
141 tuplets_[i].spanner_->set_bound (RIGHT, col);
143 else if (!tuplets_[i].spanner_->get_bound (RIGHT))
144 tuplets_[i].spanner_->set_bound (RIGHT,
145 tuplets_[i].spanner_->get_bound (LEFT));
147 last_tuplets_.push (tuplets_[i].spanner_);
148 tuplets_[i].spanner_ = 0;
152 tuplets_[i].span_stop_ += tsd;
155 if (now.main_part_ >= tuplets_[i].stop_)
163 Tuplet_engraver::finalize ()
165 if (to_boolean (get_property ("tupletFullLength")))
167 for (int i = 0; i < last_tuplets_.size (); i++)
169 Item * col = unsmob_item (get_property ("currentCommandColumn"));
170 last_tuplets_[i]->set_bound (RIGHT, col);
175 Tuplet_engraver::Tuplet_engraver ()
179 ADD_ACKNOWLEDGER (Tuplet_engraver,note_column);
180 ADD_TRANSLATOR (Tuplet_engraver,
181 /* descr */ "Catch Time_scaled_music and generate appropriate bracket ",
182 /* creats*/ "TupletBracket",
183 /* accepts */ "time-scaled-music",
184 /* reads */ "tupletNumberFormatFunction tupletSpannerDuration tupletFullLength" ,