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