]> git.donarmstrong.com Git - lilypond.git/blob - lily/score-element.cc
release: 1.1.18
[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--1998 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   for (PCursor<Atom*> i(output_p_->atoms_); i.ok(); i++)
188     {
189       i->origin_l_ = this;
190     }
191   
192   pscore_l_->outputter_l_->output_molecule (output_p_,
193                                             absolute_offset (),
194                                             classname(this));
195 }
196
197 /*
198   
199   VIRTUAL STUBS
200
201  */
202
203 void
204 Score_element::do_break_processing()
205 {
206   handle_broken_dependencies();
207 }
208
209 void
210 Score_element::do_post_processing()
211 {
212 }
213
214 void
215 Score_element::do_breakable_col_processing()
216 {
217   handle_prebroken_dependencies();
218 }
219
220 void
221 Score_element::do_pre_processing()
222 {
223 }
224
225 void
226 Score_element::do_space_processing ()
227 {
228 }
229
230 void
231 Score_element::do_add_processing()
232 {
233 }
234
235 void
236 Score_element::do_substitute_dependency (Score_element*,Score_element*)
237 {
238 }
239 void
240 Score_element::do_substitute_dependent (Score_element*,Score_element*)
241 {
242 }
243
244 void
245 Score_element::do_unlink()
246 {
247 }
248
249 void
250 Score_element::do_junk_links()
251 {
252 }
253
254
255
256 Molecule*
257 Score_element::do_brew_molecule_p() const
258 {
259   Atom a (lookup_l ()->fill (Box (Interval (0,0), Interval (0,0))));
260   return new Molecule (a);
261 }
262
263
264 Line_of_score *
265 Score_element::line_l() const
266 {
267   return 0;
268 }
269
270 /*
271   
272   DEPENDENCIES
273
274   */
275
276 void
277 Score_element::remove_dependency (Score_element*e)
278 {
279   remove_edge_out (e);
280   substitute_dependency (e, 0);
281 }
282
283 void
284 Score_element::add_dependency (Score_element*e)
285 {
286   Directed_graph_node::add_edge (e);
287 }
288 void
289 Score_element::substitute_dependency (Score_element* old, Score_element* new_l)
290 {
291   do_substitute_dependency (old,new_l);
292   old->do_substitute_dependent (this, 0);
293 }
294
295 void
296 Score_element::handle_broken_dependencies()
297 {
298   Line_of_score *line  = line_l();
299   if (!line)
300     return;
301
302   Link_array<Score_element> remove_us_arr;
303   for (int i=0; i < dependency_size(); i++) 
304     {
305       Score_element * elt = dependency (i);
306       if (elt->line_l() != line)
307         {
308           if (Spanner *sp = dynamic_cast<Spanner *> (elt)) 
309             {
310               Spanner * broken = sp->find_broken_piece (line);
311               substitute_dependency (sp, broken);
312
313               add_dependency (broken);
314             }
315           else if (Item *original = dynamic_cast <Item *> (elt))
316             {
317               Item * my_item = original->find_prebroken_piece (line);
318                 
319               substitute_dependency (elt, my_item);
320               if (my_item)
321                 add_dependency (my_item);
322             }
323           remove_us_arr.push (elt);
324         }
325     }
326
327   remove_us_arr.default_sort();
328   remove_us_arr.uniq();
329   for (int i=0;  i <remove_us_arr.size(); i++)
330     remove_dependency (remove_us_arr[i]);
331 }
332
333 /*
334   This sux.
335
336   unlike with spanners, the number of items can increase
337
338   span: item1
339
340   becomes
341
342   span: item1 item2 item3
343
344   How to let span (a derived class) know that this happened?
345  */
346 void
347 Score_element::handle_prebroken_dependencies()
348 {
349   Link_array<Score_element> old_arr, new_arr;
350   
351   for (int i=0; i < dependency_size(); i++) 
352     {
353       Score_element * elt = dependency (i);
354       Item *it_l = dynamic_cast <Item *> (elt);
355       if (it_l && it_l->breakable_b_)
356         if (Item *me = dynamic_cast<Item*> (this) )
357           {
358             Score_element *new_l = it_l->find_prebroken_piece (me->break_status_dir_);
359             if (new_l != elt) 
360               {
361                 new_arr.push (new_l);
362                 old_arr.push (elt);
363               }
364           }
365         else 
366           {
367             new_arr.push (it_l->broken_to_drul_[LEFT]);
368             old_arr.push (0);
369             old_arr.push (0);           
370             new_arr.push (it_l->broken_to_drul_[RIGHT]);                
371           }
372     }
373   
374   for (int i=0;  i < old_arr.size(); i++)
375     if (old_arr[i])
376       substitute_dependency (old_arr[i], new_arr[i]);
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 }