]> git.donarmstrong.com Git - lilypond.git/blob - lily/score-element.cc
release: 1.1.35
[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 Interval
27 Score_element::dim_cache_callback (Dimension_cache*c)
28 {
29   Score_element *  e =dynamic_cast<Score_element*>( c->element_l());
30   if(&e->dim_cache_[X_AXIS] == c)
31     return e->do_width ();
32   else
33     return e->do_height ();
34 }
35
36 Score_element::Score_element()
37 {
38   output_p_ =0;
39   dim_cache_[X_AXIS].set_callback (dim_cache_callback);
40   dim_cache_[Y_AXIS].set_callback (dim_cache_callback); 
41   used_b_ = false;
42   pscore_l_=0;
43   lookup_l_ =0;
44   status_i_ = 0;
45   original_l_ = 0;
46   element_property_alist_ = SCM_EOL;
47 }
48
49 Score_element::Score_element (Score_element const&s)
50   : Graphical_element (s)
51 {
52   used_b_ = true;
53   original_l_ =(Score_element*) &s;
54   element_property_alist_ = scm_list_copy (s.element_property_alist_);
55   dependency_arr_ = s.dependency_arr_;
56   output_p_ =0;
57   status_i_ = s.status_i_;
58   lookup_l_ = s.lookup_l_;
59   pscore_l_ = s.pscore_l_;
60 }
61
62 Score_element::~Score_element()
63 {
64   delete output_p_; 
65   assert (status_i_ >=0);
66   status_i_  = -1;
67 }
68
69 Score_element*
70 Score_element::dependency (int i) const
71 {
72   return dependency_arr_ [i];
73 }
74
75 int
76 Score_element::dependency_size () const
77 {
78   return dependency_arr_.size ();
79 }
80
81
82
83 SCM
84 Score_element::get_elt_property (SCM sym) const
85 {
86   SCM s =  scm_assq(sym, element_property_alist_);
87   // is this a good idea?
88   if (s == SCM_BOOL_F && pscore_l_)
89     s = pscore_l_->paper_l_->get_scm_var (sym);
90
91   return s;
92 }
93
94 SCM
95 Score_element::remove_elt_property (SCM key)
96 {
97   SCM s = get_elt_property (key); 
98   element_property_alist_ =  scm_assq_remove_x (element_property_alist_, key);
99   return s;
100 }
101
102 void
103 Score_element::set_elt_property (SCM s, SCM v)
104 {
105   element_property_alist_ =
106     scm_assoc_set_x (element_property_alist_, s, v);
107 }
108
109 Interval
110 Score_element::do_width() const 
111 {
112   Interval r;
113
114   Molecule*m = output_p_ ?  output_p_ : do_brew_molecule_p();
115   r = m->extent().x ();
116
117   if (!output_p_)
118     delete m;
119   
120   return r;
121 }
122
123 Interval
124 Score_element::do_height() const 
125 {
126   Interval r;
127   Molecule*m = output_p_ ?  output_p_ : do_brew_molecule_p();
128   r = m->extent().y ();
129   if (!output_p_)
130     delete m;
131
132   return r;
133 }
134
135
136 /*
137   STANDARD METHS
138  */
139 void
140 Score_element::print() const
141 {
142 #ifndef NPRINT
143   DOUT << classname(this) << "{\n";
144   DOUT << "dependencies: " << dependency_size();
145  
146   Graphical_element::do_print ();
147   do_print();
148   
149   DOUT <<  "}\n";
150 #endif
151 }
152
153
154 Paper_def*
155 Score_element::paper_l ()  const
156 {
157  return pscore_l_->paper_l_;
158 }
159
160
161 Lookup const *
162 Score_element::lookup_l () const
163 {
164   if (!lookup_l_)
165     {
166       Score_element * me = (Score_element*)this;
167       SCM sz = me->remove_elt_property (fontsize_scm_sym);
168       int i = (sz != SCM_BOOL_F)
169         ? gh_scm2int (SCM_CDR (sz))
170         : 0;
171
172
173       me->lookup_l_ =  pscore_l_->paper_l_->lookup_l (i);
174     }
175   return lookup_l_;
176 }
177
178 void
179 Score_element::add_processing()
180 {
181   assert (status_i_ >=0);
182   if (status_i_)
183     return;
184   status_i_ ++;
185   do_add_processing();
186 }
187
188
189 void
190 Score_element::calculate_dependencies (int final, int busy,
191                                     Score_element_method_pointer funcptr)
192 {
193   assert (status_i_ >=0);
194
195   if (status_i_ >= final)
196     return;
197
198   assert (status_i_!= busy);
199   status_i_= busy;
200
201   for (int i=0; i < dependency_arr_.size(); i++)
202     dependency_arr_[i]->calculate_dependencies (final, busy, funcptr);
203
204   Link_array<Score_element> extra (get_extra_dependencies());
205   for (int i=0; i < extra.size(); i++)
206     extra[i]->calculate_dependencies (final, busy, funcptr);
207   
208   invalidate_cache (X_AXIS);
209   invalidate_cache (Y_AXIS);
210   (this->*funcptr)();
211   status_i_= final;
212 }
213
214 void
215 Score_element::output_processing () 
216 {
217   if (get_elt_property (transparent_scm_sym) != SCM_BOOL_F)
218     return;
219
220   if (output_p_)
221     delete output_p_;
222   
223   output_p_ = do_brew_molecule_p ();
224   pscore_l_->outputter_l_->output_molecule (output_p_,
225                                             absolute_offset (),
226                                             classname(this));
227 }
228
229
230 /*
231   
232   VIRTUAL STUBS
233
234  */
235
236 void
237 Score_element::do_break_processing()
238 {
239   handle_broken_dependencies();
240 }
241
242 void
243 Score_element::do_post_processing()
244 {
245 }
246
247 void
248 Score_element::do_breakable_col_processing()
249 {
250   handle_prebroken_dependencies();
251 }
252
253 void
254 Score_element::do_pre_processing()
255 {
256 }
257
258 void
259 Score_element::do_space_processing ()
260 {
261 }
262
263 void
264 Score_element::do_add_processing()
265 {
266 }
267
268 void
269 Score_element::do_substitute_element_pointer (Score_element*,Score_element*)
270 {
271 }
272
273
274 Molecule*
275 Score_element::do_brew_molecule_p() const
276 {
277   Molecule a (lookup_l ()->fill (Box (Interval (0,0), Interval (0,0))));
278   return new Molecule (a);
279 }
280
281
282 Line_of_score *
283 Score_element::line_l() const
284 {
285   return 0;
286 }
287
288 /*
289   
290   DEPENDENCIES
291
292   */
293
294 void
295 Score_element::remove_dependency (Score_element*e)
296 {
297   int i;
298   while ((i = dependency_arr_.find_i (e)) >=0 )
299     dependency_arr_.unordered_del (i);
300
301   substitute_dependency (e, 0);
302 }
303
304 void
305 Score_element::add_dependency (Score_element*e)
306 {
307   if (e)
308     {
309       dependency_arr_.push (e);
310       e->used_b_ = true;
311     }
312   else
313     warning("Null dependency added");
314       
315 }
316 void
317 Score_element::substitute_dependency (Score_element* old, Score_element* new_l)
318 {
319   do_substitute_element_pointer (old,new_l);
320   old->do_substitute_element_pointer (this, 0);
321 }
322
323 void
324 Score_element::handle_broken_dependencies()
325 {
326   Line_of_score *line  = line_l();
327   if (!line)
328     return;
329
330   Link_array<Score_element> remove_us_arr;
331   for (int i=0; i < dependency_size(); i++) 
332     {
333       Score_element * elt = dependency (i);
334       if (elt->line_l() != line)
335         {
336           if (Spanner *sp = dynamic_cast<Spanner *> (elt)) 
337             {
338               Spanner * broken = sp->find_broken_piece (line);
339               substitute_dependency (sp, broken);
340
341               if (broken)
342                 add_dependency (broken);
343             }
344           else if (Item *original = dynamic_cast <Item *> (elt))
345             {
346               Item * my_item = original->find_prebroken_piece (line);
347                 
348               substitute_dependency (elt, my_item);
349               if (my_item)
350                 add_dependency (my_item);
351             }
352           remove_us_arr.push (elt);
353         }
354     }
355
356   remove_us_arr.default_sort();
357   remove_us_arr.uniq();
358   for (int i=0;  i <remove_us_arr.size(); i++)
359     remove_dependency (remove_us_arr[i]);
360 }
361
362 /*
363   This sux.
364
365   unlike with spanners, the number of items can increase
366
367   span: item1
368
369   becomes
370
371   span: item1 item2 item3
372
373   How to let span (a derived class) know that this happened?
374  */
375 void
376 Score_element::handle_prebroken_dependencies()
377 {
378   /*  dynamic_cast<Item*> (this) && 
379   if (!break_status_dir ())
380     return;
381   */
382   Link_array<Score_element> old_arr, new_arr;
383   
384   for (int i=0; i < dependency_size(); i++) 
385     {
386       Score_element * elt = dependency (i);
387       Item *it_l = dynamic_cast <Item *> (elt);
388       if (it_l && it_l->broken_original_b ())
389         if (Item *me = dynamic_cast<Item*> (this) )
390           {
391             Score_element *new_l = it_l->find_prebroken_piece (me->break_status_dir ());
392             if (new_l != elt) 
393               {
394                 new_arr.push (new_l);
395                 old_arr.push (elt);
396               }
397           }
398         else 
399           {
400             Direction d = LEFT;
401             do {
402               old_arr.push (0);
403               new_arr.push (it_l->find_prebroken_piece (d));
404             } while (flip(&d)!= LEFT);
405           }
406     }
407   
408   for (int i=0;  i < old_arr.size(); i++)
409     if (old_arr[i])
410       substitute_dependency (old_arr[i], new_arr[i]);
411 }
412
413 void
414 Score_element::handle_prebroken_dependents()
415 {
416 }
417
418
419
420 Link_array<Score_element>
421 Score_element::get_extra_dependencies() const
422 {
423   Link_array<Score_element> empty;
424   return empty;
425 }
426
427 bool
428 Score_element::linked_b() const
429 {
430   return used_b_;
431 }
432
433 void
434 Score_element::do_print () const
435 {
436 }