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