X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fpure-from-neighbor-engraver.cc;h=cea3936161c4c62357250ca9ca664b7a00275bcb;hb=5d84bfad4626892bcffd05adcced53c8a2329047;hp=14d94730b8e48d42a813bd66b25c1a5523fb885d;hpb=4f49b000d6e257724e311b406e2346b8388c1f0e;p=lilypond.git diff --git a/lily/pure-from-neighbor-engraver.cc b/lily/pure-from-neighbor-engraver.cc index 14d94730b8..cea3936161 100644 --- a/lily/pure-from-neighbor-engraver.cc +++ b/lily/pure-from-neighbor-engraver.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2011 Mike Solomon + Copyright (C) 2011--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 @@ -26,69 +26,124 @@ #include "pure-from-neighbor-interface.hh" #include "engraver.hh" +#include "translator.icc" + class Pure_from_neighbor_engraver : public Engraver { - vector items_then_; - vector items_now_; - vector pures_then_; - vector pures_now_; + vector pure_relevants_; + vector need_pure_heights_from_neighbors_; public: TRANSLATOR_DECLARATIONS (Pure_from_neighbor_engraver); protected: - DECLARE_ACKNOWLEDGER (pure_from_neighbor); - DECLARE_ACKNOWLEDGER (item); - void stop_translation_timestep (); + void acknowledge_pure_from_neighbor (Grob_info); + void acknowledge_item (Grob_info); + void finalize (); }; -Pure_from_neighbor_engraver::Pure_from_neighbor_engraver () +Pure_from_neighbor_engraver::Pure_from_neighbor_engraver (Context *c) + : Engraver (c) { } void Pure_from_neighbor_engraver::acknowledge_item (Grob_info i) { - SCM pure_relevant_p = ly_lily_module_constant ("pure-relevant?"); - if (!Pure_from_neighbor_interface::has_interface (i.grob ()) - && to_boolean (scm_call_1 (pure_relevant_p, i.item ()->self_scm ()))) - items_now_.push_back (i.item ()); + if (!has_interface (i.item ())) + pure_relevants_.push_back (i.item ()); } -// note that this can get out of hand if there are lots of vertical axis groups... +bool +in_same_column (Grob *g1, Grob *g2) +{ + return (g1->spanned_rank_interval ()[LEFT] + == g2->spanned_rank_interval ()[LEFT]) + && (g1->spanned_rank_interval ()[RIGHT] + == g2->spanned_rank_interval ()[RIGHT]) + && (g1->spanned_rank_interval ()[LEFT] + == g1->spanned_rank_interval ()[RIGHT]); +} void Pure_from_neighbor_engraver::acknowledge_pure_from_neighbor (Grob_info i) { - pures_now_.push_back (i.item ()); + need_pure_heights_from_neighbors_.push_back (i.item ()); } void -Pure_from_neighbor_engraver::stop_translation_timestep () +Pure_from_neighbor_engraver::finalize () { - if (pures_now_.size ()) - { - for (vsize i = 0; i < pures_now_.size (); i++) - for (vsize j = 0; j < items_then_.size (); j++) - Pointer_group_interface::add_grob (pures_now_[i], ly_symbol2scm ("elements"), items_then_[j]); + if (!need_pure_heights_from_neighbors_.size ()) + return; - for (vsize i = 0; i < pures_then_.size (); i++) - for (vsize j = 0; j < items_now_.size (); j++) - Pointer_group_interface::add_grob (pures_then_[i], ly_symbol2scm ("elements"), items_now_[j]); + vector_sort (need_pure_heights_from_neighbors_, Grob::less); + vector_sort (pure_relevants_, Grob::less); - items_then_.clear (); - items_then_.insert (items_then_.end (), items_now_.begin (), items_now_.end ()); - items_now_.clear (); + /* + first, clump need_pure_heights_from_neighbors into + vectors of grobs that have the same column. + */ - pures_then_.clear (); - pures_then_.insert (pures_then_.end (), pures_now_.begin (), pures_now_.end ()); - pures_now_.clear (); + vsize l = 0; + vector > need_pure_heights_from_neighbors; + do + { + vector temp; + temp.push_back (need_pure_heights_from_neighbors_[l]); + for (; + (l < need_pure_heights_from_neighbors_.size () - 1 + && ((need_pure_heights_from_neighbors_[l] + ->spanned_rank_interval ()[LEFT]) + == (need_pure_heights_from_neighbors_[l + 1] + ->spanned_rank_interval ()[LEFT]))); + l++) + temp.push_back (need_pure_heights_from_neighbors_[l + 1]); + need_pure_heights_from_neighbors.push_back (temp); + l++; } + while (l < need_pure_heights_from_neighbors_.size ()); + + /* + then, loop through the pure_relevants_ list, adding the items + to the elements of need_pure_heights_from_neighbors_ on either side. + */ + + int pos[2] = { -1, 0}; + for (vsize i = 0; i < pure_relevants_.size (); i++) + { + while (pos[1] < (int) need_pure_heights_from_neighbors.size () + && (pure_relevants_[i]->spanned_rank_interval ()[LEFT] + > (need_pure_heights_from_neighbors[pos[1]][0] + ->spanned_rank_interval ()[LEFT]))) + { + pos[0] = pos[1]; + pos[1]++; + } + for (int j = 0; j < 2; j++) + if (pos[j] >= 0 && pos[j] + < (int) need_pure_heights_from_neighbors.size ()) + for (vsize k = 0; + k < need_pure_heights_from_neighbors[pos[j]].size (); + k++) + if (!in_same_column (need_pure_heights_from_neighbors[pos[j]][k], + pure_relevants_[i])) + Pointer_group_interface::add_grob + (need_pure_heights_from_neighbors[pos[j]][k], + ly_symbol2scm ("neighbors"), + pure_relevants_[i]); + } + + need_pure_heights_from_neighbors_.clear (); + pure_relevants_.clear (); } -#include "translator.icc" +void +Pure_from_neighbor_engraver::boot () +{ + ADD_ACKNOWLEDGER (Pure_from_neighbor_engraver, item); + ADD_ACKNOWLEDGER (Pure_from_neighbor_engraver, pure_from_neighbor); +} -ADD_ACKNOWLEDGER (Pure_from_neighbor_engraver, item); -ADD_ACKNOWLEDGER (Pure_from_neighbor_engraver, pure_from_neighbor); ADD_TRANSLATOR (Pure_from_neighbor_engraver, /* doc */ "Coordinates items that get their pure heights from their neighbors.",