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