]> git.donarmstrong.com Git - lilypond.git/blob - lily/score-elem.cc
868dc3e176340ffec850aa1e5782fc8ed20f0e5a
[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 #include "item.hh"
20 #include "p-col.hh"
21
22 Score_elem*
23 Score_elem::dependency(int i)const
24 {
25     return (Score_elem*) get_out_edge_arr()[i];
26 }
27
28 int
29 Score_elem::dependency_size() const
30 {
31     return get_out_edge_arr().size();
32 }
33
34 Score_elem*
35 Score_elem::dependent(int i) const
36 {
37     return (Score_elem*) get_in_edge_arr()[i];
38 }
39
40 int
41 Score_elem::dependent_size() const
42 {
43     return get_in_edge_arr().size();
44 }
45
46
47 String
48 Score_elem::TeX_string() const
49 {
50     assert( status > POSTCALCED);
51     if (transparent_b_ )
52         return "";
53     String s("\\placebox{%}{%}{%}");
54     Array<String> a;
55     a.push(print_dimen(offset_.y));
56     a.push(print_dimen(offset_.x));
57     a.push( output->TeX_string());
58     return substitute_args(s, a);
59 }
60
61
62 Score_elem::Score_elem(Score_elem const&s)
63 {
64     transparent_b_ = s.transparent_b_;
65     empty_b_ = s.empty_b_;
66     /* called from derived ctor, so most info points to the same deps
67       as (Directed_graph_node&)s. Nobody points to us, so don't copy
68       dependents.      
69      */
70     copy_edges_out(s);
71     x_group_element_i_ = 0;
72     y_group_element_i_ = 0;    
73     status = s.status;
74     assert(!s.output);
75     output = 0;
76     pscore_l_ = s.pscore_l_;
77     offset_ = Offset(0,0);
78 }
79
80 Score_elem::~Score_elem()
81 {
82     // some paranoia to prevent weird segv's
83     assert(status < DELETED);
84     delete output;
85     status = DELETED;
86     output = 0;
87     assert(!x_group_element_i_ && !y_group_element_i_);
88 }
89
90 void
91 Score_elem::translate_x(Real x)
92 {
93     offset_.x += x;
94 }
95
96
97
98 void
99 Score_elem::translate_y(Real y)
100 {
101     offset_.y += y;
102 }
103
104
105 void
106 Score_elem::translate(Offset O)
107 {
108     translate_y(O.y);
109     translate_x(O.x);
110 }
111
112 Interval
113 Score_elem::do_width() const 
114 {
115     Interval r;
116
117     if (!output){
118         Molecule*m = brew_molecule_p();
119         r = m->extent().x;
120         delete m;
121     } else
122         r = output->extent().x;
123     return r;
124 }
125
126 Interval
127 Score_elem::width() const
128 {
129     Interval r=(empty_b_)?Interval(0,0):do_width();
130
131     if (!r.empty_b()) // float exception on DEC Alpha
132         r+=offset_.x;
133
134     return r;
135 }
136
137 Interval
138 Score_elem::do_height() const 
139 {
140     Interval r;
141     if (!output){
142         Molecule*m = brew_molecule_p();
143         r = m->extent().y;
144         delete m;
145     } else
146         r = output->extent().y;
147     return r;
148 }
149
150 Interval
151 Score_elem::height() const
152 {
153     Interval r=(empty_b_)?Interval(0,0): do_height();
154
155     if (!r.empty_b())
156         r+=offset_.y;
157
158   
159     return r;
160 }
161
162 void
163 Score_elem::print()const
164 {
165 #ifndef NPRINT
166     mtor << name() << "{\n";
167     mtor << "dets: " << dependent_size() << "dependencies: " << 
168         dependency_size() << "\n";
169     do_print();
170     if (output)
171         output->print();
172     
173     mtor <<  "}\n";
174 #endif
175 }
176
177
178
179 Score_elem::Score_elem()
180 {
181     transparent_b_ = empty_b_ = false;
182     x_group_element_i_ = 0;
183     y_group_element_i_ =0;
184     pscore_l_=0;
185     offset_ = Offset(0,0);
186     output = 0;
187     status = ORPHAN;
188 }
189
190
191 Paper_def*
192 Score_elem::paper()  const
193 {
194     assert(pscore_l_);
195     return pscore_l_->paper_l_;
196 }
197
198 void
199 Score_elem::add_processing()
200 {
201     if (status >= VIRGIN)
202         return;
203     status = VIRGIN;
204     do_add_processing();
205 }
206
207 void
208 Score_elem::pre_processing()
209 {
210     if (status >= PRECALCED )
211         return;
212
213     assert(status != PRECALCING); // cyclic dependency
214     status = PRECALCING;
215
216     for (int i=0; i < dependency_size(); i++)
217         dependency(i)->pre_processing();
218
219     
220     do_pre_processing();
221     status = PRECALCED;
222 }
223
224 void
225 Score_elem::breakable_col_processing()
226 {
227     if (status >= PREBROKEN )
228         return;
229
230     assert(status != PREBREAKING); // cyclic dependency
231     status = PREBREAKING;
232
233     for (int i=0; i < dependency_size(); i++)
234         dependency(i)->breakable_col_processing();
235
236     
237     do_breakable_col_processing();
238     status = PREBROKEN;
239 }
240
241 void
242 Score_elem::break_processing()
243 {
244     if (status >= BROKEN )
245         return;
246
247     assert(status != BREAKING); // cyclic dependency
248     status = BREAKING;
249
250     for (int i=0; i < dependency_size(); i++)
251         dependency(i)->break_processing();
252
253     
254     do_break_processing();
255     status = BROKEN;
256 }
257
258 void
259 Score_elem::do_break_processing()
260 {
261     handle_broken_dependencies();
262 }
263
264
265 void
266 Score_elem::post_processing()
267 {
268     if (status >= POSTCALCED)
269         return;
270     assert(status != POSTCALCING);// cyclic dependency
271     status=POSTCALCING; 
272
273   
274     for (int i=0; i < dependency_size(); i++)
275         dependency(i)->post_processing();
276     do_post_processing();
277     status=POSTCALCED;
278 }
279
280 void 
281 Score_elem::molecule_processing()
282 {
283     if (status >= OUTPUT)
284         return;
285     status = OUTPUT;            // do it only once.
286   
287     for (int i=0; i < dependency_size(); i++)
288         dependency(i)->molecule_processing();
289
290     if (transparent_b_)
291         return ;
292     output= brew_molecule_p();
293 }
294
295 void
296 Score_elem::do_post_processing()
297 {
298 }
299
300 void
301 Score_elem::do_breakable_col_processing()
302 {
303     handle_prebroken_dependencies();
304 }
305
306 void
307 Score_elem::do_pre_processing()
308 {
309 }
310
311 void
312 Score_elem::do_add_processing()
313 {
314
315 }
316
317 void
318 Score_elem::do_substitute_dependency(Score_elem*,Score_elem*)
319 {
320 }
321
322
323 IMPLEMENT_STATIC_NAME(Score_elem);
324 IMPLEMENT_IS_TYPE_B(Score_elem);
325
326 Molecule*
327 Score_elem::brew_molecule_p()const
328 {
329     Atom a(paper()->lookup_l()->fill(Box(Interval(0,0), Interval(0,0))));
330     return new Molecule (a);
331 }
332 Offset
333 Score_elem::offset() const
334 {
335     return offset_; 
336 }
337
338 Line_of_score *
339 Score_elem::line_l()const
340 {
341     return 0;
342 }
343
344 /********************
345   DEPENDENCIES
346  */
347
348 void
349 Score_elem::remove_dependency(Score_elem*e)
350 {
351     remove_edge_out(e);
352     do_substitute_dependency(e, 0);
353 }
354
355 void
356 Score_elem::add_dependency(Score_elem*e)
357 {
358     Directed_graph_node::add(e);
359 }
360
361
362 void
363 Score_elem::handle_broken_dependencies()
364 {
365     Line_of_score *line  = line_l();
366     if (!line)
367         return;
368
369     Link_array<Score_elem> remove_us_arr;
370     for (int i=0; i < dependency_size(); i++) {
371         Score_elem * elt = dependency(i);
372         if (elt->line_l() != line){ 
373             if (elt->spanner()) {
374                 Spanner * sp = elt->spanner();
375                 Spanner * broken = sp->find_broken_piece(line);
376                 do_substitute_dependency(sp, broken);
377                 add_dependency(broken);
378             } else if (elt->item() && elt->item()->pcol_l_->breakpoint_b()
379                        && elt->item()->break_status_i() == 0) {
380                 Item * my_item = elt->item()->find_prebroken_piece(line);
381                 do_substitute_dependency( elt, my_item);
382                 if (my_item)
383                     add_dependency( my_item);
384             }
385             remove_us_arr.push(elt);
386         } 
387         
388     }
389
390     remove_us_arr.default_sort();
391     remove_us_arr.uniq();
392     for (int i=0;  i <remove_us_arr.size(); i++)
393         remove_dependency(remove_us_arr[i]);
394
395     /* Reset this. If we are a (broken) copy of a spanner, then
396       break_processing() was not called on us (and we are not breaking).  */
397     if (status < BROKEN)
398         status = BROKEN;
399 }
400
401 /*
402   This sux.
403
404   unlike with spanners, the number of items can increase
405
406   span: item1
407
408   becomes
409
410   span: item1 item2 item3
411
412   How to let span (a derived class) know that this happened?
413  */
414 void
415 Score_elem::handle_prebroken_dependencies()
416 {
417     Link_array<Score_elem> remove_us_arr;
418     for (int i=0; i < dependency_size(); i++) {
419         Score_elem * elt = dependency(i);
420         Item *it_l = elt->item();
421         if (it_l && it_l->pcol_l_->breakable_b())
422             if (item()) {
423                 Score_elem *new_l = it_l->find_prebroken_piece(item()->pcol_l_);
424                 if (new_l != elt ) {
425                     do_substitute_dependency( elt, new_l);
426                     remove_us_arr.push(elt);
427                     
428                     add_dependency(new_l);
429                 } 
430             }else {
431                 add_dependency(it_l->broken_to_a_[0]);
432                 add_dependency(it_l->broken_to_a_[1]);          
433             }
434
435     }
436     
437     remove_us_arr.default_sort();
438     remove_us_arr.uniq();
439     for (int i=0;  i <remove_us_arr.size(); i++)
440         remove_dependency(remove_us_arr[i]);
441
442     /*
443       see comment at handle_broken_dependencies()
444      */
445     if (status < PREBROKEN)
446         status = PREBROKEN;
447 }
448
449
450
451 void
452 Score_elem::unlink_all()
453 {
454     for (int i=0; i < dependency_size(); i++) 
455         dependency(i)->unlink_all();
456     junk_links();
457     y_group_element_i_ = 0;
458     x_group_element_i_ = 0;
459 }
460
461 void
462 Score_elem::unlink()
463 {
464     while ( dependency_size()) {
465         do_substitute_dependency(dependency(0),0);
466         remove_edge_out_idx(0);
467     }
468     while  ( dependent_size() ) {
469         dependent(0)->remove_dependency(this);
470     }
471 }
472
473
474
475 void
476 Score_elem::OK()const
477 {
478 #ifndef NDEBUG
479     for (int i=0; i < dependency_size(); i++) {
480         dependency(i)->OK();
481     }
482 #endif
483 }