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