/* tuplet-engraver.cc -- implement Tuplet_engraver source file of the GNU LilyPond music typesetter (c) 1998--2006 Han-Wen Nienhuys */ #include "tuplet-bracket.hh" #include "note-column.hh" #include "beam.hh" #include "engraver.hh" #include "spanner.hh" #include "translator.icc" struct Tuplet_description { Music *music_; Spanner *bracket_; Spanner *number_; Tuplet_description () { music_ = 0; bracket_ = 0; number_ = 0; } }; class Tuplet_engraver : public Engraver { public: TRANSLATOR_DECLARATIONS (Tuplet_engraver); protected: vector tuplets_; vector stopped_tuplets_; vector last_tuplets_; DECLARE_ACKNOWLEDGER (note_column); virtual bool try_music (Music *r); virtual void finalize (); void start_translation_timestep (); void process_music (); }; bool Tuplet_engraver::try_music (Music *music) { if (music->is_mus_type ("tuplet-spanner-event")) { Direction dir = to_dir (music->get_property ("span-direction")); if (dir == START) { Tuplet_description d; d.music_ = music; tuplets_.push_back (d); } if (dir == STOP) { stopped_tuplets_.push_back (tuplets_.back ()); tuplets_.pop_back (); } return true; } return false; } void Tuplet_engraver::process_music () { for (vsize i = 0; i < stopped_tuplets_.size (); i++) { bool full_length = to_boolean (get_property ("tupletFullLength")); if (stopped_tuplets_[i].bracket_) { if (full_length) { Item *col = unsmob_item (get_property ("currentMusicalColumn")); stopped_tuplets_[i].bracket_->set_bound (RIGHT, col); stopped_tuplets_[i].number_->set_bound (RIGHT, col); } else if (!stopped_tuplets_[i].bracket_->get_bound (RIGHT)) { stopped_tuplets_[i].bracket_->set_bound (RIGHT, stopped_tuplets_[i].bracket_->get_bound (LEFT)); stopped_tuplets_[i].number_->set_bound (RIGHT, stopped_tuplets_[i].bracket_->get_bound (LEFT)); } // todo: scrap last_tuplets_, use stopped_tuplets_ only. // clear stopped_tuplets_ at start_translation_timestep last_tuplets_.push_back (tuplets_[i].bracket_); last_tuplets_.push_back (tuplets_[i].number_); } } stopped_tuplets_.clear (); if (!tuplets_.size ()) return; for (vsize i = 0; i < tuplets_.size (); i++) { if (tuplets_[i].bracket_) continue; tuplets_[i].bracket_ = make_spanner ("TupletBracket", tuplets_[i].music_->self_scm ()); tuplets_[i].number_ = make_spanner ("TupletNumber", tuplets_[i].music_->self_scm ()); tuplets_[i].number_->set_object ("bracket", tuplets_[i].bracket_->self_scm ()); tuplets_[i].bracket_->set_object ("tuplet-number", tuplets_[i].number_->self_scm ()); if (i > 0 && tuplets_[i - 1].bracket_) Tuplet_bracket::add_tuplet_bracket (tuplets_[i].bracket_, tuplets_[i - 1].bracket_); if (i < tuplets_.size () - 1 && tuplets_[i + 1].bracket_) Tuplet_bracket::add_tuplet_bracket (tuplets_[i + 1].bracket_, tuplets_[i].bracket_); SCM proc = get_property ("tupletNumberFormatFunction"); if (ly_is_procedure (proc)) { SCM t = scm_apply_0 (proc, scm_list_1 (tuplets_[i].music_->self_scm ())); tuplets_[i].number_->set_property ("text", t); } } } void Tuplet_engraver::acknowledge_note_column (Grob_info inf) { for (vsize j = 0; j < tuplets_.size (); j++) if (tuplets_[j].bracket_) { Item *i = dynamic_cast (inf.grob ()); Tuplet_bracket::add_column (tuplets_[j].bracket_, i); add_bound_item (tuplets_[j].number_, i); } } void Tuplet_engraver::start_translation_timestep () { last_tuplets_.clear (); } void Tuplet_engraver::finalize () { if (to_boolean (get_property ("tupletFullLength"))) { for (vsize i = 0; i < last_tuplets_.size (); i++) { Item *col = unsmob_item (get_property ("currentCommandColumn")); last_tuplets_[i]->set_bound (RIGHT, col); } } } Tuplet_engraver::Tuplet_engraver () { } ADD_ACKNOWLEDGER (Tuplet_engraver, note_column); ADD_TRANSLATOR (Tuplet_engraver, /* doc */ "Catch TupletSpannerEvent and generate appropriate bracket ", /* create */ "TupletBracket TupletNumber", /* accept */ "tuplet-spanner-event", /* read */ "tupletNumberFormatFunction tupletSpannerDuration tupletFullLength", /* write */ "");