]> git.donarmstrong.com Git - lilypond.git/blob - lily/score-element.cc
release: 1.1.29
[lilypond.git] / lily / score-element.cc
1 /*
2   score-elem.cc -- implement Score_element
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9
10 #include <string.h>
11
12 #include "p-score.hh"
13 #include "paper-def.hh"
14 #include "lookup.hh"
15 #include "molecule.hh"
16 #include "score-element.hh"
17 #include "debug.hh"
18 #include "spanner.hh"
19 #include "line-of-score.hh"
20 #include "item.hh"
21 #include "p-col.hh"
22 #include "molecule.hh"
23 #include "misc.hh"
24 #include "paper-outputter.hh"
25
26 Score_element::Score_element()
27 {
28   output_p_ =0;
29   transparent_b_ = false;
30   size_i_ = 0;
31   pscore_l_=0;
32   status_i_ = 0;
33 }
34
35 Score_element::Score_element (Score_element const&s)
36   :  Directed_graph_node (s), Graphical_element (s)
37 {
38   /* called from derived ctor, so most info points to the same deps
39      as (Directed_graph_node&)s. Nobody points to us, so don't copy
40      dependents.      
41    */
42   copy_edges_out (s);
43   output_p_ =0;
44   transparent_b_ = s.transparent_b_;
45   status_i_ = s.status_i_;
46   pscore_l_ = s.pscore_l_;
47   size_i_ = s.size_i_;
48 }
49
50
51   
52
53 Score_element::~Score_element()
54 {
55   delete output_p_; 
56   assert (status_i_ >=0);
57 }
58
59 Score_element*
60 Score_element::dependency (int i) const
61 {
62   return (Score_element*) (get_out_edge_arr ()[i]);
63 }
64
65 int
66 Score_element::dependency_size () const
67 {
68   return get_out_edge_arr ().size ();
69 }
70
71 Score_element*
72 Score_element::dependent (int i) const
73 {
74   return (Score_element *)( get_in_edge_arr()[i]);
75 }
76
77 int
78 Score_element::dependent_size() const
79 {
80   return get_in_edge_arr().size ();
81 }
82
83
84
85 Interval
86 Score_element::do_width() const 
87 {
88   Interval r;
89
90   Molecule*m = output_p_ ?  output_p_ : do_brew_molecule_p();
91   r = m->extent().x ();
92
93   if (!output_p_)
94     delete m;
95   
96   return r;
97 }
98
99 Interval
100 Score_element::do_height() const 
101 {
102   Interval r;
103   Molecule*m = output_p_ ?  output_p_ : do_brew_molecule_p();
104   r = m->extent().y ();
105   if (!output_p_)
106     delete m;
107
108   return r;
109 }
110
111
112 /*
113   STANDARD METHS
114  */
115 void
116 Score_element::print() const
117 {
118 #ifndef NPRINT
119   DOUT << classname(this) << "{\n";
120   DOUT << "dets: " << dependent_size() << "dependencies: " << 
121     dependency_size();
122  
123   Graphical_element::do_print ();
124   do_print();
125   
126   DOUT <<  "}\n";
127 #endif
128 }
129
130
131 Paper_def*
132 Score_element::paper()  const
133 {
134   assert (pscore_l_);
135   return pscore_l_->paper_l_;
136 }
137
138
139 Lookup const *
140 Score_element::lookup_l () const
141 {
142   return pscore_l_->paper_l_->lookup_l (size_i_);
143 }
144
145 void
146 Score_element::add_processing()
147 {
148   if (status_i_)
149     return;
150   status_i_ ++;
151   do_add_processing();
152 }
153
154
155 void
156 Score_element::calculate_dependencies (int final, int busy,
157                                     Score_element_method_pointer funcptr)
158 {
159   if (status_i_ >= final)
160     return;
161
162   assert (status_i_!= busy);
163   status_i_= busy;
164
165   for (int i=0; i < dependency_size(); i++)
166     dependency (i)->calculate_dependencies (final, busy, funcptr);
167
168   Link_array<Score_element> extra (get_extra_dependencies());
169   for (int i=0; i < extra.size(); i++)
170     extra[i]->calculate_dependencies (final, busy, funcptr);
171   
172   invalidate_cache (X_AXIS);
173   invalidate_cache (Y_AXIS);
174   (this->*funcptr)();
175   status_i_= final;
176 }
177
178 void
179 Score_element::output_processing () 
180 {
181   if (transparent_b_)
182     return;
183   if (output_p_)
184     delete output_p_;
185   
186   output_p_ = do_brew_molecule_p ();
187   pscore_l_->outputter_l_->output_molecule (output_p_,
188                                             absolute_offset (),
189                                             classname(this));
190 }
191
192 /*
193   
194   VIRTUAL STUBS
195
196  */
197
198 void
199 Score_element::do_break_processing()
200 {
201   handle_broken_dependencies();
202 }
203
204 void
205 Score_element::do_post_processing()
206 {
207 }
208
209 void
210 Score_element::do_breakable_col_processing()
211 {
212   handle_prebroken_dependencies();
213 }
214
215 void
216 Score_element::do_pre_processing()
217 {
218 }
219
220 void
221 Score_element::do_space_processing ()
222 {
223 }
224
225 void
226 Score_element::do_add_processing()
227 {
228 }
229
230 void
231 Score_element::do_substitute_dependency (Score_element*,Score_element*)
232 {
233 }
234 void
235 Score_element::do_substitute_dependent (Score_element*,Score_element*)
236 {
237 }
238
239 void
240 Score_element::do_unlink()
241 {
242 }
243
244 void
245 Score_element::do_junk_links()
246 {
247 }
248
249
250
251 Molecule*
252 Score_element::do_brew_molecule_p() const
253 {
254   Molecule a (lookup_l ()->fill (Box (Interval (0,0), Interval (0,0))));
255   return new Molecule (a);
256 }
257
258
259 Line_of_score *
260 Score_element::line_l() const
261 {
262   return 0;
263 }
264
265 /*
266   
267   DEPENDENCIES
268
269   */
270
271 void
272 Score_element::remove_dependency (Score_element*e)
273 {
274   remove_edge_out (e);
275   substitute_dependency (e, 0);
276 }
277
278 void
279 Score_element::add_dependency (Score_element*e)
280 {
281   Directed_graph_node::add_edge (e);
282 }
283 void
284 Score_element::substitute_dependency (Score_element* old, Score_element* new_l)
285 {
286   do_substitute_dependency (old,new_l);
287   old->do_substitute_dependent (this, 0);
288 }
289
290 void
291 Score_element::handle_broken_dependencies()
292 {
293   Line_of_score *line  = line_l();
294   if (!line)
295     return;
296
297   Link_array<Score_element> remove_us_arr;
298   for (int i=0; i < dependency_size(); i++) 
299     {
300       Score_element * elt = dependency (i);
301       if (elt->line_l() != line)
302         {
303           if (Spanner *sp = dynamic_cast<Spanner *> (elt)) 
304             {
305               Spanner * broken = sp->find_broken_piece (line);
306               substitute_dependency (sp, broken);
307
308               add_dependency (broken);
309             }
310           else if (Item *original = dynamic_cast <Item *> (elt))
311             {
312               Item * my_item = original->find_prebroken_piece (line);
313                 
314               substitute_dependency (elt, my_item);
315               if (my_item)
316                 add_dependency (my_item);
317             }
318           remove_us_arr.push (elt);
319         }
320     }
321
322   remove_us_arr.default_sort();
323   remove_us_arr.uniq();
324   for (int i=0;  i <remove_us_arr.size(); i++)
325     remove_dependency (remove_us_arr[i]);
326 }
327
328 /*
329   This sux.
330
331   unlike with spanners, the number of items can increase
332
333   span: item1
334
335   becomes
336
337   span: item1 item2 item3
338
339   How to let span (a derived class) know that this happened?
340  */
341 void
342 Score_element::handle_prebroken_dependencies()
343 {
344   Link_array<Score_element> old_arr, new_arr;
345   
346   for (int i=0; i < dependency_size(); i++) 
347     {
348       Score_element * elt = dependency (i);
349       Item *it_l = dynamic_cast <Item *> (elt);
350       if (it_l && it_l->breakable_b_)
351         if (Item *me = dynamic_cast<Item*> (this) )
352           {
353             Score_element *new_l = it_l->find_prebroken_piece (me->break_status_dir_);
354             if (new_l != elt) 
355               {
356                 new_arr.push (new_l);
357                 old_arr.push (elt);
358               }
359           }
360         else 
361           {
362             new_arr.push (it_l->broken_to_drul_[LEFT]);
363             old_arr.push (0);
364             old_arr.push (0);           
365             new_arr.push (it_l->broken_to_drul_[RIGHT]);                
366           }
367     }
368   
369   for (int i=0;  i < old_arr.size(); i++)
370     if (old_arr[i])
371       substitute_dependency (old_arr[i], new_arr[i]);
372 }
373
374 void
375 Score_element::handle_prebroken_dependents()
376 {
377 }
378
379
380 void
381 Score_element::junk_links ()
382 {
383   Directed_graph_node::junk_links();
384   Graphical_element::junk_links ();
385   do_junk_links();
386 }
387
388 void
389 Score_element::unlink()
390 {
391   do_unlink();
392   while (dependency_size()) 
393     {
394       do_substitute_dependency (dependency (0),0);
395       remove_edge_out_idx (0);
396     }
397   while  (dependent_size()) 
398     {
399       dependent (0)->remove_dependency (this);
400     }
401   Graphical_element::unlink ();
402 }
403
404
405 Link_array<Score_element>
406 Score_element::get_extra_dependencies() const
407 {
408   Link_array<Score_element> empty;
409   return empty;
410 }
411
412 bool
413 Score_element::linked_b() const
414 {
415   return get_extra_dependencies().size() || 
416     dependency_size();
417 }