X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=lily%2Fslur-proto-engraver.cc;h=99e8e8ebfcd54fd87f8ac370466e01f0b45b82ad;hb=f91c9533a7217e9d19eccc3c192ea9222efdbfc4;hp=a3ced1c2c11d612bf33cff3d76dde72fc957c086;hpb=88d306d9c5666b5ade4a136df29cca19c5ff5ed7;p=lilypond.git diff --git a/lily/slur-proto-engraver.cc b/lily/slur-proto-engraver.cc index a3ced1c2c1..99e8e8ebfc 100644 --- a/lily/slur-proto-engraver.cc +++ b/lily/slur-proto-engraver.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2013 Mike Solomon + Copyright (C) 2013--2015 Mike Solomon LilyPond is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ #include "directional-element-interface.hh" #include "international.hh" #include "note-column.hh" +#include "pointer-group-interface.hh" #include "slur.hh" #include "slur-proto-engraver.hh" #include "spanner.hh" @@ -35,39 +36,43 @@ void Slur_proto_engraver::derived_mark () const { for (vsize i = start_events_.size (); i--;) - scm_gc_mark (start_events_[i]->self_scm ()); + { + scm_gc_mark (start_events_[i].slur_->self_scm ()); + if (start_events_[i].note_) + scm_gc_mark (start_events_[i].note_->self_scm ()); + } for (vsize i = stop_events_.size (); i--;) - scm_gc_mark (stop_events_[i]->self_scm ()); + { + scm_gc_mark (stop_events_[i].slur_->self_scm ()); + if (stop_events_[i].note_) + scm_gc_mark (stop_events_[i].note_->self_scm ()); + } } void -Slur_proto_engraver::internal_listen_slur (Stream_event *ev) +Slur_proto_engraver::listen_slur (Stream_event *ev, Stream_event *note) { Direction d = to_dir (ev->get_property ("span-direction")); if (d == START) - start_events_.push_back (ev); + start_events_.push_back (Event_info (ev, note)); else if (d == STOP) - stop_events_.push_back (ev); + stop_events_.push_back (Event_info (ev, note)); else ev->origin ()->warning (_f ("direction of %s invalid: %d", event_name_, int (d))); } void -Slur_proto_engraver::internal_listen_break_slur (Stream_event *ev) +Slur_proto_engraver::listen_note (Stream_event *ev) { - // if break_slur_ is set, we only keep events with direction - if (break_slur_ - && robust_scm2dir (ev->get_property ("span-direction"), CENTER)) - break_slur_ = ev; - else if (!break_slur_) - break_slur_ = ev; - else if (break_slur_ - && robust_scm2dir (break_slur_->get_property ("span-direction"), CENTER) - && robust_scm2dir (ev->get_property ("span-direction"), CENTER)) - ev->origin ()->warning (_f ("cannot set break slur with two directions")); + for (SCM arts = ev->get_property ("articulations"); + scm_is_pair (arts); arts = scm_cdr (arts)) + { + Stream_event *art = unsmob (scm_car (arts)); + if (art->in_event_class (event_symbol ())) + listen_slur (art, ev); + } } - void Slur_proto_engraver::acknowledge_note_column (Grob_info info) { @@ -76,6 +81,25 @@ Slur_proto_engraver::acknowledge_note_column (Grob_info info) Slur::add_column (slurs_[i], e); for (vsize i = end_slurs_.size (); i--;) Slur::add_column (end_slurs_[i], e); + // Now cater for slurs starting/ending at a notehead: those override + // the column bounds + if (note_slurs_[START].empty () && note_slurs_[STOP].empty ()) + return; + extract_grob_set (e, "note-heads", heads); + for (vsize i = heads.size (); i--;) + { + if (Stream_event *ev = + unsmob (heads[i]->get_property ("cause"))) + for (LEFT_and_RIGHT (d)) + { + std::pair its + = note_slurs_[d].equal_range (ev); + for (Note_slurs::const_iterator it = its.first; + it != its.second; + ++it) + it->second->set_bound (d, heads[i]); + } + } } void @@ -139,10 +163,12 @@ Slur_proto_engraver::finalize () } void -Slur_proto_engraver::create_slur (string spanner_id, Stream_event *ev_cause, Grob *g_cause, Direction dir, bool left_broken) +Slur_proto_engraver::create_slur (const string &spanner_id, Event_info evi, Grob *g_cause, Direction dir, bool left_broken) { - Grob *ccc = unsmob_grob (get_property ("currentCommandColumn")); - SCM cause = ev_cause ? ev_cause->self_scm () : g_cause->self_scm (); + Grob *ccc = left_broken + ? unsmob (get_property ("currentCommandColumn")) + : 0; // efficiency + SCM cause = evi.slur_ ? evi.slur_->self_scm () : g_cause->self_scm (); Spanner *slur = make_spanner (grob_name_, cause); slur->set_property ("spanner-id", ly_string2scm (spanner_id)); if (dir) @@ -150,26 +176,27 @@ Slur_proto_engraver::create_slur (string spanner_id, Stream_event *ev_cause, Gro if (left_broken) slur->set_bound (LEFT, ccc); slurs_.push_back (slur); + if (evi.note_) + note_slurs_[START].insert (Note_slurs::value_type (evi.note_, slur)); + if (double_property_name_ && to_boolean (get_property (double_property_name_))) - { - set_grob_direction (slur, DOWN); - slur = make_spanner (grob_name_, cause); - slur->set_property ("spanner-id", ly_string2scm (spanner_id)); - set_grob_direction (slur, UP); - if (left_broken) - slur->set_bound (LEFT, ccc); - slurs_.push_back (slur); - } - else if (g_cause && Slur::has_interface (g_cause) && left_broken) - { - g_cause->set_object ("other-half", slur->self_scm ()); - slur->set_object ("other-half", g_cause->self_scm ()); - } + { + set_grob_direction (slur, DOWN); + slur = make_spanner (grob_name_, cause); + slur->set_property ("spanner-id", ly_string2scm (spanner_id)); + set_grob_direction (slur, UP); + if (left_broken) + slur->set_bound (LEFT, ccc); + slurs_.push_back (slur); + if (evi.note_) + note_slurs_[START].insert(Note_slurs::value_type (evi.note_, slur)); + } + } bool -Slur_proto_engraver::can_create_slur (string id, vsize old_slurs, vsize *event_idx, Stream_event *ev) +Slur_proto_engraver::can_create_slur (const string &id, vsize old_slurs, vsize *event_idx, Stream_event *ev) { for (vsize j = slurs_.size (); j--;) { @@ -196,7 +223,7 @@ Slur_proto_engraver::can_create_slur (string id, vsize old_slurs, vsize *event_i if (!updown) return false; - Stream_event *c = unsmob_stream_event (slur->get_property ("cause")); + Stream_event *c = unsmob (slur->get_property ("cause")); if (!c) { @@ -226,9 +253,9 @@ Slur_proto_engraver::can_create_slur (string id, vsize old_slurs, vsize *event_i } bool -Slur_proto_engraver::try_to_end (Stream_event *ev) +Slur_proto_engraver::try_to_end (Event_info evi) { - string id = robust_scm2string (ev->get_property ("spanner-id"), ""); + string id = robust_scm2string (evi.slur_->get_property ("spanner-id"), ""); // Find the slurs that are ended with this event (by checking the spanner-id) bool ended = false; @@ -238,82 +265,49 @@ Slur_proto_engraver::try_to_end (Stream_event *ev) { ended = true; end_slurs_.push_back (slurs_[j]); + if (evi.note_) + note_slurs_[STOP].insert + (Note_slurs::value_type + (evi.note_, dynamic_cast (slurs_[j]))); slurs_.erase (slurs_.begin () + j); } } return ended; } -void -Slur_proto_engraver::break_slurs () -{ - for (vsize i = slurs_.size (); i--;) - { - Grob *ccc = unsmob_grob (get_property ("currentCommandColumn")); - Spanner *s = dynamic_cast (slurs_[i]); - s->set_bound (RIGHT, ccc); - announce_end_grob (s, SCM_EOL); - slurs_.erase (slurs_.begin () + i); - SCM maybe_dir = s->get_property_data ("direction"); - Direction dir = is_direction (maybe_dir) - ? robust_scm2dir (maybe_dir, CENTER) - : CENTER; - create_slur (robust_scm2string (s->get_property ("spanner-id"), ""), - 0, s, dir, true); - } -} - void Slur_proto_engraver::process_music () { - // break slurs that span over this column - // if break_slur_'s direction is center - if (break_slur_ - && robust_scm2dir (break_slur_->get_property ("span-direction"), CENTER) == CENTER - && unsmob_grob (get_property ("currentCommandColumn"))) - break_slurs (); - - // create broken slurs starting at this column if break_slur_ is left - vsize old_slurs = slurs_.size (); - if (break_slur_ - && robust_scm2dir (break_slur_->get_property ("span-direction"), CENTER) == LEFT - && can_create_slur ("", old_slurs, 0, break_slur_)) - create_slur ("", break_slur_, 0, - robust_scm2dir (break_slur_->get_property ("direction"), CENTER), - true); - for (vsize i = 0; i < stop_events_.size (); i++) { - string id = robust_scm2string (stop_events_[i]->get_property ("spanner-id"), ""); + string id = robust_scm2string + (stop_events_[i].slur_->get_property ("spanner-id"), ""); bool ended = try_to_end (stop_events_[i]); 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"), "")) + if (id == robust_scm2string + (stop_events_[j].slur_->get_property ("spanner-id"), "")) stop_events_.erase (stop_events_.begin () + j); } } else - stop_events_[i]->origin ()->warning (_f ("cannot end %s", object_name_)); + stop_events_[i].slur_->origin ()->warning (_f ("cannot end %s", object_name_)); } - old_slurs = slurs_.size (); + vsize old_slurs = slurs_.size (); for (vsize i = start_events_.size (); i--;) { - Stream_event *ev = start_events_[i]; + Stream_event *ev = start_events_[i].slur_; string id = robust_scm2string (ev->get_property ("spanner-id"), ""); Direction updown = to_dir (ev->get_property ("direction")); + if (can_create_slur (id, old_slurs, &i, ev)) - create_slur (id, ev, 0, updown, false); + create_slur (id, start_events_[i], 0, updown, false); } - // if BreakSlurEvent with span-dir right, we end here - if (break_slur_ - && robust_scm2dir (break_slur_->get_property ("span-direction"), CENTER) == RIGHT) - (void) try_to_end (break_slur_); - set_melisma (slurs_.size ()); } @@ -325,7 +319,7 @@ Slur_proto_engraver::set_melisma (bool) void Slur_proto_engraver::stop_translation_timestep () { - if (Grob *g = unsmob_grob (get_property ("currentCommandColumn"))) + if (Grob *g = unsmob (get_property ("currentCommandColumn"))) { for (vsize i = 0; i < end_slurs_.size (); i++) Slur::add_extra_encompass (end_slurs_[i], g); @@ -339,23 +333,19 @@ Slur_proto_engraver::stop_translation_timestep () { Spanner *s = dynamic_cast (end_slurs_[i]); if (!s->get_bound (RIGHT)) - s->set_bound (RIGHT, unsmob_grob (get_property ("currentMusicalColumn"))); - // if BreakSlurEvent with span-dir right, - // we set right bound to current command column - if (break_slur_ - && robust_scm2dir (break_slur_->get_property ("span-direction"), CENTER) == RIGHT) - s->set_bound (RIGHT, unsmob_grob (get_property ("currentCommandColumn"))); + s->set_bound (RIGHT, unsmob (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_); + note_slurs_[LEFT].clear (); + note_slurs_[RIGHT].clear (); objects_to_acknowledge_.clear (); end_slurs_.clear (); start_events_.clear (); stop_events_.clear (); - break_slur_ = 0; } // no ADD_ACKNOWLEDGER / ADD_TRANSLATOR macro calls