2 score-elem.cc -- implement Score_element
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
13 #include "paper-score.hh"
14 #include "paper-def.hh"
16 #include "molecule.hh"
17 #include "score-element.hh"
20 #include "line-of-score.hh"
22 #include "paper-column.hh"
23 #include "molecule.hh"
25 #include "paper-outputter.hh"
26 #include "dimension-cache.hh"
27 #include "staff-side.hh"
30 Score_element::dim_cache_callback (Dimension_cache const*c)
32 Score_element * e =dynamic_cast<Score_element*> (c->element_l());
33 if(e->dim_cache_[X_AXIS] == c)
34 return e->do_width ();
36 return e->do_height ();
40 Score_element::Score_element()
43 dim_cache_[X_AXIS]->set_callback (dim_cache_callback);
44 dim_cache_[Y_AXIS]->set_callback (dim_cache_callback);
51 element_property_alist_ = SCM_EOL;
56 Score_element::Score_element (Score_element const&s)
57 : Graphical_element (s)
62 original_l_ =(Score_element*) &s;
63 element_property_alist_ = scm_protect_object (scm_list_copy (s.element_property_alist_));
64 dependency_arr_ = s.dependency_arr_;
66 status_i_ = s.status_i_;
67 lookup_l_ = s.lookup_l_;
68 pscore_l_ = s.pscore_l_;
73 Score_element::~Score_element()
76 assert (status_i_ >=0);
81 Score_element::dependency (int i) const
83 return dependency_arr_ [i];
87 Score_element::dependency_size () const
89 return dependency_arr_.size ();
92 // should also have one that takes SCM arg.
94 Score_element::get_elt_property (String nm) const
96 SCM sym = ly_symbol2scm (nm.ch_C());
97 SCM s = scm_assq(sym, element_property_alist_);
104 SCM sym2 = ly_symbol2scm ((name () + ("::" + nm)).ch_C());
107 // should probably check for Type::sym as well.
108 Paper_def * p= pscore_l_->paper_l_;
109 if (p->default_properties_.try_retrieve (sym2, &val))
111 else if (p->default_properties_.try_retrieve (sym, &val))
115 return SCM_UNDEFINED;
119 Score_element::remove_elt_property (String key)
121 SCM s = get_elt_property (key);
122 SCM sym = ly_symbol2scm (key.ch_C());
123 element_property_alist_ = scm_assq_remove_x (element_property_alist_, sym);
131 Score_element::set_elt_property (String k, SCM v)
133 SCM s = ly_symbol2scm (k.ch_C( ));
134 element_property_alist_ = scm_assoc_set_x (element_property_alist_, s, v);
138 Score_element::do_width() const
142 Molecule*m = output_p_ ? output_p_ : do_brew_molecule_p();
143 r = m->extent().x ();
152 Score_element::do_height() const
155 Molecule*m = output_p_ ? output_p_ : do_brew_molecule_p();
156 r = m->extent().y ();
164 Score_element::print() const
167 DEBUG_OUT << classname(this) << "{\n";
168 if (flower_dstream && !flower_dstream->silent_b ("Score_element"))
169 ly_display_scm (element_property_alist_);
170 DEBUG_OUT << "dependencies: " << dependency_size();
172 DEBUG_OUT << "Copy ";
173 Graphical_element::do_print ();
181 Score_element::paper_l () const
183 return pscore_l_->paper_l_;
187 Score_element::lookup_l () const
191 Score_element * urg = (Score_element*)this;
192 SCM sz = urg->remove_elt_property ("fontsize");
193 int i = (sz != SCM_UNDEFINED)
197 urg->lookup_l_ = (Lookup*)pscore_l_->paper_l_->lookup_l (i);
203 Score_element::add_processing()
205 assert (status_i_ >=0);
213 if (get_elt_property ("self-alignment-X") != SCM_UNDEFINED
214 && !dim_cache_[X_AXIS]->off_callback_l_)
216 dim_cache_[X_AXIS]->set_offset_callback (Side_position_interface::self_alignment);
219 if (get_elt_property ("self-alignment-Y") != SCM_UNDEFINED
220 && !dim_cache_[X_AXIS]->off_callback_l_)
223 dim_cache_[Y_AXIS]->set_offset_callback (Side_position_interface::self_alignment);
230 Score_element::calculate_dependencies (int final, int busy,
231 Score_element_method_pointer funcptr)
233 assert (status_i_ >=0);
235 if (status_i_ >= final)
238 assert (status_i_!= busy);
241 for (int i=0; i < dependency_arr_.size(); i++)
242 dependency_arr_[i]->calculate_dependencies (final, busy, funcptr);
244 Link_array<Score_element> extra (get_extra_dependencies());
245 for (int i=0; i < extra.size(); i++)
246 extra[i]->calculate_dependencies (final, busy, funcptr);
248 invalidate_cache (X_AXIS);
249 invalidate_cache (Y_AXIS);
255 Score_element::output_processing ()
257 if (get_elt_property ("transparent") != SCM_UNDEFINED)
260 // we're being silly here.
264 output_p_ = do_brew_molecule_p ();
265 Offset o (relative_coordinate (0, X_AXIS), relative_coordinate (0, Y_AXIS));
267 SCM s = get_elt_property ("extra-offset");
270 Real il = paper_l ()->get_var ("interline");
271 o[X_AXIS] += il * gh_scm2double (gh_car (s));
272 o[Y_AXIS] += il * gh_scm2double (gh_cdr (s));
275 pscore_l_->outputter_l_->output_molecule (output_p_,
289 Score_element::do_break_processing()
291 handle_broken_dependencies();
295 Score_element::do_post_processing()
300 Score_element::do_breakable_col_processing()
302 handle_prebroken_dependencies();
306 Score_element::do_pre_processing()
311 Score_element::do_space_processing ()
316 Score_element::do_add_processing()
321 Score_element::do_substitute_element_pointer (Score_element*,Score_element*)
327 Score_element::do_brew_molecule_p() const
329 Molecule a (lookup_l ()->fill (Box (Interval (0,0), Interval (0,0))));
330 return new Molecule (a);
335 Score_element::line_l() const
341 Score_element::add_dependency (Score_element*e)
345 dependency_arr_.push (e);
349 programming_error ("Null dependency added");
353 Score_element::substitute_dependency (Score_element* old, Score_element* new_l)
355 do_substitute_element_pointer (old,new_l);
356 old->do_substitute_element_pointer (this, 0);
361 Do break substitution, and return new value.
364 Score_element::handle_broken_smobs (SCM s, Line_of_score * line)
366 if (SMOB_IS_TYPE_B (Score_element, s))
368 Score_element *sc = SMOB_TO_TYPE (Score_element, s);
369 if (sc->line_l () != line)
371 sc= sc->find_broken_piece (line);
374 return sc ? sc->self_scm_ : SCM_UNDEFINED;
376 else if (gh_pair_p (s))
379 UGH! breaks on circular lists.
381 gh_set_car_x (s, handle_broken_smobs (gh_car (s), line));
382 gh_set_cdr_x (s, handle_broken_smobs (gh_cdr (s), line));
388 Score_element::handle_broken_dependencies()
390 Line_of_score *line = line_l();
394 element_property_alist_ = handle_broken_smobs (element_property_alist_, line);
396 Link_array<Score_element> new_deps;
398 for (int i=0; i < dependency_size(); i++)
400 Score_element * elt = dependency (i);
401 if (elt->line_l() != line)
403 Score_element * broken = elt->find_broken_piece (line);
404 substitute_dependency (elt, broken);
410 dependency_arr_ = new_deps;
419 Score_element::handle_prebroken_dependencies()
421 element_property_alist_
422 = handle_broken_smobs (element_property_alist_, line_l ());
424 Link_array<Score_element> old_arr, new_arr;
426 for (int i=0; i < dependency_size(); i++)
428 Score_element * elt = dependency (i);
429 Item *it_l = dynamic_cast <Item *> (elt);
430 if (it_l && it_l->broken_original_b ())
431 if (Item *me = dynamic_cast<Item*> (this) )
433 Score_element *new_l = it_l->find_broken_piece (me->break_status_dir ());
436 new_arr.push (new_l);
445 new_arr.push (it_l->find_broken_piece (d));
446 } while (flip(&d)!= LEFT);
450 for (int i=0; i < old_arr.size(); i++)
452 substitute_dependency (old_arr[i], new_arr[i]);
456 Score_element::handle_prebroken_dependents()
461 Score_element::handle_broken_dependents()
467 Link_array<Score_element>
468 Score_element::get_extra_dependencies() const
470 Link_array<Score_element> empty;
475 Score_element::linked_b() const
481 Score_element::do_print () const
488 Score_element::find_broken_piece (Line_of_score*) const
494 Score_element::mark_smob (SCM ses)
496 void * mp = (void*) SCM_CDR(ses);
497 Score_element * s = (Score_element*) mp;
499 assert (s->self_scm_ == ses);
500 return s->element_property_alist_;
505 Score_element::print_smob (SCM s, SCM port, scm_print_state *)
507 Score_element *sc = (Score_element *) SCM_CDR (s);
509 scm_puts ("#<Score_element ", port);
510 scm_puts ((char *)sc->name (), port);
511 scm_puts ("properties = ", port);
512 scm_display (sc->element_property_alist_, port);
513 scm_puts (" >", port);
518 Score_element::do_smobify_self ()
520 scm_unprotect_object (element_property_alist_); // ugh
522 #include "ly-smobs.icc"
523 IMPLEMENT_SMOBS(Score_element);
526 Score_element::equal_p (SCM a, SCM b)
528 return SCM_CDR(a) == SCM_CDR(b) ? SCM_BOOL_T : SCM_BOOL_F;