X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Faccidental-engraver.cc;h=2b44ea3f51f7a6fc85e2deac30880e8c60147170;hb=f459e523e2df1d26a854b4ff1e1d2f18189a7287;hp=ae3fe262a8f747c363842060f378c455e4aa212b;hpb=e37010af17faa8b185de836664b6544bd29dc1d0;p=lilypond.git diff --git a/lily/accidental-engraver.cc b/lily/accidental-engraver.cc index ae3fe262a8..2b44ea3f51 100644 --- a/lily/accidental-engraver.cc +++ b/lily/accidental-engraver.cc @@ -6,8 +6,7 @@ */ #include "event.hh" - - +#include "spanner.hh" #include "item.hh" #include "tie.hh" #include "rhythmic-head.hh" @@ -20,12 +19,6 @@ #include "context.hh" #include "protected-scm.hh" -/** - -The algorithm for accidentals should be documented, and made -tweakable. - -*/ struct Accidental_entry { bool done_; @@ -33,11 +26,13 @@ struct Accidental_entry { Grob * accidental_; Context *origin_; Grob* head_; + bool tied_; Accidental_entry(); }; Accidental_entry::Accidental_entry() { + tied_ = false; done_ = false; melodic_ =0; accidental_ = 0; @@ -67,11 +62,10 @@ public: Grob * accidental_placement_; - /* - The next - */ Array accidentals_; - Link_array ties_; + Link_array ties_; + + SCM get_bar_num (); }; @@ -109,15 +103,16 @@ Accidental_engraver::initialize () /* -calculates the number of accidentals on basis of the current local key sig - (passed as argument) + calculates the number of accidentals on basis of the current local key + sig (passed as argument) + Returns number of accidentals (0, 1 or 2). - Negative (-1 or -2) if accidental has changed. */ static int -number_accidentals_from_sig (SCM sig, Music *, Pitch *pitch, SCM curbarnum, SCM lazyness, - bool ignore_octave_b) +number_accidentals_from_sig (bool *different, + SCM sig, Pitch *pitch, SCM curbarnum, SCM lazyness, + bool ignore_octave) { int n = pitch->get_notename (); int o = pitch->get_octave(); @@ -126,7 +121,7 @@ number_accidentals_from_sig (SCM sig, Music *, Pitch *pitch, SCM curbarnum, SCM int accbarnum_i = 0; SCM prev; - if (ignore_octave_b) + if (ignore_octave) prev = ly_assoc_cdr (scm_int2num (n), sig); else prev = scm_assoc (gh_cons (scm_int2num (o), scm_int2num (n)), sig); @@ -155,17 +150,19 @@ number_accidentals_from_sig (SCM sig, Music *, Pitch *pitch, SCM curbarnum, SCM num = 2; else num = 1; - - return a == p ? num : -num; + + *different = (a != p); + return num; } static int -number_accidentals (Music * note, Pitch *pitch, Context * origin, +number_accidentals (bool *different, + Pitch *pitch, Context * origin, SCM accidentals, SCM curbarnum) { int number = 0; - bool diff = false; + *different = false; if (gh_pair_p (accidentals) && !gh_symbol_p (ly_car (accidentals))) warning (_f ("Accidental typesetting list must begin with context-name: %s", ly_scm2string (ly_car (accidentals)).to_str0 ())); @@ -187,10 +184,11 @@ number_accidentals (Music * note, Pitch *pitch, Context * origin, if (same_octave_b || any_octave_b) { + bool d = false; int n = number_accidentals_from_sig - (localsig, note, pitch, curbarnum, lazyness, any_octave_b); - diff = diff || (n < 0); - number = max (number, abs (n)); + (&d, localsig, pitch, curbarnum, lazyness, any_octave_b); + *different = *different || d; + number = max (number, n); } else warning (_f ("unknown accidental typesetting: %s. Ignored", @@ -214,7 +212,21 @@ number_accidentals (Music * note, Pitch *pitch, Context * origin, ly_scm2string (rule).to_str0 ())); } - return diff ? -number : number; + return number; +} + +SCM +Accidental_engraver::get_bar_num () +{ + SCM barnum = get_property ("currentBarNumber"); + SCM smp = get_property("measurePosition"); + + Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0); + if (mp.main_part_ < Rational (0) + && gh_number_p (barnum)) + barnum = scm_int2num (gh_scm2int (barnum) - 1); + + return barnum ; } void @@ -222,13 +234,10 @@ Accidental_engraver::process_acknowledged_grobs () { if (accidentals_.size () && !accidentals_.top().done_) { - //SCM localsig = get_property ("localKeySignature"); SCM accidentals = get_property ("autoAccidentals"); SCM cautionaries = get_property ("autoCautionaries"); - SCM barnum = get_property ("currentBarNumber"); - SCM smp = get_property("measurePosition"); - Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0); - if(mp.main_part_get_mus_property ("pitch")); if (!pitch) continue; + + bool different = false; + bool different_caut = false; - int num = number_accidentals (note, pitch, origin, accidentals, barnum); - int num_caut = number_accidentals (note, pitch, origin, cautionaries, barnum); + int num = number_accidentals (&different, + pitch, origin, + accidentals, barnum); + int num_caut = number_accidentals (&different_caut, + pitch, origin, + cautionaries, barnum); + bool cautionary = to_boolean (note->get_mus_property ("cautionary")); - if (abs (num_caut) > abs (num)) + if (num_caut > num) { num = num_caut; + different = different_caut; cautionary = true; } - if(num==0 && to_boolean (note->get_mus_property ("force-accidental"))) - num=1; + if (num == 0 && to_boolean (note->get_mus_property ("force-accidental"))) + num = 1; - bool different = num < 0; - num = abs (num); - - /* see if there's a tie that "changes" the accidental */ - /* works because if there's a tie, the note to the left - is of the same pitch as the actual note */ - - Grob *tie_break_reminder = 0; - bool tie_changes = false; - for (int j = 0; j < ties_.size (); j++) - if (support == Tie::head (ties_[j], RIGHT)) - { - tie_changes = different; - - /* Enable accidentals for broken tie - - We only want an accidental on a broken tie, - if the tie changes the accidental. - - Maybe check property noTieBreakForceAccidental? */ - if (different) - tie_break_reminder = ties_[j]; - break; - } + /* + Can not look for ties: it's not guaranteed that they reach + us before the notes + */ + if (num) { - Grob * a = make_item ("Accidental"); + /* + We construct the accidentals at the originating Voice + level, so that we get the property settings for + Accidental from the respective Voice. + */ + Grob * a = make_item_from_properties (origin, + ly_symbol2scm ("Accidental")); a->set_parent (support, Y_AXIS); if (!accidental_placement_) @@ -310,118 +315,120 @@ Accidental_engraver::process_acknowledged_grobs () a->set_grob_property ("cautionary", SCM_BOOL_T); } - if (tie_break_reminder) - { - // TODO. - a->set_grob_property ("tie", tie_break_reminder->self_scm()); - } - support->set_grob_property ("accidental-grob", a->self_scm ()); a->set_grob_property ("accidentals", accs); accidentals_[i].accidental_ = a; - /* - We add the accidentals to the support of the arpeggio, so it is put left of the - accidentals. - - */ + + /* + We add the accidentals to the support of the arpeggio, + so it is put left of the accidentals. + */ for (int i = 0; i < left_objects_.size (); i++) Side_position_interface::add_support (left_objects_[i], a); for (int i = 0; i < right_objects_.size (); i++) Side_position_interface::add_support (a, right_objects_[i]); } - - - /* - We should not record the accidental if it is the first - note and it is tied from the previous measure. - - Checking whether it is tied also works mostly, but will it - always do the correct thing? - */ - - - int n = pitch->get_notename (); - int o = pitch->get_octave (); - int a = pitch->get_alteration (); - SCM on_s = gh_cons (scm_int2num (o), scm_int2num (n)); - - /* - TODO: Speed this up! - - Perhaps only check translators mentioned in the auto-accidentals? - -rz - - TODO: profile this. - - I'd be surprised if the impact of this would be - measurable. Anyway, it seems localsig doesn't change - every time-step, but a set_property() is done every - time. We could save on that, probably. - - --hwn. - - - */ - - while (origin) - { - SCM localsig = origin->get_property ("localKeySignature"); - if (tie_changes) - { - /* - Remember an alteration that is different both from - that of the tied note and of the key signature. - */ - localsig = ly_assoc_front_x - (localsig, on_s, gh_cons (SCM_BOOL_T, barnum)); - } - else - { - /* - not really really correct if there are more than one - noteheads with the same notename. - */ - localsig = ly_assoc_front_x - (localsig, on_s, gh_cons (scm_int2num (a), barnum)); - } - origin->set_property ("localKeySignature", localsig); - origin = origin->daddy_context_; - } } } } + + + void Accidental_engraver::finalize () { - /* - Must reset, since Accidental_engraver is GCd. - */ last_keysig_ = SCM_EOL; } void Accidental_engraver::stop_translation_timestep () { - for (int i = 0; i < accidentals_.size(); i++) + for (int j = ties_.size (); j --; ) + { + Grob * r = Tie::head (ties_[j], RIGHT); + for (int i = accidentals_.size (); i--;) + if (accidentals_[i].head_ == r) + { + if (Grob * g = accidentals_[i].accidental_) + { + g->set_grob_property ("tie", ties_[j]->self_scm ()); + accidentals_[i].tied_ = true; + } + + ties_.del (j); + break; + } + } + + for (int i = accidentals_.size (); i--;) { - Grob *a = accidentals_[i].accidental_; - if (a) + SCM barnum = get_bar_num (); + + Music * note = accidentals_[i].melodic_; + Context * origin = accidentals_[i].origin_; + + Pitch * pitch = unsmob_pitch (note->get_mus_property ("pitch")); + if (!pitch) + continue; + + int n = pitch->get_notename (); + int o = pitch->get_octave (); + int a = pitch->get_alteration (); + SCM on_s = gh_cons (scm_int2num (o), scm_int2num (n)); + + while (origin) { - typeset_grob (a); + /* + huh? we set props all the way to the top? + */ + SCM localsig = origin->get_property ("localKeySignature"); + bool change = false; + if (accidentals_[i].tied_) + { + /* + Remember an alteration that is different both from + that of the tied note and of the key signature. + */ + localsig = ly_assoc_front_x + (localsig, on_s, gh_cons (SCM_BOOL_T, barnum)); + + change = true; + } + else + { + /* + not really really correct if there are more than one + noteheads with the same notename. + */ + localsig = ly_assoc_front_x + (localsig, on_s, gh_cons (scm_int2num (a), barnum)); + + change = true; + } + + if (change) + origin->set_property ("localKeySignature", localsig); + origin = origin->daddy_context_; } } + + for (int i = 0; i < accidentals_.size(); i++) + { + if (Grob *a = accidentals_[i].accidental_) + typeset_grob (a); + } if (accidental_placement_) typeset_grob(accidental_placement_); - accidental_placement_ = 00; + + accidental_placement_ = 0; accidentals_.clear(); left_objects_.clear (); right_objects_.clear (); - ties_.clear (); } void @@ -444,7 +451,7 @@ Accidental_engraver::acknowledge_grob (Grob_info info) } else if (Tie::has_interface (info.grob_)) { - ties_.push (info.grob_); + ties_.push (dynamic_cast (info.grob_)); } else if (Arpeggio::has_interface (info.grob_)) { @@ -483,11 +490,14 @@ Accidental_engraver::process_music () ENTER_DESCRIPTION (Accidental_engraver, -"Make accidentals. Catches note heads, ties and notices key-change " -" events. Due to interaction with ties (which don't come together " -" with note heads), this needs to be in a context higher than Tie_engraver.", - "Accidental", -/* accepts */ "", + "Make accidentals. Catches note heads, ties and notices key-change " + "events. This engraver usually lives at Staff level, but " + "reads the settings for Accidental at @code{Voice} level, " + "so you can @code{\\override} them at @code{Voice}. " + , + + "Accidental", + "", "finger-interface rhythmic-head-interface tie-interface arpeggio-interface", "localKeySignature extraNatural autoAccidentals autoCautionaries", "localKeySignature");