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