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