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