X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=lily%2Fdynamic-engraver.cc;h=273aa105688c435fa9221f1b7b6643d7f96cb2fc;hb=b542997680bb2d95c3a03a77468b67e04d30685f;hp=0e3f29135304af912deeb44d87cb352dc86bc4d9;hpb=4bbc3761de1012c805f55bc957cb9c7c35ef3ddc;p=lilypond.git diff --git a/lily/dynamic-engraver.cc b/lily/dynamic-engraver.cc index 0e3f291353..273aa10568 100644 --- a/lily/dynamic-engraver.cc +++ b/lily/dynamic-engraver.cc @@ -1,23 +1,76 @@ /* - dynamic-reg.cc -- implement Dynamic_engraver + dynamic-engraver.cc -- implement Dynamic_engraver source file of the GNU LilyPond music typesetter - (c) 1997--1999 Han-Wen Nienhuys + (c) 1997--2000 Han-Wen Nienhuys */ #include "debug.hh" +#include "dimensions.hh" +#include "dimension-cache.hh" #include "crescendo.hh" #include "musical-request.hh" #include "lookup.hh" #include "paper-def.hh" -#include "score-column.hh" +#include "paper-column.hh" #include "staff-symbol.hh" #include "note-column.hh" #include "text-item.hh" -#include "staff-side.hh" +#include "side-position-interface.hh" #include "engraver.hh" #include "stem.hh" #include "note-head.hh" +#include "group-interface.hh" +#include "directional-element-interface.hh" +#include "staff-symbol-referencer.hh" +#include "translator-group.hh" +#include "axis-group-interface.hh" + + +/* + TODO: + + * direction of text-dynamic-request if not equalt to direction + of line-spanner + + * FIXME: this has gotten a bit too hairy. + */ + +class Dynamic_line_spanner : public Spanner +{ +public: + Dynamic_line_spanner (SCM); + VIRTUAL_COPY_CONS(Score_element); + void add_column (Note_column*); + void add_element (Score_element*); +}; + +Dynamic_line_spanner::Dynamic_line_spanner (SCM s) + : Spanner (s) +{ + Side_position_interface (this).set_axis (Y_AXIS); + Axis_group_interface (this).set_interface (); + Axis_group_interface (this).set_axes (X_AXIS, Y_AXIS); +} + +void +Dynamic_line_spanner::add_column (Note_column* n) +{ + if (!get_bound (LEFT)) + set_bound (LEFT, n); + else + set_bound (RIGHT, n); + + add_dependency (n); +} + + +void +Dynamic_line_spanner::add_element (Score_element* e) +{ + e->set_parent (this, Y_AXIS); + Axis_group_interface (this).add_element (e); +} /** print text & hairpin dynamics. @@ -25,276 +78,353 @@ class Dynamic_engraver : public Engraver { Text_item * text_p_; - Staff_side_item * staff_side_p_; - Staff_side_spanner * ss_span_p_; - Staff_side_spanner * to_end_ss_span_p_; - - - Crescendo * to_end_cresc_p_; + Crescendo * finished_cresc_p_; Crescendo * cresc_p_; - Span_req * cresc_req_l_; - Array dynamic_req_l_arr_; + + Text_script_req* text_req_l_; + Span_req * span_start_req_l_; + Drul_array span_req_l_drul_; + + Dynamic_line_spanner* line_spanner_; + Dynamic_line_spanner* finished_line_spanner_; + Moment last_request_mom_; + + Array pending_column_arr_; + Link_array pending_element_arr_; + void typeset_all (); + public: VIRTUAL_COPY_CONS(Translator); - Dynamic_engraver(); + Dynamic_engraver (); protected: + void announce_element (Score_element_info); + virtual void do_removal_processing (); virtual void acknowledge_element (Score_element_info); virtual bool do_try_music (Music *req_l); - virtual void do_process_requests(); - virtual void do_pre_move_processing(); - virtual void do_post_move_processing(); + virtual void do_process_music (); + virtual void do_pre_move_processing (); + virtual void do_post_move_processing (); }; +ADD_THIS_TRANSLATOR (Dynamic_engraver); + +void +Dynamic_engraver::announce_element (Score_element_info i) +{ + Group_interface (i.elem_l_, "interfaces").add_thing (ly_symbol2scm ("dynamic")); + + Engraver::announce_element (i); +} -Dynamic_engraver::Dynamic_engraver() +Dynamic_engraver::Dynamic_engraver () { - do_post_move_processing(); - text_p_ =0; - staff_side_p_ =0; - to_end_cresc_p_ = cresc_p_ = 0; - ss_span_p_ = to_end_ss_span_p_=0; - cresc_req_l_ = 0; + text_p_ = 0; + finished_cresc_p_ = 0; + line_spanner_ = 0; + finished_line_spanner_ = 0; + span_start_req_l_ = 0; + cresc_p_ =0; + + text_req_l_ = 0; + span_req_l_drul_[START] = 0; + span_req_l_drul_[STOP] = 0; } void -Dynamic_engraver::do_post_move_processing() +Dynamic_engraver::do_post_move_processing () { - dynamic_req_l_arr_.clear(); + text_req_l_ = 0; + span_req_l_drul_[START] = 0; + span_req_l_drul_[STOP] = 0; } bool Dynamic_engraver::do_try_music (Music * m) { - Request * r = dynamic_cast (m); - - if(Text_script_req * d = dynamic_cast (r)) + if (Text_script_req* d = dynamic_cast (m)) { - if (d->style_str_ != "dynamic") - return false; + if (d->style_str_ == "dynamic") + { + text_req_l_ = d; + return true; + } } - else if (Span_req * s = dynamic_cast (r)) + else if (Span_req* s = dynamic_cast (m)) { - if (s-> span_type_str_ != "crescendo" - && s->span_type_str_ != "decrescendo") - return false; + if ((s->span_type_str_ == "crescendo" + || s->span_type_str_ == "decrescendo")) + { + span_req_l_drul_[s->span_dir_] = s; + return true; + } } - else - return false; - - for (int i=0; i < dynamic_req_l_arr_.size (); i++) - if (r->equal_b (dynamic_req_l_arr_[i])) - return true; - - dynamic_req_l_arr_.push (r); - return true; + return false; } - void -Dynamic_engraver::do_process_requests() +Dynamic_engraver::do_process_music () { - Crescendo* new_cresc_p=0; - Staff_side_spanner * new_sss_p =0; - for (int i=0; i < dynamic_req_l_arr_.size(); i++) + if ((span_req_l_drul_[START] || span_req_l_drul_[STOP] || text_req_l_) + && !line_spanner_ + && pending_element_arr_.size ()) { - if (Text_script_req *absd = - dynamic_cast ( dynamic_req_l_arr_[i])) - { - if (text_p_) - { - dynamic_req_l_arr_[i]->warning (_("Got a dynamic already. Continuing dazed and confused")); - continue; - } - - String loud = absd->text_str_; + line_spanner_ = new Dynamic_line_spanner (get_property ("basicDynamicLineSpannerProperties")); + for (int i = 0; i < pending_column_arr_.size (); i++) + line_spanner_->add_column (pending_column_arr_[i]); + pending_column_arr_.clear (); + announce_element (Score_element_info + (line_spanner_, + text_req_l_ ? text_req_l_ : span_req_l_drul_[START])); - text_p_ = new Text_item; - text_p_->text_str_ = loud; // ugh - Scalar prop = get_property ("dynamicStyle", 0); + } - text_p_->style_str_ = prop.length_i () ? prop : "dynamic"; + if (line_spanner_ && pending_element_arr_.size ()) + { + for (int i = 0; i < pending_element_arr_.size (); i++) + line_spanner_->add_element (pending_element_arr_[i]); + pending_element_arr_.clear (); + } - staff_side_p_ = new Staff_side_item; - staff_side_p_->set_elt_property (script_priority_scm_sym, - gh_int2scm (100)); - - staff_side_p_->set_victim (text_p_); - staff_side_p_->axis_ = Y_AXIS; - staff_side_p_->dir_ = DOWN; + /* + TODO: This should be optionised: + * break when group of dynamic requests ends + * break now (only if no cresc. in progress) + * continue through piece */ + if (span_req_l_drul_[START] || span_req_l_drul_[STOP] || text_req_l_) + { + last_request_mom_ = now_mom (); + } + else + { + /* + During a (de)crescendo, pending request will not be cleared, + and a line-spanner will always be created, as \< \! are already + two requests. - - prop = get_property ("verticalDirection", 0); - if (prop.isdir_b()) - { - staff_side_p_->dir_ = Direction (int (prop)); - } + Maybe always creating a line-spanner for a (de)crescendo (see + below) is not a good idea: - prop = get_property ("dynamicDir", 0); - if (prop.isnum_b ()) - { - staff_side_p_->dir_ = (Direction) (int) prop; - } - if (absd->dir_) - { - staff_side_p_->dir_ = absd->dir_; - } + a\< b\p \!c - prop = get_property ("dynamicPadding", 0); - if (prop.isnum_b ()) - { - staff_side_p_->set_elt_property (padding_scm_sym, - gh_double2scm(Real(prop))); - } - announce_element (Score_element_info (text_p_, absd)); - announce_element (Score_element_info (staff_side_p_, absd)); - } - else if (Span_req *span_l - = dynamic_cast (dynamic_req_l_arr_[i])) + the \p will be centred on the line-spanner, and thus clash + with the hairpin. When axis-group code is in place, the \p + should move below the hairpin, which is probably better? + + Urg, but line-spanner must always have at least same duration + as (de)crecsendo, b.o. line-breaking. + */ + if (now_mom () > last_request_mom_ && !span_start_req_l_) { - if (span_l->span_dir_ == STOP) + for (int i = 0; i < pending_element_arr_.size (); i++) { - if (!cresc_p_) + Score_element* e = pending_element_arr_[i]; + Side_position_interface (e).set_axis (Y_AXIS); + Side_position_interface (e).add_staff_support (); + + /* + UGH UGH + */ + Direction d = directional_element (e).get (); + if (!d) { - span_l->warning (_ ("can't find (de)crescendo to end")); - } - else - { - assert (!to_end_cresc_p_); - to_end_cresc_p_ =cresc_p_; - to_end_ss_span_p_ = ss_span_p_ ; - - cresc_p_ = 0; - ss_span_p_ =0; - - - - - Scalar prop = get_property ("verticalDirection", 0); - if (prop.isdir_b()) - { - to_end_ss_span_p_->dir_ = Direction (int (prop)); - } - prop = get_property ("dynamicDir", 0); - if (prop.isdir_b ()) - { - to_end_ss_span_p_->dir_ = (Direction) (int) prop; - } - prop = get_property ("dynamicPadding", 0); - if (prop.isnum_b ()) - { - to_end_ss_span_p_->set_elt_property (padding_scm_sym, - gh_double2scm(Real(prop))); - } + SCM s = get_property ("dynamicDirection"); + if (!isdir_b (s)) + s = get_property ("verticalDirection"); + if (isdir_b (s)) + d = to_dir (s); + directional_element (e).set (d); } + + SCM s = get_property ("dynamicPadding"); + if (gh_number_p (s)) + e->set_elt_property ("padding", s); + s = get_property ("dynamicMinimumSpace"); + if (gh_number_p (s)) + e->set_elt_property ("minimum-space", s); } - else if (span_l->span_dir_ == START) + pending_element_arr_.clear (); + if (line_spanner_) { - cresc_req_l_ = span_l; - assert (!new_cresc_p); - new_cresc_p = new Crescendo; - new_cresc_p->grow_dir_ = (span_l->span_type_str_ == "crescendo") ? BIGGER : SMALLER; - announce_element (Score_element_info (new_cresc_p, span_l)); - - new_sss_p = new Staff_side_spanner; - new_sss_p->set_victim (new_cresc_p); - new_sss_p->axis_ = Y_AXIS; - // UGH.! - // new_sss_p->set_elt_property (dangling_scm_sym, SCM_BOOL_T); - announce_element (Score_element_info (new_sss_p, span_l)); + for (int i = 0; i < pending_column_arr_.size (); i++) + line_spanner_->add_column (pending_column_arr_[i]); + pending_column_arr_.clear (); + finished_line_spanner_ = line_spanner_; + line_spanner_ = 0; } } + } + + if (text_req_l_) + { + String loud = text_req_l_->text_str_; + + text_p_ = new Text_item (get_property ("basicDynamicTextProperties")); + text_p_->set_elt_property ("text", ly_str02scm (loud.ch_C ())); + if (Direction d=text_req_l_->get_direction ()) + directional_element (text_p_).set (d); + pending_element_arr_.push (text_p_); + + text_p_->add_offset_callback (Side_position_interface::aligned_on_self, + Y_AXIS); + announce_element (Score_element_info (text_p_, text_req_l_)); } - if (new_cresc_p) + if (span_req_l_drul_[STOP]) { - if (cresc_p_) + if (!cresc_p_) { - ::warning (_ ("Too many crescendi here")); - typeset_element (cresc_p_); - typeset_element (ss_span_p_); + span_req_l_drul_[STOP]->warning + (_ ("can't find start of (de)crescendo")); + } + else + { + assert (!finished_cresc_p_); + cresc_p_->set_bound (RIGHT, get_staff_info ().musical_pcol_l ()); + finished_cresc_p_ = cresc_p_; cresc_p_ = 0; - ss_span_p_ =0; + span_start_req_l_ = 0; } - - cresc_p_ = new_cresc_p; - ss_span_p_ = new_sss_p; - cresc_p_->set_bounds(LEFT,get_staff_info().musical_pcol_l ()); - ss_span_p_->set_bounds (LEFT,get_staff_info().musical_pcol_l ()); - if (text_p_) + } + + if (span_req_l_drul_[START]) + { + if (span_start_req_l_) { - cresc_p_->dyn_b_drul_[LEFT] = true; - if (to_end_cresc_p_) - to_end_cresc_p_->dyn_b_drul_[RIGHT] = true; + span_req_l_drul_[START]->warning + (span_start_req_l_->span_dir_ == 1 + ? + _ ("already have a crescendo") + : _ ("already have a decrescendo")); + } + else + { + span_start_req_l_ = span_req_l_drul_[START]; + cresc_p_ = new Crescendo (get_property ("basicCrescendoProperties")); + cresc_p_->set_elt_property + ("grow-direction", + gh_int2scm ((span_req_l_drul_[START]->span_type_str_ == "crescendo") + ? BIGGER : SMALLER)); + + SCM s = get_property (span_req_l_drul_[START]->span_type_str_ + "Text"); + if (gh_string_p (s)) + { + cresc_p_->set_elt_property ("start-text", s); + daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_ + + "Text", SCM_UNDEFINED); + } + + s = get_property (span_req_l_drul_[START]->span_type_str_ + "Spanner"); + + + /* + TODO: Use symbols. + */ + if (gh_string_p (s)) //&& ly_scm2string (s) != "hairpin") + { + cresc_p_->set_elt_property ("spanner", s); + daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_ + + "Spanner", SCM_UNDEFINED); + } + + cresc_p_->set_bound (LEFT, get_staff_info ().musical_pcol_l ()); + + + /* + We know how wide the text is, if we can be sure that the + text already has relevant pointers into the paperdef, + and it has its font-size property set. + + Since font-size may be set by a context higher up, we + can not be sure of the size. + + + We shouldn't try to do this stuff here, the Item should + do it when the score is finished. We could maybe + set a callback to have the Item do the alignment if + it is not a special symbol, like Crescendo. + */ + + + if (text_p_) + { + index_set_cell (cresc_p_->get_elt_property ("dynamic-drul"), + LEFT, SCM_BOOL_T); + if (finished_cresc_p_) + index_set_cell (finished_cresc_p_->get_elt_property ("dynamic-drul"), + RIGHT, SCM_BOOL_T); + } + pending_element_arr_.push (cresc_p_); + cresc_p_->set_elt_property ("self-alignment-Y", gh_int2scm (0)); + cresc_p_->add_offset_callback + (Side_position_interface::aligned_on_self, Y_AXIS); + announce_element (Score_element_info (cresc_p_, span_req_l_drul_[START])); } } } void -Dynamic_engraver::do_pre_move_processing() +Dynamic_engraver::do_pre_move_processing () { typeset_all (); } - - -ADD_THIS_TRANSLATOR(Dynamic_engraver); - void Dynamic_engraver::do_removal_processing () { if (cresc_p_) { typeset_element (cresc_p_ ); - typeset_element (ss_span_p_); - ss_span_p_ =0; - cresc_req_l_->warning (_ ("unended crescendo")); + span_start_req_l_->warning (_ ("unterminated (de)crescendo")); cresc_p_ =0; } typeset_all (); + if (line_spanner_) + { + Side_position_interface (line_spanner_).add_staff_support (); + typeset_element (line_spanner_); + line_spanner_ = 0; + } } - void Dynamic_engraver::typeset_all () { - if (to_end_cresc_p_) + if (finished_cresc_p_) { - to_end_cresc_p_->set_bounds(RIGHT,get_staff_info().musical_pcol_l ()); - to_end_ss_span_p_->set_bounds(RIGHT,get_staff_info().musical_pcol_l ()); - typeset_element (to_end_cresc_p_); - typeset_element (to_end_ss_span_p_); - to_end_cresc_p_ =0; - to_end_ss_span_p_ =0; + typeset_element (finished_cresc_p_); + finished_cresc_p_ =0; } if (text_p_) { typeset_element (text_p_); - typeset_element (staff_side_p_); - text_p_ =0; - staff_side_p_ =0; + text_p_ = 0; + } + if (finished_line_spanner_) + { + Side_position_interface (finished_line_spanner_).add_staff_support (); + typeset_element (finished_line_spanner_); + finished_line_spanner_ = 0; } } - void Dynamic_engraver::acknowledge_element (Score_element_info i) { - if (dynamic_cast (i.elem_l_) - || dynamic_cast (i.elem_l_) - ) + if (Note_column* n = dynamic_cast (i.elem_l_)) { - if (staff_side_p_) - staff_side_p_->add_support (i.elem_l_); - - if (to_end_ss_span_p_) - to_end_ss_span_p_->add_support (i.elem_l_); - - if (ss_span_p_) - ss_span_p_->add_support (i.elem_l_); + if (line_spanner_) + { + Side_position_interface (line_spanner_).add_support (n); + line_spanner_->add_column (n); + } + else + { + pending_column_arr_.push (n); + } } }