X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fpercent-repeat-engraver.cc;h=dff1f5aae4816ad1c2247522ba83eddfaac6e46e;hb=5b4b0d6e9a197e8f9eb085b7c2ad78b8be3e5cfc;hp=521972ec315be8464af520c65dbfe8e3790062a2;hpb=2c22efe5a46a37065b10c3f51c5d7db00d07d318;p=lilypond.git diff --git a/lily/percent-repeat-engraver.cc b/lily/percent-repeat-engraver.cc index 521972ec31..dff1f5aae4 100644 --- a/lily/percent-repeat-engraver.cc +++ b/lily/percent-repeat-engraver.cc @@ -1,62 +1,65 @@ /* - new-chord-tremolo-engraver.cc -- implement Chord_tremolo_engraver + percent-repeat-engraver.cc -- implement Percent_repeat_engraver source file of the GNU LilyPond music typesetter - (c) 2000--2005 Han-Wen Nienhuys + (c) 2000--2008 Han-Wen Nienhuys , Erik Sandberg */ -#include "repeated-music.hh" + +#include "score-engraver.hh" + +#include "bar-line.hh" #include "global-context.hh" -#include "warn.hh" +#include "international.hh" +#include "item.hh" #include "misc.hh" +#include "repeated-music.hh" +#include "side-position-interface.hh" #include "spanner.hh" -#include "item.hh" -#include "percent-repeat-iterator.hh" -#include "bar-line.hh" -#include "score-engraver.hh" - -/** - This acknowledges repeated music with "percent" style. It typesets - a % sign. - - TODO: +#include "stream-event.hh" +#include "warn.hh" - - BEAT case: Create items for single beat repeats, i.e. c4 / / / +#include "translator.icc" - - DOUBLE_MEASURE case: attach a % to an appropriate barline. +/* +* TODO: Create separate Double_percent_repeat_engraver? +* Or, at least move double percent handling to Slash_repeat_engraver */ + class Percent_repeat_engraver : public Engraver { void typeset_perc (); + bool check_count_visibility (SCM count); public: TRANSLATOR_DECLARATIONS (Percent_repeat_engraver); + protected: - Music *repeat_; + Stream_event *percent_event_; - /// moment (global time) where beam started. - Moment start_mom_; + /// moment (global time) where percent started. Moment stop_mom_; + Moment start_mom_; - /// location within measure where beam started. - Moment beam_start_location_; - Moment next_moment_; - Moment body_length_; - - enum + enum Repeat_sign_type { UNKNOWN, MEASURE, DOUBLE_MEASURE, - } - repeat_sign_type_; + }; + Repeat_sign_type repeat_sign_type_; - Item *double_percent_; - Spanner *perc_; - Spanner *finished_perc_; + Spanner *percent_; + Spanner *percent_counter_; + + + Grob *first_command_column_; + Moment command_moment_; + protected: virtual void finalize (); - virtual bool try_music (Music *); + DECLARE_TRANSLATOR_LISTENER (percent); + void stop_translation_timestep (); void start_translation_timestep (); void process_music (); @@ -64,143 +67,191 @@ protected: Percent_repeat_engraver::Percent_repeat_engraver () { - perc_ = 0; - finished_perc_ = 0; - repeat_ = 0; + percent_ = 0; + percent_counter_ = 0; + percent_event_ = 0; - double_percent_ = 0; + first_command_column_ = 0; + command_moment_ = Moment (-1); } -bool -Percent_repeat_engraver::try_music (Music *m) +void +Percent_repeat_engraver::start_translation_timestep () { - if (m->is_mus_type ("repeated-music") - && m->get_property ("iterator-ctor") - == Percent_repeat_iterator::constructor_proc - && !repeat_) + if (now_mom ().main_part_ != command_moment_.main_part_) { - body_length_ = Repeated_music::body_get_length (m); - int count = Repeated_music::repeat_count (m); - - Moment now = now_mom (); - start_mom_ = now; - stop_mom_ = start_mom_ + Moment (count) * body_length_; - next_moment_ = start_mom_ + body_length_; - - Moment meas_len (robust_scm2moment (get_property ("measureLength"), Moment (1))); - if (meas_len == body_length_) - repeat_sign_type_ = MEASURE; - else if (Moment (2) * meas_len == body_length_) - repeat_sign_type_ = DOUBLE_MEASURE; - else - { - warning (_f ("can't handle a percent repeat of length: %s", - body_length_.to_string ())); - return false; - } + first_command_column_ = unsmob_grob (get_property ("currentCommandColumn")); + command_moment_ = now_mom (); + } - repeat_ = m; + if (stop_mom_.main_part_ == now_mom ().main_part_) + { + if (percent_) + typeset_perc (); + percent_event_ = 0; + repeat_sign_type_ = UNKNOWN; + } +} - Global_context *global = get_global_context (); - for (int i = 1; i < count; i++) +IMPLEMENT_TRANSLATOR_LISTENER (Percent_repeat_engraver, percent); +void +Percent_repeat_engraver::listen_percent (Stream_event *ev) +{ + if (!percent_event_) + { + Moment body_length = get_event_length (ev); + Moment meas_len (robust_scm2moment (get_property ("measureLength"), + Moment (1))); + if (meas_len == body_length) { - Moment m = next_moment_ + Moment (i) * body_length_; - global->add_moment_to_process (m); - - /* bars between % too. */ - if (repeat_sign_type_ == DOUBLE_MEASURE) - global->add_moment_to_process (m - meas_len); + repeat_sign_type_ = MEASURE; + start_mom_ = now_mom (); + stop_mom_ = now_mom () + body_length; + get_global_context ()->add_moment_to_process (stop_mom_); } - - if (repeat_sign_type_ == DOUBLE_MEASURE) - next_moment_ += meas_len; - - return true; + else if (Moment (2) * meas_len == body_length) + { + repeat_sign_type_ = DOUBLE_MEASURE; + start_mom_ = now_mom () + meas_len; + stop_mom_ = now_mom () + body_length; /* never used */ + get_global_context ()->add_moment_to_process (start_mom_); + } + else + { + /* + don't warn about percent repeats: slash repeats are not + exactly 1 or 2 measures long. + */ + return; + } + percent_event_ = ev; } - - return false; + else + /* print a warning: no assignment happens because + percent_event_ != 0 */ + ASSIGN_EVENT_ONCE (percent_event_, ev); } void Percent_repeat_engraver::process_music () { - if (repeat_ && now_mom () == next_moment_) + if (percent_event_ && now_mom ().main_part_ == start_mom_.main_part_) { if (repeat_sign_type_ == MEASURE) { - finished_perc_ = perc_; - typeset_perc (); - perc_ = make_spanner ("PercentRepeat", repeat_->self_scm ()); - SCM col = get_property ("currentCommandColumn"); - perc_->set_bound (LEFT, unsmob_grob (col)); + if (percent_) + typeset_perc (); + + percent_ = make_spanner ("PercentRepeat", percent_event_->self_scm ()); + + Grob *col = first_command_column_; + percent_->set_bound (LEFT, col); + + SCM count = percent_event_->get_property ("repeat-count"); + if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats")) + && check_count_visibility (count)) + { + percent_counter_ + = make_spanner ("PercentRepeatCounter", percent_event_->self_scm ()); + + SCM text = scm_number_to_string (count, scm_from_int (10)); + percent_counter_->set_property ("text", text); + percent_counter_->set_bound (LEFT, col); + Side_position_interface::add_support (percent_counter_, + percent_); + percent_counter_->set_parent (percent_, Y_AXIS); + } + else + percent_counter_ = 0; } else if (repeat_sign_type_ == DOUBLE_MEASURE) { - double_percent_ = make_item ("DoublePercentRepeat", repeat_->self_scm ()); - - /* - forbid breaks on a % line. Should forbid all breaks, really. - - Ugh. Why can't this be regular communication between - contexts? - */ - get_score_engraver ()->forbid_breaks (); + Item *double_percent = make_item ("DoublePercentRepeat", percent_event_->self_scm ()); + + SCM count = percent_event_->get_property ("repeat-count"); + if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats")) + && check_count_visibility (count)) + { + Item *double_percent_counter = make_item ("DoublePercentRepeatCounter", + percent_event_->self_scm ()); + + SCM text = scm_number_to_string (count, + scm_from_int (10)); + double_percent_counter->set_property ("text", text); + + Side_position_interface::add_support (double_percent_counter, + double_percent); + double_percent_counter->set_parent (double_percent, Y_AXIS); + double_percent_counter->set_parent (double_percent, X_AXIS); + } + + /* forbid breaks on a % line. Should forbid all breaks, really. */ + context ()->get_score_context ()->set_property ("forbidBreak", SCM_BOOL_T); + + /* No more processing needed. */ + repeat_sign_type_ = UNKNOWN; } - next_moment_ = next_moment_ + body_length_; } } void Percent_repeat_engraver::finalize () { - typeset_perc (); - if (perc_) + if (percent_) { - repeat_->origin ()->warning (_ ("unterminated percent repeat")); - perc_->suicide (); + percent_event_->origin ()->warning (_ ("unterminated percent repeat")); + percent_->suicide (); + percent_counter_->suicide (); } } void Percent_repeat_engraver::typeset_perc () { - if (finished_perc_) + if (percent_) { - SCM col = get_property ("currentCommandColumn"); - finished_perc_->set_bound (RIGHT, unsmob_grob (col)); - finished_perc_ = 0; - } + Grob *col = first_command_column_; + + percent_->set_bound (RIGHT, col); + percent_ = 0; - double_percent_ = 0; + if (percent_counter_) + percent_counter_->set_bound (RIGHT, col); + percent_counter_ = 0; + } } -void -Percent_repeat_engraver::start_translation_timestep () +bool +Percent_repeat_engraver::check_count_visibility (SCM count) { - if (stop_mom_ == now_mom ()) - { - if (perc_) - { - finished_perc_ = perc_; - typeset_perc (); - } - repeat_ = 0; - perc_ = 0; - repeat_sign_type_ = UNKNOWN; - } + SCM proc = get_property ("repeatCountVisibility"); + return (ly_is_procedure (proc) && to_boolean (scm_call_2 (proc, + count, + context ()->self_scm ()))); } + void Percent_repeat_engraver::stop_translation_timestep () { - typeset_perc (); } -#include "translator.icc" - ADD_TRANSLATOR (Percent_repeat_engraver, - /* doc */ "Make whole bar and double bar repeats.", - /* create */ "PercentRepeat DoublePercentRepeat", - /* accept */ "repeated-music", - /* read */ "measureLength currentCommandColumn", - /* write */ ""); + /* doc */ + "Make whole bar and double bar repeats.", + + /* create */ + "DoublePercentRepeat " + "DoublePercentRepeatCounter " + "PercentRepeat " + "PercentRepeatCounter ", + + /* read */ + "countPercentRepeats " + "currentCommandColumn " + "measureLength " + "repeatCountVisibility ", + + /* write */ + "forbidBreak " + );