]> git.donarmstrong.com Git - lilypond.git/blob - lily/score-element.cc
release: 1.1.34
[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   break_helper_only_b_ = false;
30   transparent_b_ = false;
31   pscore_l_=0;
32   status_i_ = 0;
33   element_property_alist_ = SCM_EOL;
34 }
35
36 Score_element::Score_element (Score_element const&s)
37   :   Graphical_element (s)
38 {
39   /* called from derived ctor, so most info points to the same deps
40      as (Directed_graph_node&)s. Nobody points to us, so don't copy
41      dependents.      
42    */
43   
44
45   // deep copy ?
46   element_property_alist_ = s.element_property_alist_;
47   dependency_arr_ = s.dependency_arr_;
48   output_p_ =0;
49   break_helper_only_b_ = s.break_helper_only_b_;
50   transparent_b_ = s.transparent_b_;
51   status_i_ = s.status_i_;
52   pscore_l_ = s.pscore_l_;
53 }
54
55 Score_element::~Score_element()
56 {
57   delete output_p_; 
58   assert (status_i_ >=0);
59   status_i_  = -1;
60 }
61
62 Score_element*
63 Score_element::dependency (int i) const
64 {
65   return dependency_arr_ [i];
66 }
67
68 int
69 Score_element::dependency_size () const
70 {
71   return dependency_arr_.size ();
72 }
73
74
75
76 SCM
77 Score_element::get_elt_property (SCM s)
78 {
79   return scm_assq(s, element_property_alist_);
80 }
81 void
82 Score_element::set_elt_property (SCM s, SCM v)
83 {
84   element_property_alist_ =
85     scm_assoc_set_x (element_property_alist_, s, v);
86 }
87
88 Interval
89 Score_element::do_width() const 
90 {
91   Interval r;
92
93   Molecule*m = output_p_ ?  output_p_ : do_brew_molecule_p();
94   r = m->extent().x ();
95
96   if (!output_p_)
97     delete m;
98   
99   return r;
100 }
101
102 Interval
103 Score_element::do_height() const 
104 {
105   Interval r;
106   Molecule*m = output_p_ ?  output_p_ : do_brew_molecule_p();
107   r = m->extent().y ();
108   if (!output_p_)
109     delete m;
110
111   return r;
112 }
113
114
115 /*
116   STANDARD METHS
117  */
118 void
119 Score_element::print() const
120 {
121 #ifndef NPRINT
122   DOUT << classname(this) << "{\n";
123   DOUT << "dependencies: " << dependency_size();
124  
125   Graphical_element::do_print ();
126   do_print();
127   
128   DOUT <<  "}\n";
129 #endif
130 }
131
132
133 Paper_def*
134 Score_element::paper()  const
135 {
136   return pscore_l_->paper_l_;
137 }
138
139
140 Lookup const *
141 Score_element::lookup_l () const
142 {
143   SCM sz = scm_assq (ly_symbol ("fontsize"), element_property_alist_);
144   if (sz != SCM_BOOL_F)
145     return pscore_l_->paper_l_->lookup_l (gh_scm2int (SCM_CDR (sz)));
146   else
147     return pscore_l_->paper_l_->lookup_l (0);
148 }
149
150 void
151 Score_element::add_processing()
152 {
153   assert (status_i_ >=0);
154   if (status_i_)
155     return;
156   status_i_ ++;
157   do_add_processing();
158 }
159
160
161 void
162 Score_element::calculate_dependencies (int final, int busy,
163                                     Score_element_method_pointer funcptr)
164 {
165   assert (status_i_ >=0);
166
167   if (status_i_ >= final)
168     return;
169
170   assert (status_i_!= busy);
171   status_i_= busy;
172
173   for (int i=0; i < dependency_size(); i++)
174     dependency (i)->calculate_dependencies (final, busy, funcptr);
175
176   Link_array<Score_element> extra (get_extra_dependencies());
177   for (int i=0; i < extra.size(); i++)
178     extra[i]->calculate_dependencies (final, busy, funcptr);
179   
180   invalidate_cache (X_AXIS);
181   invalidate_cache (Y_AXIS);
182   (this->*funcptr)();
183   status_i_= final;
184 }
185
186 void
187 Score_element::output_processing () 
188 {
189   if (transparent_b_)
190     return;
191   if (output_p_)
192     delete output_p_;
193   
194   output_p_ = do_brew_molecule_p ();
195   pscore_l_->outputter_l_->output_molecule (output_p_,
196                                             absolute_offset (),
197                                             classname(this));
198 }
199
200 /*
201   
202   VIRTUAL STUBS
203
204  */
205
206 void
207 Score_element::do_break_processing()
208 {
209   handle_broken_dependencies();
210 }
211
212 void
213 Score_element::do_post_processing()
214 {
215 }
216
217 void
218 Score_element::do_breakable_col_processing()
219 {
220   handle_prebroken_dependencies();
221 }
222
223 void
224 Score_element::do_pre_processing()
225 {
226 }
227
228 void
229 Score_element::do_space_processing ()
230 {
231 }
232
233 void
234 Score_element::do_add_processing()
235 {
236 }
237
238 void
239 Score_element::do_substitute_element_pointer (Score_element*,Score_element*)
240 {
241 }
242
243
244 Molecule*
245 Score_element::do_brew_molecule_p() const
246 {
247   Molecule 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   int i;
268   while ((i = dependency_arr_.find_i (e)) >=0 )
269     dependency_arr_.unordered_del (i);
270
271   substitute_dependency (e, 0);
272 }
273
274 void
275 Score_element::add_dependency (Score_element*e)
276 {
277   if (e)
278     dependency_arr_.push (e);
279   else
280     warning("Null dependency added");
281       
282 }
283 void
284 Score_element::substitute_dependency (Score_element* old, Score_element* new_l)
285 {
286   do_substitute_element_pointer (old,new_l);
287   old->do_substitute_element_pointer (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
381 Link_array<Score_element>
382 Score_element::get_extra_dependencies() const
383 {
384   Link_array<Score_element> empty;
385   return empty;
386 }
387
388 bool
389 Score_element::linked_b() const
390 {
391   return get_extra_dependencies().size() || 
392     dependency_size();
393 }
394 void
395 Score_element::do_print () const
396 {
397 }