X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fkeep-alive-together-engraver.cc;h=6875cd022fa68cf9e57eb4328c6d5af9f81952ed;hb=97a0169312a260933246ab224e4f8b0969871dd5;hp=f4240cd3d6b8714f102aabdea96aea76931bcda4;hpb=9e205dd2ae57dce8b8e3a42f86b945517374265a;p=lilypond.git diff --git a/lily/keep-alive-together-engraver.cc b/lily/keep-alive-together-engraver.cc index f4240cd3d6..6875cd022f 100644 --- a/lily/keep-alive-together-engraver.cc +++ b/lily/keep-alive-together-engraver.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2010 Joe Neeman + Copyright (C) 2010--2015 Joe Neeman LilyPond is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,21 +22,23 @@ #include "engraver.hh" #include "grob.hh" #include "grob-array.hh" +#include "international.hh" #include "translator.icc" class Keep_alive_together_engraver: public Engraver { - vector group_spanners_; + vector group_spanners_; public: TRANSLATOR_DECLARATIONS (Keep_alive_together_engraver); - DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner); + void acknowledge_hara_kiri_group_spanner (Grob_info); virtual void finalize (); }; -Keep_alive_together_engraver::Keep_alive_together_engraver () +Keep_alive_together_engraver::Keep_alive_together_engraver (Context *c) + : Engraver (c) { } @@ -51,35 +53,98 @@ Keep_alive_together_engraver::finalize () { for (vsize i = 0; i < group_spanners_.size (); ++i) { - SCM grob_array_scm = Grob_array::make_array (); - Grob_array *ga = unsmob_grob_array (grob_array_scm); - - // It would make Hara_kiri_group_spanner::request_suicide a _little_ - // faster if we removed each grob from its own array. It seems - // unnecessary for now, though. - ga->set_array (group_spanners_); - group_spanners_[i]->set_object ("keep-alive-with", grob_array_scm); + SCM this_layer = group_spanners_[i]->get_property ("remove-layer"); + if (scm_is_false (this_layer)) + continue; + + SCM live_scm = Grob_array::make_array (); + Grob_array *live = unsmob (live_scm); + SCM dead_scm = Grob_array::make_array (); + Grob_array *dead = unsmob (dead_scm); + + for (vsize j = 0; j < group_spanners_.size (); ++j) + { + if (i == j) + continue; + + if (scm_is_symbol (this_layer)) + { + if (scm_is_eq (this_layer, ly_symbol2scm ("any"))) + { + // layer is kept alive by any other layer + live->add (group_spanners_[j]); + continue; + } + else if (scm_is_eq (this_layer, ly_symbol2scm ("above"))) + { + // layer is kept alive by the layer preceding it + if (i == j + 1) + live->add (group_spanners_[j]); + continue; + } + else if (scm_is_eq (this_layer, ly_symbol2scm ("below"))) + { + // layer is kept alive by the layer following it + if (i == j - 1) + live->add (group_spanners_[j]); + continue; + } + else + { + group_spanners_[i]->warning (_f ("unknown remove-layer value `%s'", + ly_symbol2string (this_layer).c_str ())); + continue; + } + } + + SCM that_layer = group_spanners_[j]->get_property ("remove-layer"); + + if (scm_is_false (that_layer)) + continue; + if (!scm_is_integer (this_layer)) + { + // unset layers are kept alive by all but ignored layers + live->add (group_spanners_[j]); + continue; + } + // an explicit layer is only affected by explicit layers + if (!scm_is_integer (that_layer)) + continue; + if (scm_is_true (scm_num_eq_p (that_layer, this_layer))) + live->add (group_spanners_[j]); + else if (scm_is_true (scm_less_p (that_layer, this_layer))) + dead->add (group_spanners_[j]); + } + if (!live->empty ()) + group_spanners_[i]->set_object ("keep-alive-with", live_scm); + if (!dead->empty ()) + group_spanners_[i]->set_object ("make-dead-when", dead_scm); } } -ADD_ACKNOWLEDGER (Keep_alive_together_engraver, hara_kiri_group_spanner); + +void +Keep_alive_together_engraver::boot () +{ + ADD_ACKNOWLEDGER (Keep_alive_together_engraver, hara_kiri_group_spanner); +} ADD_TRANSLATOR (Keep_alive_together_engraver, - /* doc */ - "This engraver collects all @code{Hara_kiri_group_spanner}s " - "that are created in contexts at or below its own. " - "These spanners are then tied together so that one will " - "be removed only if all are removed. For example, " - "if a @code{StaffGroup} uses this engraver, then the staves " - "in the group will all be visible as long as there is a note " - "in at least one of them.", - - /* create */ - "", - - /* read */ - "", - - /* write */ - "" - ); + /* doc */ + "This engraver collects all @code{Hara_kiri_group_spanner}s " + "that are created in contexts at or below its own. " + "These spanners are then tied together so that one will " + "be removed only if all are removed. For example, " + "if a @code{StaffGroup} uses this engraver, then the staves " + "in the group will all be visible as long as there is a note " + "in at least one of them.", + + /* create */ + "", + + /* read */ + "", + + /* write */ + "" + );