]> git.donarmstrong.com Git - lilypond.git/blob - lily/percent-repeat-engraver.cc
3090e9b615cce4ab84fe4f5d109bbf0b7a40d555
[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--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include "engraver.hh"
11 #include "repeated-music.hh"
12 #include "engraver-group-engraver.hh"
13 #include "global-context.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-line.hh"
20
21 #include "score-engraver.hh"
22 #include "context.hh"
23
24
25 /**
26   This acknowledges repeated music with "percent" style.  It typesets
27   a % sign.  
28
29   TODO:
30
31   - BEAT case: Create items for single beat repeats, i.e. c4 / / /
32
33   - DOUBLE_MEASURE case: attach a % to an appropriate barline.
34   
35 */
36 class Percent_repeat_engraver : public Engraver
37 {
38   void typeset_perc ();
39 public:
40   TRANSLATOR_DECLARATIONS (Percent_repeat_engraver);
41 protected:
42   Repeated_music * repeat_;
43
44   /// moment (global time) where beam started.
45   Moment start_mom_;
46   Moment stop_mom_;
47
48   /// location  within measure where beam started.
49   Moment beam_start_location_;
50   Moment next_moment_;
51   Moment body_length_;
52
53   enum {
54     UNKNOWN,
55     MEASURE,
56     DOUBLE_MEASURE,
57   } repeat_sign_type_ ;
58
59   Item * double_percent_;
60   Spanner * perc_;
61   Spanner * finished_perc_;
62 protected:
63   virtual void finalize ();
64   virtual bool try_music (Music*);
65   virtual void stop_translation_timestep ();
66   virtual void start_translation_timestep ();
67   virtual void process_music ();
68 };
69
70 Percent_repeat_engraver::Percent_repeat_engraver ()
71 {
72   perc_  = 0;
73   finished_perc_ = 0;
74   repeat_ =0;
75
76   double_percent_ = 0;
77 }
78
79 bool
80 Percent_repeat_engraver::try_music (Music * m)
81 {
82   Repeated_music * rp = dynamic_cast<Repeated_music*> (m);
83   if (rp
84       && rp->get_property ("iterator-ctor")
85          == Percent_repeat_iterator::constructor_proc
86       && !repeat_)
87     {
88       body_length_ = rp->body_get_length ();
89       int count =   rp->repeat_count ();
90       
91       Moment now = now_mom ();
92       start_mom_ = now;
93       stop_mom_ = start_mom_ + Moment (count) * body_length_;
94       next_moment_ = start_mom_ + body_length_;
95
96       SCM m = get_property ("measureLength");
97       Moment meas_len;
98       if (unsmob_moment (m))
99         meas_len = *unsmob_moment (m);
100
101       if (meas_len == body_length_)
102         repeat_sign_type_ = MEASURE;
103       else if (Moment (2)* meas_len == body_length_)
104         {
105           repeat_sign_type_ = DOUBLE_MEASURE;
106           next_moment_ += meas_len ;
107         }
108       else
109         {
110           warning (_ ("Don't know how to handle a percent repeat of this length."));
111           return false;
112         }
113
114       repeat_ = rp;
115
116       
117       Global_context *global = get_global_context ();
118       for (int i = 0; i < count; i++)  
119         global->add_moment_to_process (next_moment_ + Moment (i) * body_length_);
120   
121       return true;
122     }
123
124   return false;
125 }
126
127 void
128 Percent_repeat_engraver::process_music ()
129 {
130   if (repeat_ && now_mom () == next_moment_)
131     {
132       if (repeat_sign_type_ == MEASURE)
133         {
134           finished_perc_ = perc_;
135           typeset_perc ();
136           perc_ = make_spanner ("PercentRepeat");
137           SCM col =get_property ("currentCommandColumn");
138           perc_->set_bound (LEFT, unsmob_grob (col));
139           announce_grob (perc_, repeat_->self_scm ());
140         }
141       else if (repeat_sign_type_ == DOUBLE_MEASURE)
142         {
143           double_percent_ = make_item ("DoublePercentRepeat");
144           announce_grob (double_percent_, repeat_->self_scm ());
145
146       /*
147         forbid breaks on a % line. Should forbid all breaks, really.
148        */
149
150           get_score_engraver ()->forbid_breaks ();      // guh. Use properties!      
151         }
152       next_moment_ = next_moment_ + body_length_;
153
154       get_global_context ()->add_moment_to_process (next_moment_);
155     }
156 }
157
158 void
159 Percent_repeat_engraver::finalize ()
160 {
161   typeset_perc ();
162   if (perc_)
163     {
164       repeat_->origin ()->warning (_ ("unterminated percent repeat"));
165       perc_->suicide ();
166     }
167 }
168
169 void
170 Percent_repeat_engraver::typeset_perc ()
171 {
172   if (finished_perc_)
173     {
174       SCM col =get_property ("currentCommandColumn");
175       finished_perc_->set_bound (RIGHT, unsmob_grob (col));
176       typeset_grob (finished_perc_);
177       finished_perc_ = 0;
178     }
179
180   if (double_percent_)
181     {
182       typeset_grob (double_percent_);
183       double_percent_ = 0;
184     }
185 }
186
187
188
189
190 void
191 Percent_repeat_engraver::start_translation_timestep ()
192 {
193   if (stop_mom_ == now_mom ())
194     {
195       if (perc_)
196         {
197           finished_perc_ = perc_;
198           typeset_perc ();
199         }
200       repeat_ = 0;
201       perc_ = 0;
202       repeat_sign_type_ = UNKNOWN;
203     }
204 }
205
206
207 void
208 Percent_repeat_engraver::stop_translation_timestep ()
209 {
210   typeset_perc ();
211 }
212
213
214
215
216 ENTER_DESCRIPTION (Percent_repeat_engraver,
217 /* descr */       "Make whole bar and double bar repeats.",
218 /* creats*/       "PercentRepeat DoublePercentRepeat",
219 /* accepts */     "repeated-music",
220 /* acks  */      "",
221 /* reads */       "measureLength currentCommandColumn",
222 /* write */       "");