\header {
- texidoc = "SpanBars participate in the horizontal collision system;
-the accidentals should not collide with the bar lines."
+ texidoc = "Because @code{BarLine} grobs take their
+extra-positioning-height from their neighbors via the
+@code{pure-from-neighbor-interface}, the left edge of an
+accidental should never fall to the left of the right
+edge of a bar line. This spacing should also take place when
+@code{SpanBar} grobs are present.
+"
}
-\version "2.14.0"
+\version "2.15.21"
upper = \relative c' {
\key f \minor \time 12/8
Axis_group_interface::calc_pure_relevant_grobs (SCM smob)
{
Grob *me = unsmob_grob (smob);
+ return internal_calc_pure_relevant_grobs (me, "elements");
+}
- extract_grob_set (me, "elements", elts);
+SCM
+Axis_group_interface::internal_calc_pure_relevant_grobs (Grob *me, string grob_set_name)
+{
+ extract_grob_set (me, grob_set_name.c_str (), elts);
vector<Grob *> relevant_grobs;
SCM pure_relevant_p = ly_lily_module_constant ("pure-relevant?");
"kern "
"thin-kern "
"hair-thickness "
+ "has-span-bar "
"thick-thickness "
"glyph "
"glyph-name "
DECLARE_SCHEME_CALLBACK (calc_pure_relevant_items, (SCM));
DECLARE_SCHEME_CALLBACK (calc_pure_relevant_spanners, (SCM));
DECLARE_SCHEME_CALLBACK (calc_pure_y_common, (SCM));
+ static SCM internal_calc_pure_relevant_grobs (Grob *, string);
static Interval relative_group_extent (vector<Grob *> const &list,
Grob *common, Axis);
static Interval relative_maybe_bound_group_extent (vector<Grob *> const &list,
class Pure_from_neighbor_interface
{
public:
- DECLARE_SCHEME_CALLBACK (filter_elements, (SCM));
+ DECLARE_SCHEME_CALLBACK (calc_pure_relevant_grobs, (SCM));
DECLARE_GROB_INTERFACE ();
};
static Interval get_spanned_interval (Grob *);
static void add_bar (Grob *, Grob *);
static void evaluate_glyph (Grob *);
+ static void notify_grobs_of_my_existence (Grob *);
DECLARE_SCHEME_CALLBACK (width, (SCM smob));
DECLARE_SCHEME_CALLBACK (print, (SCM));
DECLARE_SCHEME_CALLBACK (calc_glyph_name, (SCM));
class Pure_from_neighbor_engraver : public Engraver
{
- vector<Grob *> items_then_;
- vector<Grob *> items_now_;
- vector<Grob *> pures_then_;
- vector<Grob *> pures_now_;
+ vector<Grob *> pure_relevants_;
+ vector<Grob *> 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 finalize ();
};
Pure_from_neighbor_engraver::Pure_from_neighbor_engraver ()
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 ())
+ if (!Pure_from_neighbor_interface::has_interface (i.item ())
&& to_boolean (scm_call_1 (pure_relevant_p, i.item ()->self_scm ())))
- items_now_.push_back (i.item ());
+ pure_relevants_.push_back (i.item ());
}
-// note that this can get out of hand if there are lots of vertical axis groups...
-
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;
+
+ vector_sort (need_pure_heights_from_neighbors_, Grob::less);
+ vector_sort (pure_relevants_, Grob::less);
+
+ /*
+ first, clump need_pure_heights_from_neighbors into
+ vectors of grobs that have the same column.
+ */
- 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]);
+ vsize l = 0;
+ vector<vector<Grob *> > need_pure_heights_from_neighbors;
+ do
+ {
+ vector<Grob *> 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 ());
- items_then_.clear ();
- items_then_.insert (items_then_.end (), items_now_.begin (), items_now_.end ());
- items_now_.clear ();
+ /*
+ then, loop through the pure_relevants_ list, adding the items
+ to the elements of need_pure_heights_from_neighbors_ on either side.
+ */
- pures_then_.clear ();
- pures_then_.insert (pures_then_.end (), pures_now_.begin (), pures_now_.end ());
- pures_now_.clear ();
+ int pos[2] = {-1, 0};
+ for (vsize i = 0; i < pure_relevants_.size (); i++)
+ {
+ if (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++)
+ 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"
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "axis-group-interface.hh"
#include "grob.hh"
#include "grob-array.hh"
+#include "moment.hh"
+#include "paper-column.hh"
#include "pointer-group-interface.hh"
#include "pure-from-neighbor-interface.hh"
#include "spanner.hh"
#include "system.hh"
-MAKE_SCHEME_CALLBACK (Pure_from_neighbor_interface, filter_elements, 1);
+MAKE_SCHEME_CALLBACK (Pure_from_neighbor_interface, calc_pure_relevant_grobs, 1);
SCM
-Pure_from_neighbor_interface::filter_elements (SCM smob)
+Pure_from_neighbor_interface::calc_pure_relevant_grobs (SCM smob)
{
Grob *me = unsmob_grob (smob);
- extract_grob_set (me, "elements", elts);
+ extract_grob_set ((me->original () && me->original ()->is_live ()
+ ? me->original ()
+ : me),
+ "neighbors",
+ elts);
+
vector<Grob *> new_elts;
- Interval_t<int> srl = me->get_system ()->spanned_rank_interval ();
- for (vsize i = 0; i < elts.size (); i++)
- if (srl.contains (elts[i]->spanned_rank_interval ()[LEFT]))
- new_elts.push_back (elts[i]);
-
- SCM elements_scm = me->get_object ("elements");
- if (Grob_array::unsmob (elements_scm))
- {
- vector<Grob *> &arr
- = unsmob_grob_array (elements_scm)->array_reference ();
- arr = new_elts;
- }
-
- return SCM_BOOL_T;
+ new_elts.insert (new_elts.end (), elts.begin (), elts.end ());
+
+ SCM neighbors_scm = me->get_object ("neighbors");
+ if (Grob_array::unsmob (neighbors_scm))
+ {
+ vector<Grob *> &arr
+ = unsmob_grob_array (neighbors_scm)->array_reference ();
+ arr = new_elts;
+ }
+
+ return Axis_group_interface::internal_calc_pure_relevant_grobs (me, "neighbors");
}
ADD_INTERFACE (Pure_from_neighbor_interface,
"heights of the objects' neighbors.",
/* properties */
- "elements-filtered "
+ "neighbors "
"pure-relevant-grobs "
"pure-Y-common "
);
SCM vis = bars_[0]->internal_get_property (vissym);
if (ly_is_equal (spanbar_->internal_get_property (vissym), vis))
spanbar_->set_property (vissym, vis);
-
+ Span_bar::notify_grobs_of_my_existence (spanbar_);
spanbar_ = 0;
}
bars_.resize (0);
#include "span-bar.hh"
#include "engraver.hh"
+/*
+ Note that span bar stubs 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<Grob *> spanbars_;
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)
{
gi.rerouting_daddy_context_ = affected_contexts[j];
announce_grob (gi);
if (!keep_extent[j])
- it->set_property ("Y-extent", ly_interval2scm (Interval (infinity_f, -infinity_f)));
+ it->suicide ();//it->set_property ("Y-extent", ly_interval2scm (Interval (infinity_f, -infinity_f)));
}
}
spanbars_.clear ();
return ly_string2scm (type);
}
+void
+Span_bar::notify_grobs_of_my_existence (Grob *me)
+{
+ extract_grob_set (me, "elements", elts);
+ vector<Grob *> sortable (elts.begin (), elts.end ());
+ vector_sort (sortable, Grob::vertical_less);
+ for (vsize i = 0; i < sortable.size (); i++)
+ sortable[i]->set_property ("has-span-bar",
+ scm_cons (scm_from_bool (i != 0),
+ scm_from_bool (i != sortable.size () - 1)));
+}
+
Interval
Span_bar::get_spanned_interval (Grob *me)
{
Real staff_space = Staff_symbol_referencer::staff_space (g);
return scm_from_double (staff_space);
}
+
+LY_DEFINE (ly_staff_symbol_staff_radius, "ly:staff-symbol-staff-radius",
+ 1, 0, 0, (SCM grob),
+ "Returns the radius of the staff associated with"
+ " @var{grob}.")
+{
+ LY_ASSERT_SMOB (Grob, grob, 1);
+ Grob *g = unsmob_grob (grob);
+ Real staff_radius = Staff_symbol_referencer::staff_radius (g);
+ return scm_from_double (staff_radius);
+}
\consists "Output_property_engraver"
\consists "Bar_engraver"
+ \consists "Pure_from_neighbor_engraver"
%% Bar_engraver must be first so default bars aren't overwritten
%% with empty ones.
the vertical edges: @code{(@var{left-height} . @var{right-height})}.")
(edge-text ,pair? "A pair specifying the texts to be set at the
edges: @code{(@var{left-text} . @var{right-text})}.")
- (elements-filtered ,boolean? "Callback to filter an element list.")
(round-up-exceptions ,list? "A list of pairs where car is the numerator
and cdr the denominator of a moment. Each pair in this list means that
the multi-measure rests of the corresponding length will be rounded up to
shift dotted up-note to the right, rather than shifting just the
dot.")
-
;;
;; r
;;
column.")
(grace-spacing ,ly:grob? "A run of grace notes.")
+ (has-span-bar ,pair? "A pair of booleans indicating whether a a span bar
+is drawn above, or respectively below, this staff.")
(heads ,ly:grob-array? "An array of note heads.")
(items-worth-living ,ly:grob-array? "An array of interesting items. If
(melody-spanner ,ly:grob? "The @code{MelodyItem} object for a stem.")
+ (neighbors ,ly:grob-array? "The X-axis neighbors of a grob. Used by the
+pure-from-neighbor-interface to determine various grob heights.")
+
(normal-stems ,ly:grob-array? "An array of visible stems.")
(note-columns ,ly:grob-array? "An array of @code{NoteColumn} grobs.")
(note-head ,ly:grob? "A single note head.")
(break-align-anchor . ,ly:bar-line::calc-anchor)
(break-align-symbol . staff-bar)
(break-visibility . ,bar-line::calc-break-visibility)
+ (extra-spacing-height . ,pure-from-neighbor-interface::account-for-span-bar)
(gap . 0.4)
(glyph . "|")
(glyph-name . ,bar-line::calc-glyph-name)
(right-edge . (extra-space . 0.0))))
(stencil . ,ly:bar-line::print)
(meta . ((class . Item)
+ (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
+ (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
(interfaces . (bar-line-interface
break-aligned-interface
- font-interface))))))
+ font-interface
+ pure-from-neighbor-interface))))))
(BarNumber
. (
(break-align-anchor . ,ly:break-aligned-interface::calc-extent-aligned-anchor)
(break-align-symbol . clef)
(break-visibility . ,begin-of-line-visible)
+ ;(extra-spacing-height . ,pure-from-neighbor-interface::extra-spacing-height)
(glyph-name . ,ly:clef::calc-glyph-name)
(non-musical . #t)
(space-alist . ((cue-clef . (extra-space . 2.0))
(stencil . ,ly:clef::print)
(Y-offset . ,ly:staff-symbol-referencer::callback)
(meta . ((class . Item)
+ ;(object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
+ ; (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
(interfaces . (break-aligned-interface
clef-interface
font-interface
+ ;pure-from-neighbor-interface
staff-symbol-referencer-interface))))))
(ClusterSpanner
(break-align-anchor . ,ly:break-aligned-interface::calc-extent-aligned-anchor)
(break-align-symbol . cue-clef)
(break-visibility . ,begin-of-line-visible)
+ ;(extra-spacing-height . ,pure-from-neighbor-interface::extra-spacing-height)
(font-size . -4)
(glyph-name . ,ly:clef::calc-glyph-name)
(non-musical . #t)
(stencil . ,ly:clef::print)
(Y-offset . ,ly:staff-symbol-referencer::callback)
(meta . ((class . Item)
+ ;(object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
+ ; (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
(interfaces . (break-aligned-interface
clef-interface
font-interface
+ ;pure-from-neighbor-interface
staff-symbol-referencer-interface))))))
(CueEndClef
(break-align-anchor . ,ly:break-aligned-interface::calc-extent-aligned-anchor)
(break-align-symbol . cue-end-clef)
(break-visibility . ,begin-of-line-invisible)
+ ;(extra-spacing-height . ,pure-from-neighbor-interface::extra-spacing-height)
(font-size . -4)
(glyph-name . ,ly:clef::calc-glyph-name)
(non-musical . #t)
(stencil . ,ly:clef::print)
(Y-offset . ,ly:staff-symbol-referencer::callback)
(meta . ((class . Item)
+ ;(object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
+ ; (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
(interfaces . (break-aligned-interface
clef-interface
font-interface
+ ;pure-from-neighbor-interface
staff-symbol-referencer-interface))))))
(Custos
(first-note . (fixed-space . 2.5))))
(stencil . ,ly:key-signature-interface::print)
(extra-spacing-width . (0.0 . 1.0))
+ ;(extra-spacing-height . ,pure-from-neighbor-interface::extra-spacing-height-including-staff)
(Y-offset . ,ly:staff-symbol-referencer::callback)
(meta . ((class . Item)
+ ;(object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
+ ; (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
(interfaces . (break-aligned-interface
font-interface
key-signature-interface
+ ;pure-from-neighbor-interface
staff-symbol-referencer-interface))))))
(non-musical . #t)
(stencil . ,ly:span-bar::print)
(X-extent . ,ly:span-bar::width)
- (Y-extent . #f)
+ (Y-extent . (+inf.0 . -inf.0))
(meta . ((class . Item)
(interfaces . (bar-line-interface
font-interface
(SpanBarStub
. (
- (elements-filtered . ,ly:pure-from-neighbor-interface::filter-elements)
(X-extent . ,grob::x-parent-width)
- (Y-extent . ,span-bar-stub::height)
+ (Y-extent . ,(ly:make-unpure-pure-container #f ly:axis-group-interface::pure-height))
(meta . ((class . Item)
(object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
- (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
+ (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
(interfaces . (pure-from-neighbor-interface))))))
(StaffGrouper
(break-align-symbol . time-signature)
(break-align-anchor-alignment . ,LEFT)
(break-visibility . ,all-visible)
+ ;(extra-spacing-height . ,pure-from-neighbor-interface::extra-spacing-height-including-staff)
(extra-spacing-height . (-1.0 . 1.0))
(extra-spacing-width . (0.0 . 0.8))
(non-musical . #t)
(stencil . ,ly:time-signature::print)
(style . C)
(meta . ((class . Item)
+ ;(object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
+ ; (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
(interfaces . (break-aligned-interface
font-interface
+ ;pure-from-neighbor-interface
time-signature-interface))))))
(TrillPitchAccidental
(,ly:side-position-interface::y-aligned-side . ,ly:side-position-interface::pure-y-aligned-side)
(,ly:slur::height . ,ly:slur::pure-height)
(,ly:slur::outside-slur-callback . ,ly:slur::pure-outside-slur-callback)
- (,span-bar-stub::height . ,ly:axis-group-interface::pure-height)
(,ly:stem::calc-stem-begin-position . ,ly:stem::pure-calc-stem-begin-position)
(,ly:stem::calc-stem-end-position . ,ly:stem::pure-calc-stem-end-position)
(,stem::length . ,stem::pure-length)
(equal? (ly:item-break-dir g) RIGHT))
(ly:grob-translate-axis! g 3.5 X)))
-(define-public (span-bar-stub::height grob)
- (ly:grob-property grob 'elements-filtered)
- (ly:axis-group-interface::height grob))
+(define-public (pure-from-neighbor-interface::extra-spacing-height grob)
+ (let* ((height (ly:grob::stencil-height grob))
+ (from-neighbors (interval-union
+ height
+ (ly:axis-group-interface::pure-height
+ grob
+ 0
+ 10000000))))
+ (coord-operation - from-neighbors height)))
+
+(define-public (pure-from-neighbor-interface::account-for-span-bar grob)
+ (define (other-op x) (x (cons cdr car)))
+ (let* ((esh (pure-from-neighbor-interface::extra-spacing-height grob))
+ (hsb (ly:grob-property grob 'has-span-bar)))
+ (if (pair? hsb)
+ (cons-map
+ (lambda (x)
+ (if (and ((other-op x) hsb)
+ (not (and (eq? x car)
+ (not (ly:grob-property grob 'allow-span-bar)))))
+ (x esh)
+ 0))
+ (cons car cdr))
+ '(0 . 0))))
+
+(define (pure-from-neighbor-interface::extra-spacing-height-including-staff grob)
+ (let ((esh (pure-from-neighbor-interface::extra-spacing-height grob))
+ (to-staff (coord-operation -
+ (interval-widen
+ '(0 . 0)
+ (ly:staff-symbol-staff-radius grob))
+ (ly:grob::stencil-height grob))))
+ (interval-union esh to-staff)))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tuplets