lilypond-1.1.5
[lilypond.git] / src / simplewalker.cc
blobf99d9f52136445d3b3699854f4910de549daf2c2
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 "misc.hh"
25 Rhythmic_grouping
26 parse_grouping(Array<Scalar> const &a)
28 Array<int> r;
29 Array<Moment> grouplen_arr;
30 for (int i= 0 ; i < a.size()/2; ) {
31 r.push(a[i++]);
32 grouplen_arr.push(Moment(1,(int) a[i++]));
34 Moment here =0;
36 Array<Rhythmic_grouping*> children;
37 for (int i=0; i < r.size(); i++) {
39 Moment last = here;
40 here += grouplen_arr[i] * Rational(r[i]);
41 children.push(
42 new Rhythmic_grouping(MInterval(last, here), r[i] ));
44 return Rhythmic_grouping(children);
49 void
50 Simple_walker::do_INTERPRET_command(Command*com)
52 Array<Scalar> args(com->args);
53 args.del(0);
54 if (com->args[0] == "GROUPING") {
55 default_grouping = parse_grouping(args);
56 }else if (com->args[0] == "NEWMEASURE") {
57 local_key_.reset(key_);
59 } else if (com->args[0] == "KEY") {
61 if (col()->when() > Moment(0)) {
62 assert(!oldkey_undo);
63 oldkey_undo = new Array<int>( key_.oldkey_undo(args));
66 typesetkey = key_.read(args);
67 local_key_.reset(key_);
68 } else if (com->args[0] == "CLEF") {
69 clef_.read(args);
70 } else {
71 WARN << " ignoring INTERPRET command: " << com->args[0]<< '\n';
75 void
76 Simple_walker::do_TYPESET_command(Command*com)
78 /* ignore these commands if non-default versions have been
79 processed. */
80 if (com->args[0] == "CURRENTKEY")
81 if (processed_key)
82 return;
83 else
84 com->args[0] = "KEY"; // urgh
86 if (com->args[0] == "CURRENTCLEF") {
87 if (processed_clef)
88 return;
90 if (com->args[0] == "BAR") {
92 if (processed_bar_priority > com->priority)
93 return;
94 else
95 processed_bar_priority = com->priority;
98 Item* i = staff()->get_TYPESET_item(com);
99 if (!i)
100 return;
102 if (com->args[0] == "KEY") {
103 ((Keyitem*) i)->read(clef_);
104 if (oldkey_undo) {
105 ((Keyitem*) i)->read(*oldkey_undo);
106 delete oldkey_undo;
107 oldkey_undo = 0;
109 processed_key = true;
111 ((Keyitem*) i)->read(typesetkey); // ugh
114 if (com->args[0] == "CLEF"||com->args[0] == "CURRENTCLEF") {
115 processed_clef =true;
116 Clef_item*c=(Clef_item*)i;
117 c->read(clef_);
118 c->change = (break_status != BREAK_POST - BREAK_PRE);
120 col()->typeset_item_directional(i, 1, break_status);
123 void
124 Simple_walker::do_local_key(Note_req*n,Notehead* head_p)
126 if ( local_key_.oct(n->octave).acc(n->notename) != n->accidental) {
127 if (!local_key_item_) {
128 local_key_item_ = staff()->get_local_key_item();
129 local_key_item_->c0_position = clef_.c0_pos;
131 local_key_item_->add(head_p);
132 local_key_item_->add(n->octave, n->notename, n->accidental);
133 local_key_.oct(n->octave).set(n->notename, n->accidental);
137 void
138 Simple_walker::do_note(Note_info n)
140 Simple_column*c = col();
141 Simple_staff *s = staff();
142 Item*rhythmic=0;
143 if (n.rq->note()) {
144 Note_req * req = n.rq->note() ;
145 const Voice *v = req->elt_l_->voice_l_;
147 Notehead*n = s->get_notehead(req, clef_.c0_pos);
148 rhythmic=n;
149 if (stem_)
150 stem_->add(n);
152 if (current_grouping) {
153 current_grouping->add_child(
154 c->tdescription_->whole_in_measure, req->duration());
156 noteheads.push(n);
157 int sidx =find_slur(v);
158 if (sidx >= 0) {
159 pending_slurs[sidx]->add(n);
162 if (wantkey)
163 do_local_key(req,n);
164 } else if (n.rq->rest()) {
165 rhythmic = s->get_rest(n.rq->rest());
166 c->typeset_item(rhythmic);
168 for (int i= 0; i < n.scripts.size(); i ++) {
169 Script * s_p =new Script(n.scripts[i], 10);
170 s_p->set_support(rhythmic);
171 s_p->set_stem(stem_);
172 c->typeset_item(s_p); // UGR
176 void
177 Simple_walker::process_requests()
179 Simple_column*c = col();
180 Simple_staff *s = staff();
182 if (c->beam_ && c->beam_->spantype == Span_req::START) {
183 if (beam_)
184 error("Too many beams (t = " +String(c->when())+")");
185 beam_ = new Beam;
186 assert(!current_grouping);
187 current_grouping = new Rhythmic_grouping;
190 for (int i=0; i < c->slurs.size(); i++) {
191 Slur_req*sl = c->slurs[i];
193 if (sl->spantype == Span_req::START) {
194 if (find_slur(sl->elt_l_->voice_l_)>=0)
195 error( "Too many slurs in voice", sl->defined_ch_c_l_m );
196 pending_slur_reqs.push(sl);
197 pending_slurs.push(new Slur);
201 if (c->text_) {
202 c->typeset_item(new Text_item(c->text_, 10)); // UGR
205 if (c->stem_) {
206 stem_ = s->get_stem(c->stem_->stem());
209 for (int i = 0; i < c->notes.size(); i ++) {
210 do_note(c->notes[i]);
213 if (beam_) {
214 if (!stem_)
215 WARN <<"beamed note should have a stem (t = "
216 <<String(c->when())<<")\n";
217 else
218 beam_->add(stem_);
222 if (stem_) {
223 c->typeset_item(stem_);
224 /* needed, otherwise placement of
225 local_key fucks up */
228 if (c->beam_&& c->beam_->spantype == Span_req::STOP) {
229 if (!beam_) {
230 error( "No beam to end", c->beam_->defined_ch_c_l_m );
232 default_grouping.extend(current_grouping->interval());
233 beam_->set_grouping(default_grouping, *current_grouping);
234 pscore_l_->typeset_spanner(beam_, s->theline_l_);
236 if (c->beam_->nplet) {
237 Text_spanner* t = new Text_spanner;
238 t->set_support(beam_);
239 t->spec.align_i_ = 0;
240 t->spec.text_str_ = c->beam_->nplet;
241 pscore_l_->typeset_spanner(t, s->theline_l_);
244 beam_ = 0;
245 delete current_grouping;
246 current_grouping =0;
248 for (int i = 0; i < noteheads.size(); i++) {
249 c->typeset_item(noteheads[i]);
251 noteheads.set_size(0);
253 if (local_key_item_) {
254 c->typeset_item(local_key_item_);
255 local_key_item_ = 0;
257 if (stem_) {
258 stem_ = 0;
260 for (int i=0; i < c->slurs.size(); i++) {
261 Slur_req *sl = c->slurs[i];
263 if (sl->spantype == Span_req::STOP) {
264 int idx = find_slur(sl->elt_l_->voice_l_);
265 if (idx < 0)
266 error( "can't find slur end", sl->defined_ch_c_l_m );
268 pscore_l_->typeset_spanner(pending_slurs[idx],
269 s->theline_l_);
270 pending_slurs.del(idx);
271 pending_slur_reqs.del(idx);
276 Simple_walker::Simple_walker(Simple_walker const&)
277 : Staff_walker(0, 0)
279 assert(false);
282 Simple_walker::~Simple_walker()
284 if (pending_slurs.size())
285 WARN << "destructing " << pending_slurs.size() << " Pending slurs ";
286 if (beam_)
287 WARN << "destructing Beam\n";
288 if (local_key_item_)
289 WARN<<"destructing Local_key_item\n";
290 if (stem_)
291 WARN<< "destructing Stem\n";
292 delete local_key_item_;
293 delete stem_;
294 delete beam_;
298 Simple_walker::Simple_walker(Simple_staff*s)
299 : Staff_walker(s, s->theline_l_->pscore_l_)
301 stem_ = 0;
302 beam_ =0;
303 oldkey_undo = 0;
304 current_grouping = 0;
305 Local_key_item * i = s->get_local_key_item();
306 wantkey =i;
307 delete i;
308 local_key_item_ = 0;
309 do_post_move();
314 Simple_staff*
315 Simple_walker::staff()
317 return (Simple_staff*) staff_l_;
320 Simple_column*
321 Simple_walker::col()
323 return (Simple_column*) *(*this);
326 void
327 Simple_walker::do_post_move()
329 processed_clef =false;
330 processed_key = false;
331 processed_bar_priority = 0;
335 Simple_walker::find_slur(const Voice *v)
337 for (int i=0; i < pending_slur_reqs.size(); i++) {
338 if (pending_slur_reqs[i]->elt_l_->voice_l_== v)
339 return i;
341 return -1;