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;
65 should protect because smobify_self () might trigger GC.
67 element_property_alist_ = scm_protect_object (scm_list_copy (s.element_property_alist_));
68 dependency_arr_ = s.dependency_arr_;
70 status_i_ = s.status_i_;
71 lookup_l_ = s.lookup_l_;
72 pscore_l_ = s.pscore_l_;
77 Score_element::~Score_element()
80 assert (status_i_ >=0);
85 Score_element::dependency (int i) const
87 return dependency_arr_ [i];
91 Score_element::dependency_size () const
93 return dependency_arr_.size ();
96 // should also have one that takes SCM arg.
98 Score_element::get_elt_property (String nm) const
100 SCM sym = ly_symbol2scm (nm.ch_C());
101 SCM s = scm_assq(sym, element_property_alist_);
108 SCM sym2 = ly_symbol2scm ((name () + ("::" + nm)).ch_C());
111 // should probably check for Type::sym as well.
112 Paper_def * p= pscore_l_->paper_l_;
113 if (p->default_properties_.try_retrieve (sym2, &val))
115 else if (p->default_properties_.try_retrieve (sym, &val))
119 return SCM_UNDEFINED;
123 Score_element::remove_elt_property (String key)
125 SCM s = get_elt_property (key);
126 SCM sym = ly_symbol2scm (key.ch_C());
127 element_property_alist_ = scm_assq_remove_x (element_property_alist_, sym);
135 Score_element::set_elt_property (String k, SCM v)
137 SCM s = ly_symbol2scm (k.ch_C( ));
138 element_property_alist_ = scm_assoc_set_x (element_property_alist_, s, v);
142 Score_element::do_width() const
146 Molecule*m = output_p_ ? output_p_ : do_brew_molecule_p();
147 r = m->extent().x ();
156 Score_element::do_height() const
159 Molecule*m = output_p_ ? output_p_ : do_brew_molecule_p();
160 r = m->extent().y ();
168 Score_element::print() const
171 DEBUG_OUT << classname(this) << "{\n";
172 if (flower_dstream && !flower_dstream->silent_b ("Score_element"))
173 ly_display_scm (element_property_alist_);
174 DEBUG_OUT << "dependencies: " << dependency_size();
176 DEBUG_OUT << "Copy ";
177 Graphical_element::do_print ();
185 Score_element::paper_l () const
187 return pscore_l_->paper_l_;
191 Score_element::lookup_l () const
195 Score_element * urg = (Score_element*)this;
196 SCM sz = urg->remove_elt_property ("fontsize");
197 int i = (sz != SCM_UNDEFINED)
201 urg->lookup_l_ = (Lookup*)pscore_l_->paper_l_->lookup_l (i);
207 Score_element::add_processing()
209 assert (status_i_ >=0);
218 if (get_elt_property ("self-alignment-X") != SCM_UNDEFINED
219 && !dim_cache_[X_AXIS]->off_callback_l_)
221 dim_cache_[X_AXIS]->off_callbacks_.push (Side_position_interface::self_alignment);
224 if (get_elt_property ("self-alignment-Y") != SCM_UNDEFINED
225 && !dim_cache_[X_AXIS]->off_callback_l_)
228 dim_cache_[Y_AXIS]->set_offset_callback (Side_position_interface::self_alignment);
236 Score_element::calculate_dependencies (int final, int busy,
237 Score_element_method_pointer funcptr)
239 assert (status_i_ >=0);
241 if (status_i_ >= final)
244 assert (status_i_!= busy);
247 for (int i=0; i < dependency_arr_.size(); i++)
248 dependency_arr_[i]->calculate_dependencies (final, busy, funcptr);
250 Link_array<Score_element> extra (get_extra_dependencies());
251 for (int i=0; i < extra.size(); i++)
252 extra[i]->calculate_dependencies (final, busy, funcptr);
259 Score_element::output_processing ()
261 if (get_elt_property ("transparent") != SCM_UNDEFINED)
264 // we're being silly here.
268 output_p_ = do_brew_molecule_p ();
269 Offset o (relative_coordinate (0, X_AXIS), relative_coordinate (0, Y_AXIS));
271 SCM s = get_elt_property ("extra-offset");
274 Real il = paper_l ()->get_var ("interline");
275 o[X_AXIS] += il * gh_scm2double (gh_car (s));
276 o[Y_AXIS] += il * gh_scm2double (gh_cdr (s));
279 pscore_l_->outputter_l_->output_molecule (output_p_,
293 Score_element::do_break_processing()
295 handle_broken_dependencies();
299 Score_element::do_post_processing()
304 Score_element::do_breakable_col_processing()
306 handle_prebroken_dependencies();
310 Score_element::do_pre_processing()
315 Score_element::do_space_processing ()
320 Score_element::do_add_processing()
325 Score_element::do_substitute_element_pointer (Score_element*,Score_element*)
331 Score_element::do_brew_molecule_p() const
333 Molecule a (lookup_l ()->fill (Box (Interval (0,0), Interval (0,0))));
334 return new Molecule (a);
339 Score_element::line_l() const
345 Score_element::add_dependency (Score_element*e)
349 dependency_arr_.push (e);
353 programming_error ("Null dependency added");
357 Score_element::substitute_dependency (Score_element* old, Score_element* new_l)
359 do_substitute_element_pointer (old,new_l);
360 old->do_substitute_element_pointer (this, 0);
365 Do break substitution in S, using CRITERION. Return new value.
366 CRITERION is either a SMOB pointer to the desired line, or a number
367 representing the break direction. */
369 Score_element::handle_broken_smobs (SCM s, SCM criterion)
371 if (SMOB_IS_TYPE_B (Score_element, s))
373 Score_element *sc = SMOB_TO_TYPE (Score_element, s);
375 if (gh_number_p (criterion))
377 Item * i = dynamic_cast<Item*> (sc);
378 Direction d = to_dir (criterion);
379 if (i && i->break_status_dir () != d)
381 Item *br = i->find_broken_piece (d);
382 return (br) ? br->self_scm_ : SCM_UNDEFINED;
387 Score_element * ln = SMOB_TO_TYPE (Score_element, criterion);
388 Line_of_score * line = dynamic_cast<Line_of_score*> (ln);
389 Score_element * br =0;
390 if (sc->line_l () != line)
392 br = sc->find_broken_piece (line);
393 return (br) ? br->self_scm_ : SCM_UNDEFINED;
398 else if (gh_pair_p (s))
401 UGH! breaks on circular lists.
403 gh_set_car_x (s, handle_broken_smobs (gh_car (s), criterion));
404 gh_set_cdr_x (s, handle_broken_smobs (gh_cdr (s), criterion));
410 Score_element::handle_broken_dependencies()
412 Line_of_score *line = line_l();
416 element_property_alist_ = handle_broken_smobs (element_property_alist_,
419 Link_array<Score_element> new_deps;
421 for (int i=0; i < dependency_size(); i++)
423 Score_element * elt = dependency (i);
424 if (elt->line_l() != line)
426 Score_element * broken = elt->find_broken_piece (line);
427 substitute_dependency (elt, broken);
433 dependency_arr_ = new_deps;
442 Score_element::handle_prebroken_dependencies()
444 if (Item*i =dynamic_cast<Item*> (this))
446 element_property_alist_
447 = handle_broken_smobs (element_property_alist_,
448 gh_int2scm (i->break_status_dir ()));
451 Link_array<Score_element> old_arr, new_arr;
453 for (int i=0; i < dependency_size(); i++)
455 Score_element * elt = dependency (i);
456 Item *it_l = dynamic_cast <Item *> (elt);
457 if (it_l && it_l->broken_original_b ())
458 if (Item *me = dynamic_cast<Item*> (this) )
460 Score_element *new_l = it_l->find_broken_piece (me->break_status_dir ());
463 new_arr.push (new_l);
472 new_arr.push (it_l->find_broken_piece (d));
473 } while (flip(&d)!= LEFT);
477 for (int i=0; i < old_arr.size(); i++)
479 substitute_dependency (old_arr[i], new_arr[i]);
483 Score_element::handle_prebroken_dependents()
488 Score_element::handle_broken_dependents()
494 Link_array<Score_element>
495 Score_element::get_extra_dependencies() const
497 Link_array<Score_element> empty;
502 Score_element::linked_b() const
508 Score_element::do_print () const
515 Score_element::find_broken_piece (Line_of_score*) const
521 Score_element::mark_smob (SCM ses)
523 void * mp = (void*) SCM_CDR(ses);
524 Score_element * s = (Score_element*) mp;
526 assert (s->self_scm_ == ses);
527 return s->element_property_alist_;
532 Score_element::print_smob (SCM s, SCM port, scm_print_state *)
534 Score_element *sc = (Score_element *) SCM_CDR (s);
536 scm_puts ("#<Score_element ", port);
537 scm_puts ((char *)sc->name (), port);
538 scm_puts ("properties = ", port);
539 scm_display (sc->element_property_alist_, port);
540 scm_puts (" >", port);
545 Score_element::do_smobify_self ()
547 scm_unprotect_object (element_property_alist_); // ugh
549 #include "ly-smobs.icc"
550 IMPLEMENT_SMOBS(Score_element);
553 Score_element::equal_p (SCM a, SCM b)
555 return SCM_CDR(a) == SCM_CDR(b) ? SCM_BOOL_T : SCM_BOOL_F;