]> git.donarmstrong.com Git - lilypond.git/blob - lily/p-score.cc
patch::: 0.0.75.jcn4: midi op
[lilypond.git] / lily / p-score.cc
1 /*
2   p-score.cc -- implement PScore
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1996, 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8
9 #include "super-elem.hh"
10 #include "idealspacing.hh"
11 #include "debug.hh"
12 #include "lookup.hh"
13 #include "spanner.hh"
14 #include "paper-def.hh"
15 #include "scoreline.hh"
16 #include "p-score.hh"
17 #include "tex-stream.hh"
18 #include "break.hh"
19 #include "p-col.hh"
20
21 PScore::PScore(Paper_def*p)
22 {
23     paper_l_ = p;
24     super_elem_l_   = new Super_elem;
25     typeset_element(super_elem_l_);
26 }
27
28 PScore::~PScore()
29 {
30     super_elem_l_->unlink_all();
31 }
32
33 void
34 PScore::typeset_element(Score_elem * elem_p)
35 {
36     elem_p_list_.bottom().add(elem_p);
37     elem_p->pscore_l_ = this;
38
39     elem_p->add_processing();
40 }
41
42 void
43 PScore::typeset_item(Item *i, PCol *c, int breakstat)
44 {
45     assert(c && i);
46
47     if (breakstat == -1) {
48         typeset_item(i, c->prebreak_p_);
49         return;
50     }
51
52     if (breakstat == 1) {
53         typeset_item(i, c->postbreak_p_);
54         return;
55     }
56
57     c->add(i);
58     typeset_element(i);
59 }
60
61 void
62 PScore::typeset_broken_spanner(Spanner*span_p)
63 {
64     span_p->left_col_l_->starters.bottom().add (span_p);
65     span_p->right_col_l_->stoppers.bottom().add(span_p);
66     assert(span_p->left_col_l_->line_l_ == span_p->right_col_l_->line_l_);
67
68     typeset_element(span_p);
69 }
70
71
72 void
73 PScore::typeset_unbroken_spanner(Spanner*span_p)
74 {
75     spanners.bottom().add(span_p);
76     span_p->pscore_l_=this;
77
78     if (     span_p->left_col_l_) 
79         span_p->left_col_l_->used_b_ = true;
80     if ( span_p->right_col_l_)
81         span_p->right_col_l_->used_b_ = true;
82     
83     // do not init start/stop fields. These are for broken spans only.
84     span_p->add_processing();
85 }
86
87 Idealspacing*
88 PScore::get_spacing(PCol*l, PCol*r)
89 {
90     assert(l!=r);
91
92     Idealspacing*i_p =new Idealspacing(l,r);
93     suz.bottom().add(i_p);
94
95     return i_p;
96 }
97
98
99 void
100 PScore::clean_cols()
101 {
102     int rank_i = 0;
103     for (iter_top(cols,c); c.ok(); )
104         if (!c->used_b()) {
105             delete c.remove_p();
106         } else {
107             c->set_rank(rank_i++);
108             c++;
109         }
110 }
111
112 void
113 PScore::do_connect(PCol *c1, PCol *c2, Real d, Real h)
114 {
115     if (!c1 || !c2 )
116         return;
117     Idealspacing*s_l=get_spacing(c1,c2);
118
119     
120     s_l->hooke = h;
121     s_l->space =d;
122 }
123
124 void
125 PScore::connect(PCol* c1, PCol *c2, Real d, Real h)
126 {
127     do_connect(c1,c2,d,h);
128     do_connect(c1->postbreak_p_, c2,d,h);
129     do_connect(c1, c2->prebreak_p_,d,h);
130     do_connect(c1->postbreak_p_, c2->prebreak_p_,d,h);
131 }
132
133 void
134 PScore::add(PCol *p)
135 {
136     p->pscore_l_ = this;
137     if (p->breakable_b()){
138         p->prebreak_p_->pscore_l_ = this;
139         p->postbreak_p_->pscore_l_ = this;
140     }
141     cols.bottom().add(p);
142 }
143
144 void
145 PScore::output(Tex_stream &ts)
146 {
147     ts << "\n "<<  paper_l_->lookup_l()->texsetting << "%(Tex id)\n";
148     ts<< super_elem_l_->TeX_string();
149     ts << "\n\\EndLilyPondOutput";
150 }
151
152
153 void
154 PScore::OK()const
155 {
156 #ifndef NDEBUG
157     for (iter_top(cols,cc); cc.ok(); cc++)
158         cc->OK();
159     for (iter_top(suz,i); i.ok(); i++)
160         i->OK();
161 #endif
162 }
163
164 void
165 PScore::print() const
166 {    
167 #ifndef NPRINT
168     mtor << "PScore { ";
169     paper_l_->print();
170     mtor << "\n elements: ";
171     for (iter_top(elem_p_list_,cc); cc.ok(); cc++)      
172         cc->print();
173     mtor << "\n unbroken spanners: ";
174     for (iter(spanners.top(), i); i.ok(); i++)
175         i->print();
176     mtor << "\ncolumns: ";
177      for (iter_top(cols,cc); cc.ok(); cc++)
178         cc->print();
179     
180     mtor << "\nideals: ";
181     for (iter_top(suz,i); i.ok(); i++)
182         i->print();
183     mtor << "}\n";
184 #endif 
185 }
186
187 void
188 PScore::preprocess()
189 {
190     super_elem_l_->breakable_col_processing();
191     super_elem_l_->pre_processing();
192 }
193
194 void
195 PScore::postprocess()
196 {
197     super_elem_l_->post_processing();
198     super_elem_l_->molecule_processing();
199 }
200
201 PCursor<PCol *>
202 PScore::find_col(PCol const *c)const
203 {
204     PCol const *what = c;
205     if (what->daddy_l_ )
206         what = what->daddy_l_;
207     
208     return cols.find((PCol*)what);
209 }
210
211
212 void
213 PScore::set_breaking(Array<Col_hpositions> const &breaking)
214 {
215     super_elem_l_->line_of_score_l_->set_breaking( breaking);
216     super_elem_l_->break_processing();
217
218
219     for (iter(spanners.top(),i); i.ok(); ) {
220         Spanner *span_p = i.remove_p();
221         if (span_p->broken_b()) {
222             span_p->unlink();
223             delete span_p;
224         }else{
225             typeset_broken_spanner(span_p);
226         }
227     }
228     for (iter(elem_p_list_.top(),i ); i.ok() ;) {
229         Item *i_l =i->item();
230         if ( i_l && !i_l->pcol_l_->line_l_) {
231             i_l->unlink();
232             delete i.remove_p();
233         } else
234             i++;
235     }
236
237     for (iter_top(cols, i); i.ok(); i++)
238         i->clean_breakable_items();
239 }
240
241 void
242 PScore::calc_breaking()
243 {
244     Word_wrap w(*this);
245     set_breaking(w.solve());
246 }
247
248 void
249 PScore::process()
250 {
251     clean_cols();
252     print();
253     *mlog << "Preprocessing elements... " <<flush;
254     preprocess();
255     *mlog << "\nCalculating column positions ... " <<flush;
256     calc_breaking();
257     *mlog << "\nPostprocessing elements..." << endl;
258     postprocess();
259 }
260
261 /** Get all breakable columns between l and r, (not counting l and r).  */
262 Link_array<PCol>
263 PScore::breakable_col_range(PCol*l,PCol*r)const
264 {
265     Link_array<PCol> ret;
266
267     PCursor<PCol*> start(l ? find_col(l)+1 : cols.top() );
268     PCursor<PCol*> stop(r ? find_col(r) : cols.bottom());
269
270     /*
271       ugh! windows-suck-suck-suck.
272      */
273     while ( PCursor<PCol*>::compare(start,stop) < 0 ) {
274         if (start->breakable_b())
275             ret.push(start);
276         start++;
277     }
278
279     return ret;
280 }
281 Link_array<PCol>
282 PScore::col_range(PCol*l,PCol*r)const
283 {
284     Link_array<PCol> ret;
285     
286     PCursor<PCol*> start(l ? find_col(l)+1 : cols.top() );
287     PCursor<PCol*> stop(r ? find_col(r) : cols.bottom());
288     ret.push(l);
289     
290     /*
291       ugh! windows-suck-suck-suck.
292      */
293     while ( PCursor<PCol*>::compare(start,stop) < 0 )
294         ret.push(start++);
295     ret.push(r);
296     return ret;
297 }
298
299 Link_array<PCol>
300 PScore::broken_col_range(PCol*l,PCol*r)const
301 {
302     Link_array<PCol> ret;
303
304     PCursor<PCol*> start(l ? find_col(l)+1 : cols.top() );
305     PCursor<PCol*> stop(r ? find_col(r) : cols.bottom());
306   
307     /*
308       ugh! windows-suck-suck-suck.
309       */
310     while ( PCursor<PCol*>::compare(start,stop) < 0 ) {
311         if (start->breakable_b() && !start->line_l_ )
312             ret.push(start);
313         start++;
314     }
315
316     return ret;
317 }