]> git.donarmstrong.com Git - lilypond.git/blob - src/simplewalker.cc
release: 0.0.25
[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 "slur.hh"
21 #include "localkeyitem.hh"
22 #include "textitem.hh"
23 #include "lyricitem.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         ((Keyitem*) i)->read(clef_);
101         if (oldkey_undo) {
102             ((Keyitem*) i)->read(*oldkey_undo);
103             delete oldkey_undo;
104             oldkey_undo = 0;
105         }
106         processed_key = true;
107         
108         ((Keyitem*) i)->read(typesetkey); // ugh        
109     }
110
111     if (com->args[0] == "CLEF"||com->args[0] == "CURRENTCLEF") {
112         processed_clef =true;
113         Clef_item*c=(Clef_item*)i;
114         c->read(clef_);
115         c->change = (break_status != BREAK_POST - BREAK_PRE);
116     }
117     col()->typeset_item_directional(i, 1, break_status);
118 }
119
120 void
121 Simple_walker::do_local_key(Note_req*n,Notehead* head_p)
122 {
123     if ( local_key_.oct(n->octave).acc(n->name) != n->accidental) {
124         if (!local_key_item_) {
125             local_key_item_ = staff()->get_local_key_item();
126             local_key_item_->c0_position = clef_.c0_pos;
127         }
128         
129         local_key_item_->add(n->octave, n->name, n->accidental, head_p);
130         local_key_.oct(n->octave).set(n->name, n->accidental);
131     }
132 }
133
134 void
135 Simple_walker::do_note(Note_info n)
136 {
137     Simple_column*c = col();
138     Simple_staff *s = staff();
139         Item*rhythmic=0;
140     if (n.rq->note()) {
141         Note_req * req = n.rq->note() ;
142         const Voice *v = req->elt_l_->voice_;
143
144         Notehead*n = s->get_notehead(req, clef_.c0_pos);
145         rhythmic=n;
146         if (stem_)
147             stem_->add(n);
148         
149         if (current_grouping) {
150             current_grouping->add_child(
151                 c->tdescription_->whole_in_measure, req->duration());
152         }
153         noteheads.add(n);
154         int sidx =find_slur(v);
155         if (sidx >= 0) {
156             pending_slurs[sidx]->add(n);
157         }
158
159         if (wantkey)
160             do_local_key(req,n);
161     }else if (n.rq->rest()) {
162         rhythmic = s->get_rest(n.rq->rest());
163         c->typeset_item(rhythmic);
164     }
165     for (int i= 0; i < n.scripts.size(); i ++)
166         c->typeset_item(new Script(n.scripts[i], rhythmic, 10, stem_)); // UGR
167 }
168
169 void
170 Simple_walker::process_requests()
171 {
172     Simple_column*c = col();
173     Simple_staff *s = staff();
174
175     if (c->beam_&& c->beam_->spantype == Span_req::START) {
176         if (beam_)
177             error("Too many beams (t = "
178                           +String(c->when())+")");
179         beam_ = new Beam;
180         assert(!current_grouping);
181         current_grouping = new Rhythmic_grouping;
182     }
183     
184     for (int i=0; i < c->slurs.size(); i++) {
185         Slur_req*sl = c->slurs[i];
186
187         if (sl->spantype == Span_req::START) {
188             if  (find_slur(sl->elt_l_->voice_ )>=0)
189                 error_t("Too many slurs in voice", *col()->tdescription_);
190             pending_slur_reqs.add(sl);
191             pending_slurs.add(new Slur);
192         }
193     }
194     
195     if (c->text_) {
196         c->typeset_item(new Text_item(c->text_, 10)); // UGR
197     }
198
199 //    if (c->lreq_p_) {
200 //      c->typeset_item(new Lyric_item(c->lreq_p_, 10)); // UGR
201 //    }
202
203     if (c->stem_) {
204         stem_ = s->get_stem(c->stem_->stem(), c->stem_requester_len);
205     }
206     
207     for (int i = 0; i <  c->notes.size(); i ++)  {
208         do_note(c->notes[i]);
209     }
210     
211     if (beam_) {
212         if (!stem_)
213             WARN <<"beamed note should have a stem (t = " 
214                   <<String(c->when())<<")\n";
215         else
216             beam_->add(stem_);
217
218
219     }
220     if (stem_) {
221         c->typeset_item(stem_);
222         /* needed, otherwise placement of
223            local_key fucks up */
224     }
225
226     if (c->beam_&& c->beam_->spantype == Span_req::STOP) {
227         default_grouping.extend(current_grouping->interval());
228         beam_->set_grouping(default_grouping, *current_grouping);
229         pscore_->typeset_spanner(beam_, s->theline_l_);
230
231         if (c->beam_->nplet) {
232             Text_spanner* t = new Text_spanner(beam_);
233             t->spec.align_i_ = 0;
234             t->spec.text_str_ = c->beam_->nplet;
235             pscore_->typeset_spanner(t, s->theline_l_);
236         }
237
238         beam_ = 0;
239         delete current_grouping;
240         current_grouping =0;
241     }
242     for (int i = 0; i < noteheads.size(); i++) {
243         c->typeset_item(noteheads[i]);
244     }
245     noteheads.set_size(0);
246  
247     if (local_key_item_) {
248         c->typeset_item_directional(local_key_item_, -1);
249         local_key_item_ = 0;    
250     }
251     if (stem_) {
252         stem_ = 0;
253     }
254     for (int i=0; i < c->slurs.size(); i++) {
255         Slur_req *sl = c->slurs[i];
256
257         if (sl->spantype == Span_req::STOP) {
258             int idx = find_slur(sl->elt_l_->voice_);
259             if (idx < 0)
260                 error_t("can't find slur to end; ", *c->tdescription_);
261             
262             pscore_->typeset_spanner(pending_slurs[idx],
263                                      s->theline_l_);
264             pending_slurs.del(idx);
265             pending_slur_reqs.del(idx);
266         }       
267     }
268     
269 }
270
271 Simple_walker::Simple_walker(Simple_staff*s)
272     : Staff_walker(s, s->theline_l_->pscore_l_)
273 {
274     stem_ = 0;
275     beam_ =0;
276     oldkey_undo = 0;
277     current_grouping = 0;
278     Local_key_item * i = s->get_local_key_item();
279     wantkey  =i;
280     delete i;
281     local_key_item_ = 0;
282     reset();
283 }
284
285
286
287 Simple_staff*
288 Simple_walker::staff()
289 {
290     return (Simple_staff*) staff_;
291 }
292
293 Simple_column*
294 Simple_walker::col()
295 {
296     return (Simple_column*) *(*this);
297 }
298
299 void
300 Simple_walker::reset()
301 {
302     processed_clef =false;    
303     processed_key = false;
304     processed_bar_priority = 0;
305 }
306
307 int
308 Simple_walker::find_slur(const Voice *v)
309 {
310     for (int i=0; i < pending_slur_reqs.size(); i++) {
311         if (pending_slur_reqs[i]->elt_l_->voice_ == v)
312             return i;
313     }
314     return -1;
315 }
316
317