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