lilypond-1.4.2
[lilypond.git] / lily / percent-repeat-engraver.cc
blob994288da6406d9f4def48db2467390392af9e4c0
1 /*
2 new-chord-tremolo-engraver.cc -- implement Chord_tremolo_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
10 #include "engraver.hh"
11 #include "repeated-music.hh"
12 #include "engraver-group-engraver.hh"
13 #include "global-translator.hh"
14 #include "warn.hh"
15 #include "misc.hh"
16 #include "spanner.hh"
17 #include "item.hh"
18 #include "percent-repeat-iterator.hh"
19 #include "bar.hh"
21 #include "score-engraver.hh"
22 #include "translator-group.hh"
24 /**
25 This acknowledges repeated music with "percent" style. It typesets
26 a % sign.
28 TODO:
30 - BEAT case: Create items for single beat repeats, i.e. c4 / / /
32 - DOUBLE_MEASURE case: attach a % to an appropriate barline.
35 class Percent_repeat_engraver : public Engraver
37 void typeset_perc ();
38 public:
39 VIRTUAL_COPY_CONS (Translator);
40 Percent_repeat_engraver ();
41 protected:
42 Repeated_music * repeat_;
44 /// moment (global time) where beam started.
45 Moment start_mom_;
46 Moment stop_mom_;
48 /// location within measure where beam started.
49 Moment beam_start_location_;
50 Moment next_moment_;
51 Moment body_length_;
53 enum {
54 UNKNOWN,
55 BEAT,
56 MEASURE,
57 DOUBLE_MEASURE,
58 } repeat_sign_type_ ;
60 Item * beat_slash_;
61 Item * double_percent_;
62 Spanner * perc_p_;
63 Spanner * finished_perc_p_;
64 Item * stem_tremolo_;
65 protected:
66 virtual void finalize ();
67 virtual bool try_music (Music*);
68 virtual void acknowledge_grob (Grob_info);
69 virtual void stop_translation_timestep ();
70 virtual void start_translation_timestep ();
71 virtual void process_music ();
74 Percent_repeat_engraver::Percent_repeat_engraver ()
76 perc_p_ = finished_perc_p_ = 0;
77 repeat_ =0;
78 stem_tremolo_ = 0;
80 beat_slash_ = 0;
81 double_percent_ = 0;
84 bool
85 Percent_repeat_engraver::try_music (Music * m)
87 Repeated_music * rp = dynamic_cast<Repeated_music*> (m);
88 if (rp
89 && rp->get_mus_property ("iterator-ctor")
90 == Percent_repeat_iterator::constructor_cxx_function
91 && !repeat_)
93 body_length_ = rp->body_length_mom ();
94 int count = rp->repeat_count ();
96 Moment now = now_mom ();
97 start_mom_ = now;
98 stop_mom_ = start_mom_ + Moment (count) * body_length_;
99 next_moment_ = start_mom_ + body_length_;
101 SCM m = get_property ("measureLength");
102 Moment meas_len;
103 if (unsmob_moment (m))
104 meas_len = *unsmob_moment (m);
106 if (body_length_ < meas_len &&
107 meas_len.mod_rat (body_length_) == Moment (0,0))
108 repeat_sign_type_ = BEAT;
109 else if (meas_len == body_length_)
110 repeat_sign_type_ = MEASURE;
111 else if (Moment (2)* meas_len == body_length_)
113 repeat_sign_type_ = DOUBLE_MEASURE;
114 next_moment_ += meas_len ;
116 else
118 warning (_ ("Don't know how to handle a percent repeat of this length."));
119 return false;
122 repeat_ = rp;
125 Global_translator *global_l =0;
126 Translator *t = this;
129 t = t->daddy_trans_l_ ;
130 global_l = dynamic_cast<Global_translator*> (t);
132 while (!global_l);
134 for (int i = 0; i < count; i++)
135 global_l->add_moment_to_process (now + Moment (1+i) * body_length_);
137 return true;
140 return false;
143 void
144 Percent_repeat_engraver::process_music ()
146 if (repeat_ && now_mom () == next_moment_)
148 if (repeat_sign_type_ == BEAT)
150 beat_slash_ = new Item (get_property ("RepeatSlash"));
151 announce_grob (beat_slash_, repeat_);
153 else if (repeat_sign_type_ == MEASURE)
155 finished_perc_p_ = perc_p_;
156 typeset_perc ();
157 perc_p_ = new Spanner (get_property ("PercentRepeat"));
158 SCM col =get_property ("currentCommandColumn");
159 perc_p_->set_bound (LEFT, unsmob_grob (col));
160 announce_grob (perc_p_, repeat_);
162 else if (repeat_sign_type_ == DOUBLE_MEASURE)
165 double_percent_ = new Item (get_property ("DoublePercentRepeat"));
166 announce_grob (double_percent_, repeat_);
169 forbid breaks on a % line. Should forbid all breaks, really.
171 Score_engraver * e = 0;
172 Translator * t = daddy_grav_l ();
173 for (; !e && t; t = t->daddy_trans_l_)
175 e = dynamic_cast<Score_engraver*> (t);
178 if (!e)
179 programming_error ("No score engraver!");
180 else
181 e->forbid_breaks (); // guh. Use properties!
183 next_moment_ = next_moment_ + body_length_;
187 void
188 Percent_repeat_engraver::finalize ()
190 typeset_perc ();
191 if (perc_p_)
193 repeat_->origin ()->warning (_ ("unterminated chord tremolo"));
194 perc_p_->suicide ();
198 void
199 Percent_repeat_engraver::typeset_perc ()
201 if (finished_perc_p_)
203 SCM col =get_property ("currentCommandColumn");
204 finished_perc_p_->set_bound (RIGHT, unsmob_grob (col));
205 typeset_grob (finished_perc_p_);
206 finished_perc_p_ = 0;
209 if (beat_slash_)
211 typeset_grob (beat_slash_);
212 beat_slash_ = 0;
215 if (double_percent_)
217 typeset_grob (double_percent_);
218 double_percent_ = 0;
223 void
224 Percent_repeat_engraver::acknowledge_grob (Grob_info info)
230 void
231 Percent_repeat_engraver::start_translation_timestep ()
233 if (stop_mom_ == now_mom ())
235 if (perc_p_)
237 finished_perc_p_ = perc_p_;
238 typeset_perc ();
240 repeat_ = 0;
241 perc_p_ = 0;
242 repeat_sign_type_ = UNKNOWN;
247 void
248 Percent_repeat_engraver::stop_translation_timestep ()
250 typeset_perc ();
253 ADD_THIS_TRANSLATOR (Percent_repeat_engraver);