X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fscript-engraver.cc;h=afeb0fe621cda7b452e06d0c3278ee31c16cb2d5;hb=8d42f330d9a6ca0111ef66ce349a42751d686582;hp=af4be4f176af0e0441c9084eb5fc3554ccf27be1;hpb=f6e3a77381e8eb67aa01195ec3945bd978f86aa8;p=lilypond.git diff --git a/lily/script-engraver.cc b/lily/script-engraver.cc index af4be4f176..afeb0fe621 100644 --- a/lily/script-engraver.cc +++ b/lily/script-engraver.cc @@ -1,148 +1,247 @@ /* - script-engraver.cc -- implement Script_engraver + script-engraver.cc -- engrave Scripts: Articulations. - (c) 1997--1999 Han-Wen Nienhuys + source file of the GNU LilyPond music typesetter + + (c) 1997--2005 Han-Wen Nienhuys */ -#include "script-engraver.hh" -#include "script.hh" +#include "context.hh" +#include "directional-element-interface.hh" +#include "engraver.hh" +#include "slur.hh" +#include "note-column.hh" +#include "paper-column.hh" +#include "rhythmic-head.hh" +#include "script-interface.hh" #include "side-position-interface.hh" -#include "musical-request.hh" +#include "staff-symbol-referencer.hh" #include "stem.hh" -#include "staff-symbol.hh" -#include "rhythmic-head.hh" -#include "dimension-cache.hh" +#include "warn.hh" + +struct Script_tuple +{ + Music *event_; + Grob *script_; + bool follow_into_staff_; + Script_tuple () + { + follow_into_staff_ = false; + event_ = 0; + script_ = 0; + } +}; + +class Script_engraver : public Engraver +{ + Array scripts_; + Spanner *slur_; + +protected: + virtual bool try_music (Music *); + virtual void stop_translation_timestep (); + virtual void process_music (); + virtual void acknowledge_grob (Grob_info); -Script_engraver::Script_engraver() +public: + TRANSLATOR_DECLARATIONS (Script_engraver); +}; + +Script_engraver::Script_engraver () { - do_post_move_processing(); + slur_ = 0; } bool -Script_engraver::do_try_music (Music *r_l) +Script_engraver::try_music (Music *m) { - if (Articulation_req *mr = dynamic_cast (r_l)) + if (m->is_mus_type ("articulation-event")) { - for (int i=0; i < script_req_l_arr_.size(); i++) - { - if (script_req_l_arr_[i]->equal_b (mr)) - return true; - } - script_req_l_arr_.push (mr); + /* Discard double articulations for part-combining. */ + int script_count = scripts_.size (); + for (int i = 0; i < script_count; i++) + if (ly_c_equal_p (scripts_[i].event_ + ->get_property ("articulation-type"), + m->get_property ("articulation-type"))) + return true; + + Script_tuple t; + t.event_ = m; + scripts_.push (t); return true; } return false; } void -Script_engraver::do_process_requests() +copy_property (Grob *g, SCM sym, SCM alist) { - for (int i=0; i < script_req_l_arr_.size(); i++) + if (g->internal_get_property (sym) == SCM_EOL) { - Articulation_req* l=script_req_l_arr_[i]; + SCM entry = scm_assoc (sym, alist); + if (scm_is_pair (entry)) + g->internal_set_property (sym, scm_cdr (entry)); + } +} - SCM list = ly_eval_str (("(articulation-to-scriptdef \"" + l->articulation_str_ + "\")").ch_C()); - - if (list == SCM_BOOL_F) +/* Add the properties, one by one for each Script. A little memory + could be saved by tacking the props onto the Script grob (i.e. make + ScriptStaccato , ScriptMarcato, etc. ). +*/ +void make_script_from_event (Grob *p, bool *follow, Context *tg, + SCM art_type, int index) +{ + SCM alist = tg->get_property ("scriptDefinitions"); + SCM art = scm_assoc (art_type, alist); + + if (art == SCM_BOOL_F) + { + /* FIXME: */ + warning (_ ("don't know how to interpret articulation: ")); + warning (_ ("scheme encoding: ")); + scm_write (art_type, scm_current_error_port ()); + message (""); + return; + } + + art = scm_cdr (art); + + SCM follow_scm = scm_assoc (ly_symbol2scm ("follow-into-staff"), + art); + + *follow = scm_is_pair (follow_scm) && to_boolean (scm_cdr (follow_scm)); + bool priority_found = false; + + for (SCM s = art; scm_is_pair (s); s = scm_cdr (s)) + { + SCM sym = scm_caar (s); + SCM type = scm_object_property (sym, ly_symbol2scm ("backend-type?")); + if (!ly_c_procedure_p (type)) + continue; + + SCM val = scm_cdar (s); + + if (sym == ly_symbol2scm ("script-priority")) { - l->warning (_f ("Don't know how to interpret articulation `%s'", - l->articulation_str_.ch_C ())); - continue; + priority_found = true; + /* Make sure they're in order of user input by adding index i. + Don't use the direction in this priority. Smaller means closer + to the head. */ + int prio = scm_to_int (val) + index; + + val = scm_int2num (prio); } - Script *p =new Script; - Side_position_interface stafy (p); - - - list = gh_cdr (list); - p->set_elt_property ("molecule", - gh_car (list)); - - list = gh_cdr(list); - bool follow_staff = gh_scm2bool (gh_car (list)); - list = gh_cdr(list); - int relative_stem_dir = gh_scm2int (gh_car (list)); - list = gh_cdr(list); - int force_dir =gh_scm2int (gh_car (list)); - list = gh_cdr(list); - SCM priority = gh_car (list); - - - if (relative_stem_dir) - p->set_elt_property ("side-relative-direction", gh_int2scm (relative_stem_dir)); - else - stafy.set_direction ((Direction)force_dir); - - if (l->get_direction ()) - stafy.set_direction (l->get_direction ()); - - SCM axisprop = get_property ("scriptHorizontal",0); - bool xaxis = to_boolean (axisprop); - if (xaxis) - stafy.set_axis (X_AXIS); - else - stafy.set_axis (Y_AXIS); - - if (!follow_staff && ! xaxis) - p->set_elt_property ("staff-support", SCM_BOOL_T); - - if (!xaxis && follow_staff) - stafy.set_quantised (Y_AXIS); - - p->set_elt_property ("script-priority", priority); - - script_p_arr_.push (p); - - announce_element (Score_element_info (p, l)); + if (p->internal_get_property (sym) == SCM_EOL) + p->internal_set_property (sym, val); } + + if (!priority_found) + { + p->set_property ("script-priority", + scm_int2num (index)); + } + + Side_position_interface::set_axis (p, Y_AXIS); } void -Script_engraver::acknowledge_element (Score_element_info inf) +Script_engraver::process_music () { - if (Stem *s = dynamic_cast(inf.elem_l_)) + int script_count = scripts_.size (); + for (int i = 0; i < script_count; i++) { - for (int i=0; i < script_p_arr_.size(); i++) + Music *m = scripts_[i].event_; + + Grob *p = make_item ("Script", m->self_scm ()); + + make_script_from_event (p, &scripts_[i].follow_into_staff_, context (), + m->get_property ("articulation-type"), + i); + + scripts_[i].script_ = p; + + SCM force_dir = m->get_property ("direction"); + if (is_direction (force_dir) && to_dir (force_dir)) + p->set_property ("direction", force_dir); + } +} + +void +Script_engraver::acknowledge_grob (Grob_info info) +{ + int script_count = scripts_.size (); + if (Stem::has_interface (info.grob_)) + { + for (int i = 0; i < script_count; i++) { - Side_position_interface stafy (script_p_arr_[i]); - stafy.elt_l_->set_elt_property ("direction-source", s->self_scm_); - stafy.add_support (s); + Grob *e = scripts_[i].script_; + + if (to_dir (e->get_property ("side-relative-direction"))) + e->set_property ("direction-source", info.grob_->self_scm ()); + + /* FIXME: add dependency */ + e->add_dependency (info.grob_); + Side_position_interface::add_support (e, info.grob_); } } - else if (Rhythmic_head * rh = dynamic_cast(inf.elem_l_)) + else if (Rhythmic_head::has_interface (info.grob_) + && info.music_cause ()) { - for (int i=0; i < script_p_arr_.size(); i++) + for (int i = 0; i < script_count; i++) { - Side_position_interface stafy(script_p_arr_[i]); - - if (!stafy.elt_l_->parent_l (X_AXIS)) + Grob *e = scripts_[i].script_; + + if (Side_position_interface::get_axis (e) == X_AXIS + && !e->get_parent (Y_AXIS)) { - stafy.elt_l_->set_parent (inf.elem_l_, X_AXIS); + e->set_parent (info.grob_, Y_AXIS); + e->add_dependency (info.grob_); } - if (stafy.get_axis () == X_AXIS - && !stafy.elt_l_->parent_l (Y_AXIS)) - stafy.elt_l_->set_parent (rh, Y_AXIS); - - stafy.add_support (rh); + Side_position_interface::add_support (e, info.grob_); } - } -} - -void -Script_engraver::do_pre_move_processing() -{ - for (int i=0; i < script_p_arr_.size(); i++) + } + else if (Note_column::has_interface (info.grob_)) { - typeset_element (script_p_arr_[i]); + /* Make note column the parent of the script. That is not + correct, but due to seconds in a chord, noteheads may be + swapped around horizontally. + + As the note head to put it on is not known now, postpone this + decision to Script_interface::before_line_breaking (). */ + for (int i = 0; i < script_count; i++) + { + Grob *e = scripts_[i].script_; + + if (!e->get_parent (X_AXIS) + && Side_position_interface::get_axis (e) == Y_AXIS) + e->set_parent (info.grob_, X_AXIS); + } } - script_p_arr_.clear(); + else if (Slur::has_interface (info.grob_)) + slur_ = dynamic_cast (info.grob_); } void -Script_engraver::do_post_move_processing() +Script_engraver::stop_translation_timestep () { - script_req_l_arr_.clear(); + int script_count = scripts_.size (); + for (int i = 0; i < script_count; i++) + if (scripts_[i].follow_into_staff_) + { + Grob *sc = scripts_[i].script_; + sc->add_offset_callback (Side_position_interface + ::quantised_position_proc, Y_AXIS); + sc->set_property ("staff-padding", SCM_EOL); + } + + scripts_.clear (); } -ADD_THIS_TRANSLATOR(Script_engraver); - - +ADD_TRANSLATOR (Script_engraver, + /* descr */ "Handles note scripted articulations.", + /* creats*/ "Script", + /* accepts */ "script-event articulation-event", + /* acks */ "stem-interface rhythmic-head-interface " + "slur-interface note-column-interface", + /* reads */ "scriptDefinitions", + /* write */ "");