/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 2000--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Copyright (C) 2000--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
LilyPond is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
}
Interval
-Axis_group_interface::cached_pure_height (Grob *me, int start, int end)
+Axis_group_interface::sum_partial_pure_heights (Grob *me, int start, int end)
{
Interval iv = begin_of_line_pure_height (me, start);
iv.unite (rest_of_line_pure_height (me, start, end));
}
Interval
-Axis_group_interface::rest_of_line_pure_height (Grob *me, int start, int end)
+Axis_group_interface::part_of_line_pure_height (Grob *me, bool begin, int start, int end)
{
+ Spanner *sp = dynamic_cast<Spanner*> (me);
+ SCM cache_symbol = begin
+ ? ly_symbol2scm ("begin-of-line-pure-height")
+ : ly_symbol2scm ("rest-of-line-pure-height");
+ SCM cached = sp->get_cached_pure_property (cache_symbol, start, end);
+ if (scm_is_pair (cached))
+ return robust_scm2interval (cached, Interval (0, 0));
+
SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights");
+ Interval ret;
+
+ if (!scm_is_pair (adjacent_pure_heights))
+ ret = Interval (0, 0);
+ else
+ {
+ SCM these_pure_heights = begin
+ ? scm_car (adjacent_pure_heights)
+ : scm_cdr (adjacent_pure_heights);
- if (!scm_is_pair (adjacent_pure_heights)
- || !scm_is_vector (scm_cdr (adjacent_pure_heights)))
- return Interval (0, 0);
+ if (scm_is_vector (these_pure_heights))
+ ret = combine_pure_heights (me, these_pure_heights, start, end);
+ else
+ ret = Interval (0, 0);
+ }
- return combine_pure_heights (me, scm_cdr (adjacent_pure_heights), start, end);
+ sp->cache_pure_property (cache_symbol, start, end, ly_interval2scm (ret));
+ return ret;
}
Interval
Axis_group_interface::begin_of_line_pure_height (Grob *me, int start)
{
- SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights");
-
- if (!scm_is_pair (adjacent_pure_heights)
- || !scm_is_vector (scm_car (adjacent_pure_heights)))
- return Interval (0, 0);
+ return part_of_line_pure_height (me, true, start, start + 1);
+}
- return combine_pure_heights (me, scm_car (adjacent_pure_heights), start, start+1);
+Interval
+Axis_group_interface::rest_of_line_pure_height (Grob *me, int start, int end)
+{
+ return part_of_line_pure_height (me, false, start, end);
}
Interval
return ext;
}
-
// adjacent-pure-heights is a pair of vectors, each of which has one element
// for every measure in the score. The first vector stores, for each measure,
// the combined height of the elements that are present only when the bar
// is at the beginning of a line. The second vector stores, for each measure,
// the combined height of the elements that are present only when the bar
// is not at the beginning of a line.
-
MAKE_SCHEME_CALLBACK (Axis_group_interface, adjacent_pure_heights, 1)
SCM
Axis_group_interface::adjacent_pure_heights (SCM smob)
vector<Interval> begin_line_heights;
vector<Interval> mid_line_heights;
+ vector<Interval> begin_line_staff_heights;
+ vector<Interval> mid_line_staff_heights;
begin_line_heights.resize (ranks.size () - 1);
mid_line_heights.resize (ranks.size () - 1);
bool outside_staff = scm_is_number (g->get_property ("outside-staff-priority"));
Real padding = robust_scm2double (g->get_property ("outside-staff-padding"), 0.5);
+ // When we encounter the first outside-staff grob, make a copy
+ // of the current heights to use as an estimate for the staff heights.
+ // Note that the outside-staff approximation that we use here doesn't
+ // consider any collisions that might occur between outside-staff grobs,
+ // but only the fact that outside-staff grobs may need to be raised above
+ // the staff.
+ if (outside_staff && begin_line_staff_heights.empty ())
+ {
+ begin_line_staff_heights = begin_line_heights;
+ mid_line_staff_heights = mid_line_heights;
+ }
+
// TODO: consider a pure version of get_grob_direction?
Direction d = to_dir (g->get_property_data ("direction"));
d = (d == CENTER) ? UP : d;
if (rank_span[LEFT] <= start)
{
if (outside_staff)
- begin_line_heights[j].unite_disjoint (dims, padding, d);
+ begin_line_heights[j].unite (
+ begin_line_staff_heights[j].union_disjoint (dims, padding, d));
else
begin_line_heights[j].unite (dims);
}
if (rank_span[RIGHT] > start)
{
if (outside_staff)
- mid_line_heights[j].unite_disjoint (dims, padding, d);
+ mid_line_heights[j].unite (
+ mid_line_staff_heights[j].union_disjoint (dims, padding, d));
else
mid_line_heights[j].unite (dims);
}
we can assume additivity and cache things nicely. */
Grob *p = me->get_parent (Y_AXIS);
if (p && Align_interface::has_interface (p))
- return Axis_group_interface::cached_pure_height (me, start, end);
+ return Axis_group_interface::sum_partial_pure_heights (me, start, end);
Grob *common = unsmob_grob (me->get_object ("pure-Y-common"));
extract_grob_set (me, "pure-relevant-grobs", elts);
}
return ret.smobbed_copy ();
}
-
+
SCM
Axis_group_interface::generic_group_extent (Grob *me, Axis a)
{
Axis_group_interface::calc_pure_relevant_grobs (SCM smob)
{
Grob *me = unsmob_grob (smob);
-
+
extract_grob_set (me, "elements", elts);
vector<Grob*> relevant_grobs;
}
}
+bool
+Axis_group_interface::has_outside_staff_parent (Grob *me)
+{
+ return (me
+ ? (scm_is_number (me->get_property ("outside-staff-priority"))
+ || has_outside_staff_parent (me->get_parent (Y_AXIS)))
+ : false);
+}
+
// TODO: it is tricky to correctly handle skyline placement of cross-staff grobs.
// For example, cross-staff beams cannot be formatted until the distance between
// staves is known and therefore any grobs that depend on the beam cannot be placed
Skyline_pair skylines;
for (i = 0; i < elements.size ()
&& !scm_is_number (elements[i]->get_property ("outside-staff-priority")); i++)
- if (!to_boolean (elements[i]->get_property ("cross-staff")))
+ if (!(to_boolean (elements[i]->get_property ("cross-staff")) || has_outside_staff_parent (elements[i])))
add_boxes (elements[i], x_common, y_common, &boxes, &skylines);
SCM padding_scm = me->get_property ("skyline-horizontal-padding");
SCM priority = elements[i]->get_property ("outside-staff-priority");
vector<Grob*> current_elts;
current_elts.push_back (elements[i]);
- while (i + 1 < elements.size ()
+ while (i + 1 < elements.size ()
&& scm_eq_p (elements[i+1]->get_property ("outside-staff-priority"), priority))
{
if (!to_boolean (elements[i+1]->get_property ("cross-staff")))
return ret.smobbed_copy ();
}
-MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_next_staff_spacing, 3)
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_staff_staff_spacing, 3)
SCM
-Axis_group_interface::calc_pure_next_staff_spacing (SCM smob, SCM start, SCM end)
+Axis_group_interface::calc_pure_staff_staff_spacing (SCM smob, SCM start, SCM end)
{
- return calc_maybe_pure_next_staff_spacing (unsmob_grob (smob),
- true,
- scm_to_int (start),
- scm_to_int (end));
+ return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob),
+ true,
+ scm_to_int (start),
+ scm_to_int (end));
}
-MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_next_staff_spacing, 1)
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_staff_staff_spacing, 1)
SCM
-Axis_group_interface::calc_next_staff_spacing (SCM smob)
+Axis_group_interface::calc_staff_staff_spacing (SCM smob)
{
- return calc_maybe_pure_next_staff_spacing (unsmob_grob (smob),
- false,
- 0,
- INT_MAX);
+ return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob),
+ false,
+ 0,
+ INT_MAX);
}
SCM
-Axis_group_interface::calc_maybe_pure_next_staff_spacing (Grob *me, bool pure, int start, int end)
+Axis_group_interface::calc_maybe_pure_staff_staff_spacing (Grob *me, bool pure, int start, int end)
{
Grob *grouper = unsmob_grob (me->get_object ("staff-grouper"));
if (grouper)
{
- Grob *last_in_group = Staff_grouper_interface::get_maybe_pure_last_grob (grouper, pure, start, end);
- if (me == last_in_group)
- return grouper->get_maybe_pure_property ("after-last-staff-spacing", pure, start, end);
+ bool within_group = Staff_grouper_interface::maybe_pure_within_group (grouper, me, pure, start, end);
+ if (within_group)
+ return grouper->get_maybe_pure_property ("staff-staff-spacing", pure, start, end);
else
- return grouper->get_maybe_pure_property ("between-staff-spacing", pure, start, end);
+ return grouper->get_maybe_pure_property ("staffgroup-staff-spacing", pure, start, end);
}
- return me->get_maybe_pure_property ("default-next-staff-spacing", pure, start, end);
+ return me->get_maybe_pure_property ("default-staff-staff-spacing", pure, start, end);
}
Real
// VerticalAxisGroup. We should split off a
// vertical-axis-group-interface.
/* properties */
- "X-common "
- "Y-common "
"adjacent-pure-heights "
"axes "
- "default-next-staff-spacing "
+ "default-staff-staff-spacing "
"elements "
- "inter-loose-line-spacing "
- "inter-staff-spacing "
"max-stretch "
- "non-affinity-spacing "
- "next-staff-spacing "
"no-alignment "
- "pure-Y-common "
+ "nonstaff-nonstaff-spacing "
+ "nonstaff-relatedstaff-spacing "
+ "nonstaff-unrelatedstaff-spacing "
"pure-relevant-grobs "
"pure-relevant-items "
"pure-relevant-spanners "
+ "pure-Y-common "
"staff-affinity "
"staff-grouper "
+ "staff-staff-spacing "
"system-Y-offset "
"vertical-skylines "
+ "X-common "
+ "Y-common "
);