X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fspan-bar-stub-engraver.cc;h=914e73ed4b89ebecc735e1c531a53be3be8eaed1;hb=97a0169312a260933246ab224e4f8b0969871dd5;hp=47b0c1a4d55d007cadd2f40025119b3015ab978b;hpb=dc71d81b8b6846a01985d3c9eec422607bd076c8;p=lilypond.git diff --git a/lily/span-bar-stub-engraver.cc b/lily/span-bar-stub-engraver.cc index 47b0c1a4d5..914e73ed4b 100644 --- a/lily/span-bar-stub-engraver.cc +++ b/lily/span-bar-stub-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 @@ -17,33 +17,61 @@ along with LilyPond. If not, see . */ -#include #include #include "align-interface.hh" -#include "bar-line.hh" #include "context.hh" #include "grob.hh" +#include "grob-properties.hh" #include "item.hh" #include "pointer-group-interface.hh" -#include "span-bar.hh" #include "engraver.hh" +#include "translator.icc" + +/* + The Span_bar_stub_engraver creates SpanBarStub grobs in the contexts + that a grouping context contains. For example, if a PianoStaff contains + two Staffs, a Dynamics, and a Lyrics, SpanBarStubs will be created in + all contexts that do not have bar lines (Dynamics and Lyrics). + + We only want to create these SpanBarStubs in contexts that the SpanBar + traverses. However, Contexts do not contain layout information and it + is thus difficult to know if they will eventually be above or below other + Contexts. To determine this we use the VerticalAxisGroup created in the + Context. We relate VerticalAxisGroups to Contexts in the variable + axis_groups_ and weed out unused contexts after each translation timestep. + + Note that SpanBarStubs exist for pure height calculations ONLY. + They should never be visually present on the page and should never + be engraved in contexts where BarLines are engraved. +*/ + class Span_bar_stub_engraver : public Engraver { vector spanbars_; - map axis_groups_; + SCM axis_groups_; public: TRANSLATOR_DECLARATIONS (Span_bar_stub_engraver); protected: - DECLARE_ACKNOWLEDGER (span_bar); - DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner); + void acknowledge_span_bar (Grob_info); + void acknowledge_hara_kiri_group_spanner (Grob_info); void process_acknowledged (); + void stop_translation_timestep (); + virtual void derived_mark () const; }; -Span_bar_stub_engraver::Span_bar_stub_engraver () +Span_bar_stub_engraver::Span_bar_stub_engraver (Context *c) + : Engraver (c) { + axis_groups_ = SCM_EOL; +} + +void +Span_bar_stub_engraver::derived_mark () const +{ + scm_gc_mark (axis_groups_); } void @@ -52,12 +80,10 @@ Span_bar_stub_engraver::acknowledge_span_bar (Grob_info i) spanbars_.push_back (i.grob ()); } -// note that this can get out of hand if there are lots of vertical axis groups... - void Span_bar_stub_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i) { - axis_groups_[i.grob ()] = i.context (); + axis_groups_ = scm_cons (scm_cons (i.grob ()->self_scm (), i.context ()->self_scm ()), axis_groups_); } void @@ -66,12 +92,15 @@ Span_bar_stub_engraver::process_acknowledged () if (!spanbars_.size ()) return; - Grob *vertical_alignment = Grob::get_root_vertical_alignment ((*axis_groups_.begin ()).first); + if (!scm_is_pair (axis_groups_)) + { + programming_error ("At least one vertical axis group needs to be created in the first time step."); + return; + } + Grob *vertical_alignment = Grob::get_root_vertical_alignment (unsmob (scm_caar (axis_groups_))); if (!vertical_alignment) // we are at the beginning of a score, so no need for stubs return; - extract_grob_set (vertical_alignment, "elements", elts); - for (vsize i = 0; i < spanbars_.size (); i++) { extract_grob_set (spanbars_[i], "elements", bars); @@ -85,8 +114,16 @@ Span_bar_stub_engraver::process_acknowledged () vector affected_contexts; vector y_parents; vector keep_extent; - for (vsize j = 0; j < elts.size (); j++) + for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s)) { + Context *c = unsmob (scm_cdar (s)); + Grob *g = unsmob (scm_caar (s)); + if (!c || !g) + continue; + if (c->is_removable ()) + continue; + + vsize j = Grob::get_vertical_axis_group_index (g); if (j > bar_axis_indices[0] && j < bar_axis_indices.back () && find (bar_axis_indices.begin (), bar_axis_indices.end (), j) == bar_axis_indices.end ()) @@ -97,37 +134,55 @@ Span_bar_stub_engraver::process_acknowledged () break; k--; - keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar"))); - Context *c = axis_groups_[elts[j]]; if (c && c->get_parent_context ()) { - y_parents.push_back (elts[j]); + keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar"))); + y_parents.push_back (g); affected_contexts.push_back (c); } } } - reverse (affected_contexts); // from bottom to top - reverse (y_parents); // from bottom to top - reverse (keep_extent); // from bottom to top + for (vsize j = 0; j < affected_contexts.size (); j++) { - Item *it = new Item (updated_grob_properties (affected_contexts[j], ly_symbol2scm ("SpanBarStub"))); + Item *it = new Item (Grob_property_info (affected_contexts[j], ly_symbol2scm ("SpanBarStub")).updated ()); it->set_parent (spanbars_[i], X_AXIS); Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ()); - gi.rerouting_daddy_context_ = affected_contexts[j]; - announce_grob (gi); + announce_grob (gi, affected_contexts[j]); if (!keep_extent[j]) - it->set_property ("Y-extent", ly_interval2scm (Interval (infinity_f, -infinity_f))); + it->suicide (); } } + spanbars_.clear (); } -#include "translator.icc" +// removes all unused contexts +void +Span_bar_stub_engraver::stop_translation_timestep () +{ + SCM axis_groups = SCM_EOL; + for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s)) + { + Context *c = unsmob (scm_cdar (s)); + Grob *g = unsmob (scm_caar (s)); + if (!c || !g) + continue; + if (c->is_removable ()) + continue; + axis_groups = scm_cons (scm_car (s), axis_groups); + } + axis_groups_ = axis_groups; +} + +void +Span_bar_stub_engraver::boot () +{ + ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar); + ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner); +} -ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar); -ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner); ADD_TRANSLATOR (Span_bar_stub_engraver, /* doc */ "Make stubs for span bars in all contexts that the span bars cross.",