Index: lily/slur-engraver.cc |
diff --git a/lily/slur-engraver.cc b/lily/slur-engraver.cc |
index 49f92ab0ed5a96b04e5bd5331fb1b49cf12f4e35..a8a54f535a1b4bdbd0edae79b25f3bdf4d51dafb 100644 |
--- a/lily/slur-engraver.cc |
+++ b/lily/slur-engraver.cc |
@@ -24,298 +24,40 @@ |
#include "international.hh" |
#include "note-column.hh" |
#include "slur.hh" |
+#include "slur-proto-engraver.hh" |
#include "spanner.hh" |
#include "stream-event.hh" |
#include "warn.hh" |
#include "translator.icc" |
-/* |
- NOTE NOTE NOTE |
- |
- This is largely similar to Phrasing_slur_engraver. Check if fixes |
- apply there too. |
- |
- (on principle, engravers don't use inheritance for code sharing) |
- |
- */ |
- |
-/* |
- It is possible that a slur starts and ends on the same note. At |
- least, it is for phrasing slurs: a note can be both beginning and |
- ending of a phrase. |
-*/ |
-class Slur_engraver : public Engraver |
+class Slur_engraver : public Slur_proto_engraver |
{ |
- vector<Stream_event *> start_events_; |
- vector<Stream_event *> stop_events_; |
- vector<Grob *> slurs_; |
- vector<Grob *> end_slurs_; |
- vector<Grob_info> objects_to_acknowledge_; |
- |
- void set_melisma (bool); |
+ virtual void set_melisma (bool); |
protected: |
DECLARE_TRANSLATOR_LISTENER (slur); |
- DECLARE_ACKNOWLEDGER (inline_accidental); |
- DECLARE_ACKNOWLEDGER (fingering); |
- DECLARE_ACKNOWLEDGER (note_column); |
- DECLARE_ACKNOWLEDGER (script); |
- DECLARE_ACKNOWLEDGER (dots); |
- DECLARE_ACKNOWLEDGER (text_script); |
- DECLARE_END_ACKNOWLEDGER (tie); |
- DECLARE_ACKNOWLEDGER (tuplet_number); |
- |
- void acknowledge_extra_object (Grob_info); |
- void stop_translation_timestep (); |
- void process_music (); |
- |
- virtual void finalize (); |
- virtual void derived_mark () const; |
public: |
TRANSLATOR_DECLARATIONS (Slur_engraver); |
}; |
-Slur_engraver::Slur_engraver () |
+Slur_engraver::Slur_engraver () : |
+ Slur_proto_engraver ("doubleSlurs", "Slur", "slur", "slur-event") |
{ |
} |
-void |
-Slur_engraver::derived_mark () const |
-{ |
- for (vsize i = start_events_.size (); i--;) |
- scm_gc_mark (start_events_[i]->self_scm ()); |
- for (vsize i = stop_events_.size (); i--;) |
- scm_gc_mark (stop_events_[i]->self_scm ()); |
-} |
- |
IMPLEMENT_TRANSLATOR_LISTENER (Slur_engraver, slur); |
void |
Slur_engraver::listen_slur (Stream_event *ev) |
{ |
- Direction d = to_dir (ev->get_property ("span-direction")); |
- if (d == START) |
- start_events_.push_back (ev); |
- else if (d == STOP) |
- stop_events_.push_back (ev); |
- else ev->origin ()->warning (_f ("direction of %s invalid: %d", |
- "slur-event", int (d))); |
+ internal_listen_slur (ev); |
} |
void |
Slur_engraver::set_melisma (bool m) |
{ |
- context ()->set_property ("slurMelismaBusy", m ? SCM_BOOL_T : SCM_BOOL_F); |
-} |
- |
-void |
-Slur_engraver::acknowledge_note_column (Grob_info info) |
-{ |
- Grob *e = info.grob (); |
- for (vsize i = slurs_.size (); i--;) |
- Slur::add_column (slurs_[i], e); |
- for (vsize i = end_slurs_.size (); i--;) |
- Slur::add_column (end_slurs_[i], e); |
-} |
- |
-void |
-Slur_engraver::acknowledge_extra_object (Grob_info info) |
-{ |
- objects_to_acknowledge_.push_back (info); |
-} |
- |
-void |
-Slur_engraver::acknowledge_inline_accidental (Grob_info info) |
-{ |
- acknowledge_extra_object (info); |
-} |
- |
-void |
-Slur_engraver::acknowledge_dots (Grob_info info) |
-{ |
- acknowledge_extra_object (info); |
-} |
- |
-void |
-Slur_engraver::acknowledge_fingering (Grob_info info) |
-{ |
- acknowledge_extra_object (info); |
-} |
- |
-void |
-Slur_engraver::acknowledge_tuplet_number (Grob_info info) |
-{ |
- acknowledge_extra_object (info); |
-} |
- |
-void |
-Slur_engraver::acknowledge_script (Grob_info info) |
-{ |
- if (!info.grob ()->internal_has_interface (ly_symbol2scm ("dynamic-interface"))) |
- acknowledge_extra_object (info); |
-} |
- |
-void |
-Slur_engraver::acknowledge_text_script (Grob_info info) |
-{ |
- acknowledge_extra_object (info); |
-} |
- |
-void |
-Slur_engraver::acknowledge_end_tie (Grob_info info) |
-{ |
- acknowledge_extra_object (info); |
-} |
- |
-void |
-Slur_engraver::finalize () |
-{ |
- for (vsize i = 0; i < slurs_.size (); i++) |
- { |
- slurs_[i]->warning (_ ("unterminated slur")); |
- slurs_[i]->suicide (); |
- } |
- slurs_.clear (); |
-} |
- |
-void |
-Slur_engraver::process_music () |
-{ |
- for (vsize i = 0; i < stop_events_.size (); i++) |
- { |
- Stream_event *ev = stop_events_[i]; |
- string id = robust_scm2string (ev->get_property ("spanner-id"), ""); |
- |
- // Find the slurs that are ended with this event (by checking the spanner-id) |
- bool ended = false; |
- for (vsize j = slurs_.size (); j--;) |
- { |
- if (id == robust_scm2string (slurs_[j]->get_property ("spanner-id"), "")) |
- { |
- ended = true; |
- end_slurs_.push_back (slurs_[j]); |
- slurs_.erase (slurs_.begin () + j); |
- } |
- } |
- if (ended) |
- { |
- // Ignore redundant stop events for this id |
- for (vsize j = stop_events_.size (); --j > i;) |
- { |
- if (id == robust_scm2string (stop_events_[j]->get_property ("spanner-id"), "")) |
- stop_events_.erase (stop_events_.begin () + j); |
- } |
- } |
- else |
- ev->origin ()->warning (_ ("cannot end slur")); |
- } |
- |
- vsize old_slurs = slurs_.size (); |
- for (vsize i = start_events_.size (); i--;) |
- { |
- Stream_event *ev = start_events_[i]; |
- string id = robust_scm2string (ev->get_property ("spanner-id"), ""); |
- Direction updown = to_dir (ev->get_property ("direction")); |
- |
- bool completed; |
- for (vsize j = slurs_.size (); !(completed = (j-- == 0));) |
- { |
- // Check if we already have a slur with the same spanner-id. |
- if (id == robust_scm2string (slurs_[j]->get_property ("spanner-id"), "")) |
- { |
- if (j < old_slurs) |
- { |
- // We already have an old slur, so give a warning |
- // and completely ignore the new slur. |
- ev->origin ()->warning (_ ("already have slur")); |
- start_events_.erase (start_events_.begin () + i); |
- break; |
- } |
- |
- // If this slur event has no direction, it will not |
- // contribute anything new to the existing slur(s), so |
- // we can ignore it. |
- |
- if (!updown) |
- break; |
- |
- Stream_event *c = unsmob_stream_event (slurs_[j]->get_property ("cause")); |
- |
- if (!c) |
- { |
- slurs_[j]->programming_error ("slur without a cause"); |
- continue; |
- } |
- |
- Direction slur_dir = to_dir (c->get_property ("direction")); |
- |
- // If the existing slur does not have a direction yet, |
- // we'd rather take the new one. |
- |
- if (!slur_dir) |
- { |
- slurs_[j]->suicide (); |
- slurs_.erase (slurs_.begin () + j); |
- continue; |
- } |
- |
- // If the existing slur has the same direction as ours, drop ours |
- |
- if (slur_dir == updown) |
- break; |
- } |
- } |
- // If the loop completed, our slur is new |
- if (completed) |
- { |
- Grob *slur = make_spanner ("Slur", ev->self_scm ()); |
- slur->set_property ("spanner-id", ly_string2scm (id)); |
- if (updown) |
- set_grob_direction (slur, updown); |
- slurs_.push_back (slur); |
- |
- if (to_boolean (get_property ("doubleSlurs"))) |
- { |
- set_grob_direction (slur, DOWN); |
- slur = make_spanner ("Slur", ev->self_scm ()); |
- slur->set_property ("spanner-id", ly_string2scm (id)); |
- set_grob_direction (slur, UP); |
- slurs_.push_back (slur); |
- } |
- } |
- } |
- set_melisma (slurs_.size ()); |
-} |
- |
-void |
-Slur_engraver::stop_translation_timestep () |
-{ |
- if (Grob *g = unsmob_grob (get_property ("currentCommandColumn"))) |
- { |
- for (vsize i = 0; i < end_slurs_.size (); i++) |
- Slur::add_extra_encompass (end_slurs_[i], g); |
- |
- if (!start_events_.size ()) |
- for (vsize i = 0; i < slurs_.size (); i++) |
- Slur::add_extra_encompass (slurs_[i], g); |
- } |
- |
- for (vsize i = 0; i < end_slurs_.size (); i++) |
- { |
- Spanner *s = dynamic_cast<Spanner *> (end_slurs_[i]); |
- if (!s->get_bound (RIGHT)) |
- s->set_bound (RIGHT, unsmob_grob (get_property ("currentMusicalColumn"))); |
- announce_end_grob (s, SCM_EOL); |
- } |
- |
- for (vsize i = 0; i < objects_to_acknowledge_.size (); i++) |
- Slur::auxiliary_acknowledge_extra_object (objects_to_acknowledge_[i], slurs_, end_slurs_); |
- |
- objects_to_acknowledge_.clear (); |
- end_slurs_.clear (); |
- start_events_.clear (); |
- stop_events_.clear (); |
+ context ()->set_property ("slurMelismaBusy", ly_bool2scm (m)); |
} |
ADD_ACKNOWLEDGER (Slur_engraver, inline_accidental); |