Index: lily/tie-collision-engraver.cc |
diff --git a/lily/tie-collision-engraver.cc b/lily/tie-collision-engraver.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..26258e46ad0a8c48cd22b796c8f389963d4ed1af |
--- /dev/null |
+++ b/lily/tie-collision-engraver.cc |
@@ -0,0 +1,108 @@ |
+/* |
+ This file is part of LilyPond, the GNU music typesetter. |
+ |
+ Copyright (C) 2011 Mike Solomon <mike@apollinemike.com> |
+ |
+ LilyPond is free software: you can redistribute it and/or modify |
+ it under the terms of the GNU General Public License as published by |
+ the Free Software Foundation, either version 3 of the License, or |
+ (at your option) any later version. |
+ |
+ LilyPond is distributed in the hope that it will be useful, |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ GNU General Public License for more details. |
+ |
+ You should have received a copy of the GNU General Public License |
+ along with LilyPond. If not, see <http://www.gnu.org/licenses/>. |
+*/ |
+ |
+#include "engraver.hh" |
+#include "grob.hh" |
+#include "pointer-group-interface.hh" |
+ |
+class Tie_collision_engraver : public Engraver |
+{ |
+protected: |
+ vector<Grob*> ties_; |
+ vector<Grob*> blocking_grobs_; |
+ |
+ DECLARE_ACKNOWLEDGER (time_signature); |
+ DECLARE_ACKNOWLEDGER (tie); |
+ |
+ virtual void finalize (); |
+ |
+private: |
+ bool blocking_grob_has_interface (Grob *blocking_grob, Grob *tie); |
+ |
+public: |
+ TRANSLATOR_DECLARATIONS (Tie_collision_engraver); |
+}; |
+ |
+Tie_collision_engraver::Tie_collision_engraver () {} |
+ |
+void |
+Tie_collision_engraver::finalize () |
+{ |
+ if (!blocking_grobs_.size ()) |
+ return; |
+ |
+ vector_sort (blocking_grobs_, Grob::less); |
+ vector_sort (ties_, Grob::less); |
+ vsize start = 0; |
+ |
+ for (vsize i = 0; i < ties_.size (); i++) |
+ { |
+ Grob *tie = ties_[i]; |
+ |
+ Interval_t<int> tie_spanned_rank_ = tie->spanned_rank_interval (); |
+ // Start considering grobs at the first grob whose end falls at or after the tie's beginning. |
+ while (blocking_grobs_[start]->spanned_rank_interval ()[RIGHT] < tie_spanned_rank_[LEFT]) |
+ start++; |
+ |
+ // Stop when the grob's beginning comes after the tie's end. |
+ for (vsize j = start; j < blocking_grobs_.size (); j++) |
+ { |
+ Grob *blocking_grob = blocking_grobs_[j]; |
+ |
+ Interval_t<int> blocking_grob_spanned_rank = blocking_grob->spanned_rank_interval (); |
+ if (blocking_grob_spanned_rank[LEFT] > tie_spanned_rank_[RIGHT]) |
+ break; |
+ |
+ //Only consider grobs whose end falls at or after the tie's beginning. |
+ if (blocking_grob_spanned_rank[RIGHT] >= tie_spanned_rank_[LEFT]) |
+ Pointer_group_interface::add_grob (tie, ly_symbol2scm ("blocking-grobs"), blocking_grob); |
+ } |
+ } |
+} |
+ |
+void |
+Tie_collision_engraver::acknowledge_time_signature (Grob_info i) |
+{ |
+ blocking_grobs_.push_back (i.grob ()); |
+} |
+ |
+void |
+Tie_collision_engraver::acknowledge_tie (Grob_info i) |
+{ |
+ ties_.push_back (i.grob ()); |
+} |
+ |
+#include "translator.icc" |
+ |
+ADD_ACKNOWLEDGER (Tie_collision_engraver, time_signature); |
+ADD_ACKNOWLEDGER (Tie_collision_engraver, tie); |
+ |
+ADD_TRANSLATOR (Tie_collision_engraver, |
+ /* doc */ |
+ "Help ties avoid colliding with time_signatures.", |
+ |
+ /* create */ |
+ "", |
+ |
+ /* read */ |
+ "", |
+ |
+ /* write */ |
+ "" |
+ ); |