]> git.donarmstrong.com Git - lilypond.git/blob - lily/percent-repeat-engraver.cc
(stop_translation_timestep): set
[lilypond.git] / lily / percent-repeat-engraver.cc
1 /*
2   new-chord-tremolo-engraver.cc -- implement Chord_tremolo_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2000--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9
10 #include "score-engraver.hh"
11
12 #include "bar-line.hh"
13 #include "global-context.hh"
14 #include "international.hh"
15 #include "item.hh"
16 #include "misc.hh"
17 #include "percent-repeat-iterator.hh"
18 #include "repeated-music.hh"
19 #include "score-context.hh"
20 #include "side-position-interface.hh"
21 #include "spanner.hh"
22 #include "warn.hh"
23
24 #include "translator.icc"
25
26 class Percent_repeat_engraver : public Engraver
27 {
28   void typeset_perc ();
29 public:
30   TRANSLATOR_DECLARATIONS (Percent_repeat_engraver);
31   
32 protected:
33   Music *repeat_;
34
35   /// moment (global time) where beam started.
36   Moment start_mom_;
37   Moment stop_mom_;
38
39   /// location within measure where beam started.
40   Moment beam_start_location_;
41   Moment next_moment_;
42   Moment body_length_;
43
44   enum Repeat_sign_type
45     {
46       UNKNOWN,
47       MEASURE,
48       DOUBLE_MEASURE,
49     };
50   Repeat_sign_type repeat_sign_type_;
51
52   Item *double_percent_;
53   Item *double_percent_counter_;
54   
55   Spanner *percent_;
56   Spanner *percent_counter_;
57   Spanner *finished_percent_;
58   Spanner *finished_percent_counter_;
59
60   int count_;
61   int total_count_; 
62 protected:
63   virtual void finalize ();
64   virtual bool try_music (Music *);
65
66   void stop_translation_timestep ();
67   void start_translation_timestep ();
68   void process_music ();
69 };
70
71 Percent_repeat_engraver::Percent_repeat_engraver ()
72 {
73   percent_ = 0;
74   percent_counter_ = 0;
75
76   finished_percent_ = 0;
77   finished_percent_counter_ = 0;
78
79   double_percent_ = 0;
80   double_percent_counter_ = 0;
81
82   repeat_ = 0;
83   count_ = 0;
84   total_count_ = 0;
85 }
86
87 bool
88 Percent_repeat_engraver::try_music (Music *m)
89 {
90   if (m->is_mus_type ("repeated-music")
91       && m->get_property ("iterator-ctor")
92       == Percent_repeat_iterator::constructor_proc
93       && !repeat_)
94     {
95       body_length_ = Repeated_music::body_get_length (m);
96       total_count_ = Repeated_music::repeat_count (m);
97       
98       Moment now = now_mom ();
99       start_mom_ = now;
100       stop_mom_ = start_mom_ + Moment (total_count_) * body_length_;
101       next_moment_ = start_mom_;
102       next_moment_ += body_length_;
103
104       Moment meas_len (robust_scm2moment (get_property ("measureLength"),
105                                           Moment (1)));
106       
107       if (meas_len == body_length_)
108         repeat_sign_type_ = MEASURE;
109       else if (Moment (2) * meas_len == body_length_)
110         repeat_sign_type_ = DOUBLE_MEASURE;
111       else
112         return false;
113     
114
115       repeat_ = m;
116
117       Global_context *global = get_global_context ();
118       for (int i = 1; i < total_count_; i++)
119         {
120           Moment m = next_moment_ + Moment (i) * body_length_;
121           global->add_moment_to_process (m);
122
123           /* bars between % too.  */
124           if (repeat_sign_type_ == DOUBLE_MEASURE)
125             global->add_moment_to_process (m - meas_len);
126         }
127
128       if (repeat_sign_type_ == DOUBLE_MEASURE)
129         next_moment_ += meas_len;
130
131       count_ = 1;
132       return true;
133     }
134
135   return false;
136 }
137
138 void
139 Percent_repeat_engraver::process_music ()
140 {
141   if (repeat_ && now_mom ().main_part_ == next_moment_.main_part_)
142     {
143       count_ ++; 
144       if (repeat_sign_type_ == MEASURE)
145         {
146           finished_percent_ = percent_;
147           finished_percent_counter_ = percent_counter_;
148           
149           typeset_perc ();
150           percent_ = make_spanner ("PercentRepeat", repeat_->self_scm ());
151
152           Grob *col = unsmob_grob (get_property ("currentCommandColumn"));
153           percent_->set_bound (LEFT, col);
154
155           if (total_count_ > 2
156               && to_boolean (get_property ("countPercentRepeats")))
157             {
158               percent_counter_
159                 = make_spanner ("PercentRepeatCounter", repeat_->self_scm ());
160
161               SCM text = scm_number_to_string (scm_from_int (count_),
162                                                scm_from_int (10));
163               percent_counter_->set_property ("text", text);
164               percent_counter_->set_bound (LEFT, col);
165               Side_position_interface::add_support (percent_counter_,
166                                                     percent_);
167               percent_counter_->set_parent (percent_, Y_AXIS);
168             }     
169         }
170       else if (repeat_sign_type_ == DOUBLE_MEASURE)
171         {
172           double_percent_ = make_item ("DoublePercentRepeat", repeat_->self_scm ());
173
174           if (total_count_ > 2
175               && to_boolean (get_property ("countPercentRepeats")))
176             {
177               double_percent_counter_
178                 = make_item ("DoublePercentRepeatCounter",
179                              repeat_->self_scm());
180
181               SCM text = scm_number_to_string (scm_from_int (count_),
182                                                scm_from_int (10));
183               double_percent_counter_->set_property ("text", text);
184
185               Side_position_interface::add_support (double_percent_counter_,
186                                                     double_percent_);
187               double_percent_counter_->set_parent (double_percent_, Y_AXIS);
188               double_percent_counter_->set_parent (double_percent_, X_AXIS);
189             }
190           
191           /* forbid breaks on a % line. Should forbid all breaks, really. */
192           context ()->get_score_context ()->set_property ("forbidBreak", SCM_BOOL_T);
193         }
194       next_moment_ = next_moment_ + body_length_;
195       next_moment_.grace_part_ = Rational (0);
196     }
197 }
198
199 void
200 Percent_repeat_engraver::finalize ()
201 {
202   typeset_perc ();
203   if (percent_)
204     {
205       repeat_->origin ()->warning (_ ("unterminated percent repeat"));
206       percent_->suicide ();
207       percent_counter_->suicide();
208     }
209 }
210
211 void
212 Percent_repeat_engraver::typeset_perc ()
213 {
214   if (finished_percent_)
215     {
216       Grob *col = unsmob_grob (get_property ("currentCommandColumn"));
217
218       finished_percent_->set_bound (RIGHT, col);
219       finished_percent_ = 0;
220
221       if (finished_percent_counter_)
222         finished_percent_counter_->set_bound (RIGHT, col);
223     
224       finished_percent_counter_ = 0;
225     }
226
227   double_percent_ = 0;
228   double_percent_counter_ = 0;
229 }
230
231 void
232 Percent_repeat_engraver::start_translation_timestep ()
233 {
234   if (stop_mom_.main_part_ == now_mom ().main_part_)
235     {
236       if (percent_)
237         {
238           finished_percent_ = percent_;
239           finished_percent_counter_ = percent_counter_;
240
241           typeset_perc ();
242         }
243       repeat_ = 0;
244       percent_ = 0;
245       
246       percent_counter_ = 0;
247       repeat_sign_type_ = UNKNOWN;
248     }
249 }
250
251 void
252 Percent_repeat_engraver::stop_translation_timestep ()
253 {
254   typeset_perc ();
255 }
256
257 ADD_TRANSLATOR (Percent_repeat_engraver,
258                 /* doc */
259                 "Make whole bar and double bar repeats.",
260                 
261                 /* create */
262                 "PercentRepeat "
263                 "DoublePercentRepeat "
264                 "PercentRepeatCounter "
265                 "DoublePercentRepeatCounter",
266                 
267                 /* accept */
268                 "repeated-music",
269
270                 /* read */
271                 "measureLength "
272                 "currentCommandColumn "
273                 "countPercentRepeats",
274
275                 /* write */
276                 "forbidBreak "
277                 );