]> git.donarmstrong.com Git - lilypond.git/blob - src/simplewalker.cc
release: 0.0.22
[lilypond.git] / src / simplewalker.cc
1 /*
2   UGR!! CHAOS RULEZ
3   */
4 #include "textspanner.hh"
5 #include "script.hh"
6 #include "request.hh"
7 #include "voice.hh"
8 #include "clef.hh"
9 #include "beam.hh"
10 #include "pscore.hh"
11 #include "simplestaff.hh"
12 #include "simplewalker.hh"
13 #include "sccol.hh"
14 #include "stem.hh"
15 #include "notehead.hh"
16 #include "rest.hh"
17 #include "debug.hh"
18 #include "keyitem.hh"
19 #include "clefitem.hh"
20 #include "keyitem.hh"
21 #include "slur.hh"
22 #include "localkeyitem.hh"
23 #include "textitem.hh"
24
25 Rhythmic_grouping
26 parse_grouping(Array<Scalar> a, Moment one_beat)
27 {
28     Array<int> r;
29     for (int i= 0 ; i < a.size(); i++)
30         r.add(a[i]);
31     Moment here =0.0;
32
33     Array<Rhythmic_grouping*> children;
34     for (int i=0; i < r.size(); i++) {
35         
36         Moment last = here;
37         here += one_beat * r[i];
38         children.add(
39             new Rhythmic_grouping(MInterval(last, here), r[i] )
40             );
41     }
42     return Rhythmic_grouping(children);
43 }
44
45 void
46 Simple_walker::do_INTERPRET_command(Command*com)
47 {
48     Array<Scalar> args(com->args);
49     args.del(0);
50     if (com->args[0] == "GROUPING") {   
51         default_grouping = parse_grouping(args,
52                                           col()->tdescription_->one_beat);
53     }else if (com->args[0] == "NEWMEASURE") {
54         local_key_.reset(key_);
55
56     } else if (com->args[0] == "KEY") {
57         
58         if (col()->when() > Moment(0)) {
59             assert(!oldkey_undo);
60             oldkey_undo = new Array<int>( key_.oldkey_undo(args));
61         }
62         
63         typesetkey = key_.read(args);
64         local_key_.reset(key_); 
65     } else if (com->args[0] == "CLEF") {
66         clef_.read(args);
67     } else {
68         WARN << " ignoring INTERPRET command: " << com->args[0]<< '\n';
69     }
70 }
71
72 void
73 Simple_walker::do_TYPESET_command(Command*com)
74 {
75     /* ignore these commands if non-default versions have been
76       processed.  */
77     if (com->args[0] == "CURRENTKEY") 
78         if (processed_key) 
79             return;
80         else
81             com->args[0] = "KEY"; // urgh
82     
83     if (com->args[0] == "CURRENTCLEF") {
84         if (processed_clef) 
85             return;
86     }
87     if (com->args[0] == "BAR") {
88         
89         if (processed_bar_priority > com->priority)
90             return;
91         else
92             processed_bar_priority = com->priority;
93     }
94
95     Item* i = staff()->get_TYPESET_item(com);
96     if (!i)
97         return;
98
99     if (com->args[0] == "KEY") {
100         if (oldkey_undo) {
101             ((Keyitem*) i)->read(*oldkey_undo);
102             delete oldkey_undo;
103             oldkey_undo = 0;
104         }
105         processed_key = true;
106         
107         ((Keyitem*) i)->read(typesetkey); // ugh        
108     }
109
110     if (com->args[0] == "CLEF"||com->args[0] == "CURRENTCLEF") {
111         processed_clef =true;
112         Clef_item*c=(Clef_item*)i;
113         c->read(clef_);
114         c->change = (break_status != BREAK_POST - BREAK_PRE);
115     }
116     col()->typeset_item_directional(i, 1, break_status);
117 }
118
119 void
120 Simple_walker::do_local_key(Note_req*n,Notehead* head_p)
121 {
122     if ( local_key_.oct(n->octave).acc(n->name) != n->accidental) {
123         if (!local_key_item_) {
124             local_key_item_ = staff()->get_local_key_item();
125             local_key_item_->c0_position = clef_.c0_pos;
126         }
127         
128         local_key_item_->add(n->octave, n->name, n->accidental, head_p);
129         local_key_.oct(n->octave).set(n->name, n->accidental);
130     }
131 }
132
133 void
134 Simple_walker::do_note(Note_info n)
135 {
136     Simple_column*c = col();
137     Simple_staff *s = staff();
138         Item*rhythmic=0;
139     if (n.rq->note()) {
140         Note_req * req = n.rq->note() ;
141         const Voice *v = req->elt_l_->voice_;
142
143         Notehead*n = s->get_notehead(req, clef_.c0_pos);
144         rhythmic=n;
145         if (stem_)
146             stem_->add(n);
147         
148         if (current_grouping) {
149             current_grouping->add_child(
150                 c->tdescription_->whole_in_measure, req->duration());
151         }
152         noteheads.add(n);
153         int sidx =find_slur(v);
154         if (sidx >= 0) {
155             pending_slurs[sidx]->add(n);
156         }
157
158         if (wantkey)
159             do_local_key(req,n);
160     }else if (n.rq->rest()) {
161         rhythmic = s->get_rest(n.rq->rest());
162         c->typeset_item(rhythmic);
163     }
164     for (int i= 0; i < n.scripts.size(); i ++)
165         c->typeset_item(new Script(n.scripts[i], rhythmic, 10, stem_)); // UGR
166 }
167
168 void
169 Simple_walker::process_requests()
170 {
171     Simple_column*c = col();
172     Simple_staff *s = staff();
173
174     if (c->beam_&& c->beam_->spantype == Span_req::START) {
175         if (beam_)
176             error("Too many beams (t = "
177                           +String(c->when())+")");
178         beam_ = new Beam;
179         assert(!current_grouping);
180         current_grouping = new Rhythmic_grouping;
181     }
182     
183     for (int i=0; i < c->slurs.size(); i++) {
184         Slur_req*sl = c->slurs[i];
185
186         if (sl->spantype == Span_req::START) {
187             if  (find_slur(sl->elt_l_->voice_ )>=0)
188                 error_t("Too many slurs in voice", col()->when());
189             pending_slur_reqs.add(sl);
190             pending_slurs.add(new Slur);
191         }
192     }
193     
194     if (c->text_) {
195         c->typeset_item(new Text_item(c->text_, 10)); // UGR
196     }
197
198     if (c->stem_) {
199         stem_ = s->get_stem(c->stem_->stem(), c->stem_requester_len);
200     }
201     
202     for (int i = 0; i <  c->notes.size(); i ++)  {
203         do_note(c->notes[i]);
204     }
205     
206     if (beam_) {
207         if (!stem_)
208             WARN <<"beamed note should have a stem (t = " 
209                   <<String(c->when())<<"\n";
210         else
211             beam_->add(stem_);
212
213
214     }
215     if (stem_) {
216         c->typeset_item(stem_);
217         /* needed, otherwise placement of
218            local_key fucks up */
219     }
220
221     if (c->beam_&& c->beam_->spantype == Span_req::STOP) {
222         beam_->set_grouping(default_grouping, *current_grouping);
223         pscore_->typeset_spanner(beam_, s->theline);
224
225         if (c->beam_->nplet) {
226             Text_spanner* t = new Text_spanner(beam_);
227             t->spec.align = 0;
228             t->spec.text = c->beam_->nplet;
229             pscore_->typeset_spanner(t, s->theline);
230         }
231
232         beam_ = 0;
233         delete current_grouping;
234         current_grouping =0;
235     }
236     for (int i = 0; i < noteheads.size(); i++) {
237         c->typeset_item(noteheads[i]);
238     }
239     noteheads.set_size(0);
240  
241     if (local_key_item_) {
242         c->typeset_item_directional(local_key_item_, -1);
243         local_key_item_ = 0;    
244     }
245     if (stem_) {
246         stem_ = 0;
247     }
248     for (int i=0; i < c->slurs.size(); i++) {
249         Slur_req *sl = c->slurs[i];
250
251         if (sl->spantype == Span_req::STOP) {
252             int idx = find_slur(sl->elt_l_->voice_);
253             if (idx < 0)
254                 error_t("can't find slur to end; ", c->when());
255             
256             pscore_->typeset_spanner(pending_slurs[idx],
257                                      s->theline);
258             pending_slurs.del(idx);
259             pending_slur_reqs.del(idx);
260         }       
261     }
262     
263 }
264
265 Simple_walker::Simple_walker(Simple_staff*s)
266     : Staff_walker(s, s->theline->pscore_l_)
267 {
268     stem_ = 0;
269     beam_ =0;
270     oldkey_undo = 0;
271     current_grouping = 0;
272     Local_key_item * i = s->get_local_key_item();
273     wantkey  =i;
274     delete i;
275     local_key_item_ = 0;
276     reset();
277 }
278
279
280
281 Simple_staff*
282 Simple_walker::staff()
283 {
284     return (Simple_staff*) staff_;
285 }
286
287 Simple_column*
288 Simple_walker::col()
289 {
290     return (Simple_column*) *(*this);
291 }
292
293 void
294 Simple_walker::reset()
295 {
296     processed_clef =false;    
297     processed_key = false;
298     processed_bar_priority = 0;
299 }
300
301 int
302 Simple_walker::find_slur(const Voice *v)
303 {
304     for (int i=0; i < pending_slur_reqs.size(); i++) {
305         if (pending_slur_reqs[i]->elt_l_->voice_ == v)
306             return i;
307     }
308     return -1;
309 }
310
311