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