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