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