]> git.donarmstrong.com Git - lilypond.git/blob - lily/p-score.cc
release: 0.0.60
[lilypond.git] / lily / p-score.cc
1 #include "idealspacing.hh"
2 #include "debug.hh"
3 #include "lookup.hh"
4 #include "spanner.hh"
5 #include "paper-def.hh"
6 #include "molecule.hh"
7 #include "dimen.hh"
8 #include "scoreline.hh"
9 #include "p-score.hh"
10 #include "tex-stream.hh"
11 #include "item.hh"
12 #include "break.hh"
13
14 Idealspacing*
15 PScore::get_spacing(PCol*l, PCol*r)
16 {
17     assert(l!=r);
18
19     Idealspacing*i_p =new Idealspacing(l,r);
20     suz.bottom().add(i_p);
21
22     return i_p;
23 }
24
25
26 void
27 PScore::clean_cols()
28 {
29     int rank_i = 0;
30     for (iter_top(cols,c); c.ok(); )
31         if (!c->used_b()) {
32             delete c.remove_p();
33         } else {
34             c->set_rank(rank_i++);
35             c++;
36         }
37     
38 }
39
40
41 void
42 PScore::add(PStaff *s)
43 {
44     assert(s->pscore_l_ == this);
45     staffs.bottom().add(s);
46 }
47
48
49 void
50 PScore::do_connect(PCol *c1, PCol *c2, Real d, Real h)
51 {
52     if (!c1 || !c2 )
53         return;
54     Idealspacing*s_l=get_spacing(c1,c2);
55
56     
57     s_l->hooke = h;
58     s_l->space =d;
59 }
60
61 void
62 PScore::connect(PCol* c1, PCol *c2, Real d, Real h)
63 {
64     do_connect(c1,c2,d,h);
65     do_connect(c1->postbreak_p_, c2,d,h);
66     do_connect(c1, c2->prebreak_p_,d,h);
67     do_connect(c1->postbreak_p_, c2->prebreak_p_,d,h);
68 }
69
70 void
71 PScore::typeset_item(Item *i, PCol *c, PStaff *s, int breakstat)
72 {
73     assert(c && i && s);
74
75     if (breakstat == 0) {
76         typeset_item(i, c->prebreak_p_, s);
77         return;
78     }
79
80     if (breakstat == 2) {
81         typeset_item(i, c->postbreak_p_, s);
82         return;
83     }
84
85
86     its.bottom().add(i);
87     s->add(i);
88     c->add(i);
89
90     /* first do this, because i->width() may follow the 0-pointer */
91     i->add_processing();    
92 }
93
94 void
95 PScore::typeset_spanner(Spanner*span_p, PStaff*ps)
96 {
97     span_p->pstaff_l_ = ps;
98     spanners.bottom().add(span_p);
99     ps->spans.bottom().add(span_p);
100
101     // do not init start/stop fields. These are for broken spans only.
102     span_p->add_processing();
103 }
104
105
106 void
107 PScore::add(PCol *p)
108 {
109     p->pscore_l_ = this;
110     if (p->breakable_b()){
111         p->prebreak_p_->pscore_l_ = this;
112         p->postbreak_p_->pscore_l_ = this;
113     }
114     cols.bottom().add(p);
115 }
116
117 PScore::PScore( Paper_def*p)
118 {
119     paper_l_ = p;
120 }
121
122 void
123 PScore::output(Tex_stream &ts)
124 {
125     int l=1;
126
127     ts << "\n "<<  paper_l_->lookup_l()->texsetting << "%(Tex id)\n";
128     for (iter_top(lines,lic); lic.ok(); lic++) {
129         ts << "% line of score no. " << l++ <<"\n";
130         ts << lic->TeXstring();
131         if ((lic+1).ok())
132             ts << "\\interscoreline\n";
133     }   
134     ts << "\n\\EndLilyPondOutput";
135 }
136
137
138 Array<Item*>
139 PScore::select_items(PStaff*ps, PCol*pc)
140 {
141     Array<Item*> ret;
142     assert(ps && pc);
143     for (iter_top(pc->its,i); i.ok(); i++){
144         if (i->pstaff_l_ == ps)
145             ret.push((Item*)(Item const *)i);
146     }
147     return ret;
148 }
149
150 void
151 PScore::OK()const
152 {
153 #ifdef NDEBUG
154     for (iter_top(cols,cc); cc.ok(); cc++)
155         cc->OK();
156     for (iter_top(suz,i); i.ok(); i++)
157         i->OK();
158 #endif
159 }
160
161 void
162 PScore::print() const
163 {    
164 #ifndef NPRINT
165     mtor << "PScore { ";
166     paper_l_->print();
167     mtor << "\ncolumns: ";
168     for (iter_top(cols,cc); cc.ok(); cc++)
169         cc->print();
170     
171     mtor << "\nideals: ";
172     for (iter_top(suz,i); i.ok(); i++)
173         i->print();
174     mtor << "}\n";
175 #endif 
176 }
177
178 void
179 PScore::preprocess()
180 {
181     for (iter_top(spanners,i); i.ok(); i++) {
182         i->pre_processing();
183     }
184     for (iter_top(its,i); i.ok(); i++){
185         i->pre_processing();
186     }
187 }
188
189 void
190 PScore::postprocess()
191 {
192     for (iter_top(broken_spans,i); i.ok(); i++) { // could chase spans as well.
193         i->post_processing();
194     }
195     for (iter_top(its,i); i.ok(); i++){
196         i->post_processing();
197     }
198     
199     for (iter_top(broken_spans,i); i.ok(); i++) {
200         i->molecule_processing();
201     }
202     for (iter_top(its,i); i.ok(); i++){
203         i->molecule_processing();
204     }
205
206     for (iter_top(lines,i); i.ok(); i++)
207         i->process();
208
209 }
210
211 PCursor<PCol *>
212 PScore::find_col(PCol const *c)const
213 {
214     PCol const *what = c;
215     if (what->daddy_l_ )
216         what = what->daddy_l_;
217     
218     return cols.find((PCol*)what);
219 }
220
221 void
222 PScore::add_broken(Spanner*s)
223 {
224     assert(s->left_col_l_->line_l_ == s->right_col_l_->line_l_);
225     broken_spans.bottom().add(s);
226     s->left_col_l_->starters.bottom().add (s);
227     s->right_col_l_->stoppers.bottom().add (s);
228 }
229
230 void
231 PScore::set_breaking(Array<Col_hpositions> breaking)
232 {
233     for (int j=0; j < breaking.size(); j++) {
234         Array<PCol*> &curline(breaking[j].cols);
235         Array<Real> &config(breaking[j].config);
236         
237         Line_of_score *s_p = new Line_of_score(curline,this);
238         lines.bottom().add(s_p);        
239         for (int i=0; i < curline.size(); i++){
240             curline[i]->hpos = config[i];
241         }
242     }
243 }
244
245 void
246 PScore::calc_breaking()
247 {
248     Word_wrap w(*this);
249     set_breaking(w.solve());
250 }
251
252 void
253 PScore::process()
254 {
255     clean_cols();
256     print();
257     *mlog << "Preprocessing elements... " <<flush;
258     preprocess();
259     *mlog << "\nCalculating column positions ... " <<flush;
260     calc_breaking();
261     *mlog << "\nPostprocessing elements..." << endl;
262     postprocess();
263 }