]> git.donarmstrong.com Git - lilypond.git/blob - lily/score-elem.cc
release: 0.0.66
[lilypond.git] / lily / score-elem.cc
1 /*
2   score-elem.cc -- implement Score_elem
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8
9 #include "p-score.hh"
10 #include "paper-def.hh"
11 #include "lookup.hh"
12 #include "molecule.hh"
13 #include "score-elem.hh"
14 #include "debug.hh"
15 #include "tex.hh"
16 #include "dimen.hh"
17 #include "spanner.hh"
18 #include "scoreline.hh"
19
20 Score_elem*
21 Score_elem::dependency(int i)const
22 {
23     return (Score_elem*) get_out_edge_arr()[i];
24 }
25
26 int
27 Score_elem::dependency_size() const
28 {
29     return get_out_edge_arr().size();
30 }
31
32 Score_elem*
33 Score_elem::dependent(int i) const
34 {
35     return (Score_elem*) get_in_edge_arr()[i];
36 }
37
38 int
39 Score_elem::dependent_size() const
40 {
41     return get_in_edge_arr().size();
42 }
43
44
45 String
46 Score_elem::TeX_string() const
47 {
48     assert( status > POSTCALCED);
49     String s("\\placebox{%}{%}{%}");
50     Array<String> a;
51     a.push(print_dimen(offset_.y));
52     a.push(print_dimen(offset_.x));
53     a.push( output->TeX_string());
54     return substitute_args(s, a);
55 }
56
57
58 Score_elem::Score_elem(Score_elem const&s)
59 {
60     /* called from derived ctor, so most info points to the same deps
61       as (Directed_graph_node&)s. Nobody points to us, so don't copy
62       dependents.      
63      */
64     copy_edges_out(s);
65     group_element_i_ = 0;
66     status = s.status;
67     assert(!s.output);
68     output = 0;
69     pscore_l_ = s.pscore_l_;
70     offset_ = Offset(0,0);
71 }
72
73 Score_elem::~Score_elem()
74 {
75     // some paranoia to prevent weird segv's
76     assert(status < DELETED);
77     delete output;
78     status = DELETED;
79     output = 0;
80     assert(!group_element_i_ );
81 }
82
83 void
84 Score_elem::translate(Offset O)
85 {
86     offset_ += O;
87 }
88
89 Interval
90 Score_elem::do_width() const 
91 {
92     Interval r;
93     
94     if (!output){
95         Molecule*m = brew_molecule_p();
96         r = m->extent().x;
97         delete m;
98     } else
99         r = output->extent().x;
100     return r;
101 }
102
103 Interval
104 Score_elem::width() const
105 {
106     Interval r=do_width();
107
108     if (!r.empty_b()) // float exception on DEC Alpha
109         r+=offset_.x;
110
111     return r;
112 }
113
114 Interval
115 Score_elem::do_height() const 
116 {
117     Interval r;
118     if (!output){
119         Molecule*m = brew_molecule_p();
120         r = m->extent().y;
121         delete m;
122     } else
123         r = output->extent().y;
124     return r;
125 }
126
127 Interval
128 Score_elem::height() const
129 {
130     Interval r=do_height();
131
132     if (!r.empty_b())
133         r+=offset_.y;
134
135   
136     return r;
137 }
138
139 void
140 Score_elem::print()const
141 {
142 #ifndef NPRINT
143     mtor << name() << "{\n";
144     mtor << "deps: " << dependent_size() << "depts: \n" << 
145         dependency_size() << "\n";
146     do_print();
147     if (output)
148         output->print();
149     
150     mtor <<  "}\n";
151 #endif
152 }
153
154
155
156 Score_elem::Score_elem()
157 {
158     group_element_i_ = 0;
159     pscore_l_=0;
160     offset_ = Offset(0,0);
161     output = 0;
162     status = ORPHAN;
163 }
164
165
166 Paper_def*
167 Score_elem::paper()  const
168 {
169     assert(pscore_l_);
170     return pscore_l_->paper_l_;
171 }
172
173 void
174 Score_elem::add_processing()
175 {
176     if (status >= VIRGIN)
177         return;
178     status = VIRGIN;
179     do_add_processing();
180 }
181
182 void
183 Score_elem::pre_processing()
184 {
185     if (status >= PRECALCED )
186         return;
187
188     assert(status != PRECALCING); // cyclic dependency
189     status = PRECALCING;
190
191     for (int i=0; i < dependency_size(); i++)
192         dependency(i)->pre_processing();
193
194     
195     do_pre_processing();
196     status = PRECALCED;
197 }
198
199 void
200 Score_elem::break_processing()
201 {
202     if (status >= BROKEN )
203         return;
204
205     assert(status != BREAKING); // cyclic dependency
206     status = BREAKING;
207
208     for (int i=0; i < dependency_size(); i++)
209         dependency(i)->break_processing();
210
211     
212     do_break_processing();
213     status = BROKEN;
214 }
215
216 void
217 Score_elem::do_break_processing()
218 {
219     handle_broken_dependencies();
220 }
221
222
223 void
224 Score_elem::post_processing()
225 {
226     if (status >= POSTCALCED)
227         return;
228     assert(status != POSTCALCING);// cyclic dependency
229     status=POSTCALCING; 
230
231   
232     for (int i=0; i < dependency_size(); i++)
233         dependency(i)->post_processing();
234     do_post_processing();
235     status=POSTCALCED;
236 }
237
238 void 
239 Score_elem::molecule_processing()
240 {
241     if (status >= OUTPUT)
242         return;
243     status = OUTPUT;            // do it only once.
244   
245     for (int i=0; i < dependency_size(); i++)
246         dependency(i)->molecule_processing();
247
248     output= brew_molecule_p();
249 }
250
251 void
252 Score_elem::do_post_processing()
253 {
254 }
255
256 void
257 Score_elem::do_pre_processing()
258 {
259 }
260
261 void
262 Score_elem::do_add_processing()
263 {
264
265 }
266
267 void
268 Score_elem::do_substitute_dependency(Score_elem*,Score_elem*)
269 {
270 }
271
272
273 IMPLEMENT_STATIC_NAME(Score_elem);
274
275 Molecule*
276 Score_elem::brew_molecule_p()const
277 {
278     Atom a(paper()->lookup_l()->fill(Box(Interval(0,0), Interval(0,0))));
279     return new Molecule (a);
280 }
281 Offset
282 Score_elem::offset() const
283 {
284     return offset_; 
285 }
286
287 Line_of_score *
288 Score_elem::line_l()const
289 {
290     return 0;
291 }
292
293 /********************
294   DEPENDENCIES
295  */
296
297 void
298 Score_elem::remove_dependency(Score_elem*e)
299 {
300     remove_edge_out(e);
301     do_substitute_dependency(e, 0);
302 }
303
304 void
305 Score_elem::add_dependency(Score_elem*e)
306 {
307     Directed_graph_node::add(e);
308 }
309
310 bool
311 Score_elem::is_type_b(char const *s)
312 {
313     return s == static_name();
314 }
315
316 void
317 Score_elem::handle_broken_dependencies()
318 {
319     Line_of_score *line  = line_l();
320     if (!line)
321         return;
322
323     Link_array<Score_elem> remove_us_arr;
324     for (int i=0; i < dependency_size(); i++) {
325         Score_elem * elt = dependency(i);
326         if (elt->line_l() != line){ 
327             if (elt->spanner()) {
328                 Spanner * sp = elt->spanner();
329                 Spanner * broken = sp->find_broken_piece(line);
330                 do_substitute_dependency(sp, broken);
331                 add_dependency(broken);
332                 remove_us_arr.push(sp);
333             }
334             remove_us_arr.push(elt);
335         } 
336         
337     }
338
339     remove_us_arr.default_sort();
340     remove_us_arr.uniq();
341     for (int i=0;  i <remove_us_arr.size(); i++)
342         remove_dependency(remove_us_arr[i]);
343
344     if (status < BROKEN)
345         status = BROKEN;
346 }
347
348
349 void
350 Score_elem::unlink_all()
351 {
352     for (int i=0; i < dependency_size(); i++) 
353         dependency(i)->unlink_all();
354     junk_links();
355     group_element_i_ = 0;
356 }
357
358 void
359 Score_elem::unlink()
360 {
361     while ( dependency_size()) {
362         do_substitute_dependency(dependency(0),0);
363         remove_edge_out_idx(0);
364     }
365     while  ( dependent_size() ) {
366         dependent(0)->remove_dependency(this);
367     }
368 }
369
370
371
372 void
373 Score_elem::OK()const
374 {
375 #ifndef NDEBUG
376     for (int i=0; i < dependency_size(); i++) {
377         dependency(i)->OK();
378     }
379 #endif
380 }