X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fnew-fingering-engraver.cc;h=5078e2d2db9f1bcd11139528f93c469703c80c33;hb=5b4b0d6e9a197e8f9eb085b7c2ad78b8be3e5cfc;hp=f28bcb46cad5e9804c0228bbd9afb4135b1785b6;hpb=811be522d0b79493159f47789e5621dc85493495;p=lilypond.git diff --git a/lily/new-fingering-engraver.cc b/lily/new-fingering-engraver.cc index f28bcb46ca..5078e2d2db 100644 --- a/lily/new-fingering-engraver.cc +++ b/lily/new-fingering-engraver.cc @@ -3,26 +3,31 @@ source file of the GNU LilyPond music typesetter - (c) 1998--2005 Han-Wen Nienhuys + (c) 1998--2008 Han-Wen Nienhuys */ -#include "warn.hh" #include "engraver.hh" -#include "side-position-interface.hh" -#include "stem.hh" + +#include "international.hh" #include "rhythmic-head.hh" -#include "self-alignment-interface.hh" #include "script-interface.hh" +#include "self-alignment-interface.hh" +#include "side-position-interface.hh" #include "stem.hh" +#include "stream-event.hh" +#include "item.hh" +#include "warn.hh" #include "translator.icc" + + struct Finger_tuple { Grob *head_; Grob *script_; - Music *note_event_; - Music *finger_event_; + Stream_event *note_event_; + Stream_event *finger_event_; bool follow_into_staff_; int position_; @@ -33,37 +38,43 @@ struct Finger_tuple note_event_ = finger_event_ = 0; follow_into_staff_ = false; } - static int compare (Finger_tuple const &c1, Finger_tuple const &c2) - { - return c1.position_- c2.position_; - } }; +bool +operator< (Finger_tuple const &a, Finger_tuple const &b) +{ + return a.position_ < b.position_; +} + class New_fingering_engraver : public Engraver { - Array fingerings_; - Array articulations_; - Array string_numbers_; - - Link_array heads_; + vector fingerings_; + vector stroke_fingerings_; + vector articulations_; + vector string_numbers_; + + vector heads_; Grob *stem_; + void position_all (); public: TRANSLATOR_DECLARATIONS (New_fingering_engraver); protected: void stop_translation_timestep (); DECLARE_ACKNOWLEDGER (rhythmic_head); DECLARE_ACKNOWLEDGER (stem); - void add_fingering (Grob *, Music *, Music *); - void add_script (Grob *, Music *, Music *); - void add_string (Grob *, Music *, Music *); - void position_scripts (SCM orientations, Array *); + void add_fingering (Grob *, SCM, + vector *, + Stream_event *, Stream_event *); + void add_script (Grob *, Stream_event *, Stream_event *); + void add_string (Grob *, Stream_event *, Stream_event *); + void position_scripts (SCM orientations, vector *); }; void New_fingering_engraver::acknowledge_rhythmic_head (Grob_info inf) { - Music *note_ev = inf.music_cause (); + Stream_event *note_ev = inf.event_cause (); if (!note_ev) return; @@ -71,37 +82,38 @@ New_fingering_engraver::acknowledge_rhythmic_head (Grob_info inf) for (SCM s = arts; scm_is_pair (s); s = scm_cdr (s)) { - Music *m = unsmob_music (scm_car (s)); + Stream_event *ev = unsmob_stream_event (scm_car (s)); - if (!m) + if (!ev) continue; - if (m->is_mus_type ("fingering-event")) - { - add_fingering (inf.grob (), m, note_ev); - } - else if (m->is_mus_type ("text-script-event")) - { - m->origin ()->warning (_ ("can't add text scripts to individual note heads")); - } - else if (m->is_mus_type ("script-event")) - { - add_script (inf.grob (), m, note_ev); - } - else if (m->is_mus_type ("string-number-event")) - { - add_string (inf.grob (), m, note_ev); - } - else if (m->is_mus_type ("harmonic-event")) + if (ev->in_event_class ("fingering-event")) + add_fingering (inf.grob (), + ly_symbol2scm ("Fingering"), + &fingerings_, + ev, note_ev); + else if (ev->in_event_class ("text-script-event")) + ev->origin ()->warning (_ ("cannot add text scripts to individual note heads")); + else if (ev->in_event_class ("script-event")) + add_script (inf.grob (), ev, note_ev); + else if (ev->in_event_class ("string-number-event")) + add_fingering (inf.grob (), + ly_symbol2scm ("StringNumber"), &string_numbers_, + ev, note_ev); + else if (ev->in_event_class ("stroke-finger-event")) + add_fingering (inf.grob (), + ly_symbol2scm ("StrokeFinger"), &stroke_fingerings_, + ev, note_ev); + else if (ev->in_event_class ("harmonic-event")) { inf.grob ()->set_property ("style", ly_symbol2scm ("harmonic")); Grob *d = unsmob_grob (inf.grob ()->get_object ("dot")); - if (d) + if (d && !to_boolean (get_property ("harmonicDots"))) d->suicide (); } } - heads_.push (inf.grob ()); + heads_.push_back (inf.grob ()); } void @@ -112,94 +124,52 @@ New_fingering_engraver::acknowledge_stem (Grob_info inf) void New_fingering_engraver::add_script (Grob *head, - Music *event, - Music *note) + Stream_event *event, + Stream_event *note) { (void) note; Finger_tuple ft; Grob *g = make_item ("Script", event->self_scm ()); - make_script_from_event (g, &ft.follow_into_staff_, context (), + make_script_from_event (g, context (), event->get_property ("articulation-type"), 0); - if (g) - { - ft.script_ = g; - - articulations_.push (ft); - - ft.script_->set_parent (head, X_AXIS); - } + ft.script_ = g; + ft.script_->set_parent (head, X_AXIS); + + articulations_.push_back (ft); } void New_fingering_engraver::add_fingering (Grob *head, - Music *event, - Music *hevent) + SCM grob_sym, + vector *tuple_vector, + Stream_event *event, + Stream_event *hevent) { Finger_tuple ft; - ft.script_ = make_item ("Fingering", event->self_scm ()); + ft.script_ = internal_make_item (grob_sym, event->self_scm (), + ly_symbol2string (grob_sym).c_str (), + __FILE__, __LINE__, __FUNCTION__ + ); Side_position_interface::add_support (ft.script_, head); - int d = scm_to_int (event->get_property ("digit")); - - /* - TODO: - - Should add support for thumb. It's a little involved, since - the thumb lives in a different font. Maybe it should be moved? - - */ - if (d > 5) - { - /* - music for the softenon children? - */ - event->origin ()->warning (_ ("music for the martians.")); - } - SCM sstr = scm_number_to_string (scm_from_int (d), scm_from_int (10)); - ft.script_->set_property ("text", sstr); - ft.finger_event_ = event; ft.note_event_ = hevent; ft.head_ = head; - fingerings_.push (ft); -} - - -void -New_fingering_engraver::add_string (Grob *head, - Music *event, - Music *hevent) -{ - Finger_tuple ft; - - ft.script_ = make_item ("StringNumber", event->self_scm ()); - - Side_position_interface::add_support (ft.script_, head); - - int d = scm_to_int (event->get_property ("string-number")); - - SCM sstr = scm_number_to_string (scm_from_int (d), scm_from_int (10)); - ft.script_->set_property ("text", sstr); - - ft.finger_event_ = event; - ft.note_event_ = hevent; - ft.head_ = head; - - string_numbers_.push (ft); + tuple_vector->push_back (ft); } void New_fingering_engraver::position_scripts (SCM orientations, - Array *scripts) + vector *scripts) { - for (int i = 0; i < scripts->size (); i++) - if (stem_ && to_boolean (scripts->elem (i).script_->get_property ("add-stem-support"))) - Side_position_interface::add_support (scripts->elem (i).script_, stem_); + for (vsize i = 0; i < scripts->size (); i++) + if (stem_ && to_boolean (scripts->at (i).script_->get_property ("add-stem-support"))) + Side_position_interface::add_support (scripts->at (i).script_, stem_); /* This is not extremely elegant, but we have to do a little @@ -210,27 +180,25 @@ New_fingering_engraver::position_scripts (SCM orientations, to the note head, and write a more flexible function for positioning the fingerings, setting both X and Y coordinates. */ - for (int i = 0; i < scripts->size (); i++) - { - (*scripts)[i].position_ = scm_to_int ((*scripts)[i].head_->get_property ("staff-position")); - } + for (vsize i = 0; i < scripts->size (); i++) + (*scripts)[i].position_ = scm_to_int ((*scripts)[i].head_->get_property ("staff-position")); - for (int i = scripts->size (); i--;) - for (int j = heads_.size (); j--;) + for (vsize i = scripts->size (); i--;) + for (vsize j = heads_.size (); j--;) Side_position_interface::add_support ((*scripts)[i].script_, heads_[j]); - Array up, down, horiz; - for (int i = scripts->size (); i--;) + vector up, down, horiz; + for (vsize i = scripts->size (); i--;) { SCM d = (*scripts)[i].finger_event_->get_property ("direction"); if (to_dir (d)) { - ((to_dir (d) == UP) ? up : down).push ((*scripts)[i]); - scripts->del (i); + ((to_dir (d) == UP) ? up : down).push_back ((*scripts)[i]); + scripts->erase (scripts->begin () + i); } } - scripts->sort (&Finger_tuple::compare); + vector_sort (*scripts, less ()); bool up_p = scm_c_memq (ly_symbol2scm ("up"), orientations) != SCM_BOOL_F; bool down_p = scm_c_memq (ly_symbol2scm ("down"), orientations) != SCM_BOOL_F; @@ -240,25 +208,28 @@ New_fingering_engraver::position_scripts (SCM orientations, if (left_p || right_p) { if (up_p && !up.size () && scripts->size ()) - up.push (scripts->pop ()); + { + up.push_back (scripts->back ()); + scripts->pop_back (); + } if (down_p && !down.size () && scripts->size ()) { - down.push ((*scripts)[0]); - scripts->del (0); + down.push_back ((*scripts)[0]); + scripts->erase (scripts->begin ()); } - horiz.concat (*scripts); + horiz.insert (horiz.end (), scripts->begin (), scripts->end ()); } else if (up_p && down_p) { int center = scripts->size () / 2; - down.concat (scripts->slice (0, center)); - up.concat (scripts->slice (center, scripts->size ())); + down.insert (down.end (), scripts->begin (), scripts->begin () + center); + up.insert (up.end (), scripts->begin () + center, scripts->end ()); } else if (up_p) { - up.concat (*scripts); + up.insert (up.end (), scripts->begin (), scripts->end ()); scripts->clear (); } else @@ -268,55 +239,63 @@ New_fingering_engraver::position_scripts (SCM orientations, warning (_ ("no placement found for fingerings")); warning (_ ("placing below")); } - down.concat (*scripts); + down.insert (down.end (), scripts->begin (), scripts->end ()); scripts->clear (); } - for (int i = 0; i < horiz.size (); i++) + for (vsize i = 0; i < horiz.size (); i++) { Finger_tuple ft = horiz[i]; Grob *f = ft.script_; f->set_parent (ft.head_, X_AXIS); f->set_parent (ft.head_, Y_AXIS); - f->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, Y_AXIS); - f->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, Y_AXIS); - f->add_offset_callback (Side_position_interface::aligned_side_proc, X_AXIS); + f->set_property ("avoid-slur", SCM_BOOL_F); + if (hordir == LEFT + && unsmob_grob (ft.head_->get_object ("accidental-grob"))) + Side_position_interface::add_support (f, + unsmob_grob (ft.head_->get_object ("accidental-grob"))); + + Self_alignment_interface::set_align_self (f, Y_AXIS); + Self_alignment_interface::set_center_parent (f, Y_AXIS); + Side_position_interface::set_axis (f, X_AXIS); f->set_property ("direction", scm_from_int (hordir)); } - int finger_prio = 200; - for (int i = 0; i < up.size (); i++) + Direction d = DOWN; + Drul_array< vector > vertical (down, up); + do { - Finger_tuple ft = up[i]; - Grob *f = ft.script_; - f->set_parent (ft.head_, X_AXIS); - f->set_property ("script-priority", - scm_from_int (finger_prio + ft.position_)); - f->add_offset_callback (Side_position_interface::aligned_side_proc, Y_AXIS); - f->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, X_AXIS); - f->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, X_AXIS); - - f->set_property ("direction", scm_from_int (UP)); - } - - for (int i = 0; i < down.size (); i++) - { - Finger_tuple ft = down[i]; - Grob *f = ft.script_; - f->set_parent (ft.head_, X_AXIS); - f->set_property ("script-priority", - scm_from_int (finger_prio + down.size () - ft.position_)); - - f->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, X_AXIS); - f->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, X_AXIS); - f->add_offset_callback (Side_position_interface::aligned_side_proc, Y_AXIS); - f->set_property ("direction", scm_from_int (DOWN)); + for (vsize i = 0; i < vertical[d].size (); i++) + { + Finger_tuple ft = vertical[d][i]; + Grob *f = ft.script_; + int finger_prio = robust_scm2int (f->get_property ("script-priority"), 200); + f->set_parent (ft.head_, X_AXIS); + f->set_property ("script-priority", + scm_from_int (finger_prio + d * ft.position_)); + + Self_alignment_interface::set_align_self (f, X_AXIS); + Self_alignment_interface::set_center_parent (f, X_AXIS); + Side_position_interface::set_axis (f, Y_AXIS); + + f->set_property ("direction", scm_from_int (d)); + } } + while (flip (&d) != DOWN); } void New_fingering_engraver::stop_translation_timestep () +{ + position_all (); + stem_ = 0; + heads_.clear (); +} + + +void +New_fingering_engraver::position_all () { if (fingerings_.size ()) { @@ -332,11 +311,18 @@ New_fingering_engraver::stop_translation_timestep () string_numbers_.clear (); } - for (int i = articulations_.size (); i--;) + if (stroke_fingerings_.size ()) + { + position_scripts (get_property ("strokeFingerOrientations"), + &stroke_fingerings_); + stroke_fingerings_.clear (); + } + + for (vsize i = articulations_.size (); i--;) { Grob *script = articulations_[i].script_; - for (int j = heads_.size (); j--;) + for (vsize j = heads_.size (); j--;) Side_position_interface::add_support (script, heads_[j]); if (stem_ && to_dir (script->get_property ("side-relative-direction"))) @@ -344,16 +330,7 @@ New_fingering_engraver::stop_translation_timestep () if (stem_ && to_boolean (script->get_property ("add-stem-support"))) Side_position_interface::add_support (script, stem_); - - if (articulations_[i].follow_into_staff_) - { - script->add_offset_callback (Side_position_interface::quantised_position_proc, Y_AXIS); - script->set_property ("staff-padding", SCM_EOL); - } } - - stem_ = 0; - heads_.clear (); articulations_.clear (); } @@ -361,14 +338,29 @@ New_fingering_engraver::New_fingering_engraver () { stem_ = 0; } + + ADD_ACKNOWLEDGER (New_fingering_engraver, rhythmic_head); ADD_ACKNOWLEDGER (New_fingering_engraver, stem); ADD_TRANSLATOR (New_fingering_engraver, - /* descr */ "Create fingering-scripts for notes in a new chord. " - "This engraver is ill-named, since it " - "also takes care of articulations and harmonic note heads", - /* creats*/ "Fingering", - /* accepts */ "", - /* reads */ "fingeringOrientations", - /* write */ ""); + /* doc */ + "Create fingering scripts for notes in a new chord. This" + " engraver is ill-named, since it also takes care of" + " articulations and harmonic note heads.", + + /* create */ + "Fingering " + "StringNumber " + "StrokeFinger " + "Script ", + + /* read */ + "fingeringOrientations " + "harmonicDots " + "strokeFingerOrientations " + "stringNumberOrientations ", + + /* write */ + "" + );