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