From e0249b3f7eba24ce0f911dfb1c97e70da6a8021c Mon Sep 17 00:00:00 2001 From: Carl Sorensen Date: Fri, 17 Dec 2010 16:14:02 -0700 Subject: [PATCH] Add regression test Fix issue 1290 Add optional horizontal-padding argument to Skyline::distance call If horizontal padding is non-zero, the padding will be added for making the distance comparison. Padding is added during System comparison, so Systems can be farther apart than staves within systems. Add default value of skyline-horizontal-padding to the System grob. Add regression test for this behavior, which includes an override. --- .../regression/skyline-horizontal-padding.ly | 27 ++++++++ lily/include/skyline.hh | 7 ++- lily/page-layout-problem.cc | 8 ++- lily/skyline.cc | 63 ++++++++++++++++--- scm/define-grobs.scm | 1 + 5 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 input/regression/skyline-horizontal-padding.ly diff --git a/input/regression/skyline-horizontal-padding.ly b/input/regression/skyline-horizontal-padding.ly new file mode 100644 index 0000000000..1bb47de003 --- /dev/null +++ b/input/regression/skyline-horizontal-padding.ly @@ -0,0 +1,27 @@ +\version "2.13.46" + +\header { + texidoc = " +The skyline-horizontal-padding property can be set for System +in order to keep systems from being spaced too closely together. +In this example, the low notes from a system should not be +interleaved with the high notes from the next system. +" +} + +\book { + \score { + { + \override Staff.TimeSignature #'stencil = ##f + \repeat unfold 3 { c' c' \break} + } + \layout { + indent = 0 + ragged-right = ##t + \context { + \Score + \override System #'skyline-horizontal-padding = #1.5 + } + } + } +} diff --git a/lily/include/skyline.hh b/lily/include/skyline.hh index a11b21dde6..93b6e11556 100644 --- a/lily/include/skyline.hh +++ b/lily/include/skyline.hh @@ -53,7 +53,7 @@ class Skyline private: list buildings_; Direction sky_; - + void internal_merge_skyline (list*, list*, list *const result); list internal_build_skyline (list*, Real, Axis, Direction); @@ -63,10 +63,11 @@ private: public: Skyline (); Skyline (Skyline const &src); + Skyline (Skyline const &src, Real horizon_padding, Axis a); Skyline (Direction sky); Skyline (vector const &bldgs, Real horizon_padding, Axis a, Direction sky); Skyline (Box const &b, Real horizon_padding, Axis a, Direction sky); - + vector to_points (Axis) const; void merge (Skyline const &); void insert (Box const &, Real horizon_padding, Axis); @@ -74,7 +75,7 @@ public: void print_points () const; void raise (Real); void shift (Real); - Real distance (Skyline const &) const; + Real distance (Skyline const &, Real horizon_padding = 0) const; Real height (Real airplane) const; Real max_height () const; void set_minimum_height (Real height); diff --git a/lily/page-layout-problem.cc b/lily/page-layout-problem.cc index 673278f69c..8be181ae95 100644 --- a/lily/page-layout-problem.cc +++ b/lily/page-layout-problem.cc @@ -201,7 +201,13 @@ Page_layout_problem::append_system (System *sys, Spring const& spring, Real inde up_skyline.shift (indent); down_skyline.shift (indent); - Real minimum_distance = up_skyline.distance (bottom_skyline_) + padding; + /* + We need to call distance with skyline-horizontal-padding because + the system skyline-horizontal-padding is not added during the creation + of an individual staff. So we add the padding for the distance check + at the time of adding in the system. + */ + Real minimum_distance = up_skyline.distance (bottom_skyline_, robust_scm2double (sys->get_property ("skyline-horizontal-padding"), 0)) + padding; Spring spring_copy = spring; spring_copy.ensure_min_distance (minimum_distance); diff --git a/lily/skyline.cc b/lily/skyline.cc index d8105e669b..b28c6ff662 100644 --- a/lily/skyline.cc +++ b/lily/skyline.cc @@ -119,7 +119,7 @@ Building::precompute (Real start, Real start_height, Real end_height, Real end) y_intercept_ = start_height - slope_ * start; } -Real +Real Building::height (Real x) const { return isinf (x) ? y_intercept_ : slope_*x + y_intercept_; @@ -248,7 +248,7 @@ single_skyline (Building b, Real start, Real horizon_padding, list *co -infinity_f, infinity_f)); if (sloped_neighbours) ret->push_front (b.sloped_neighbour (start, horizon_padding, RIGHT)); - + if (b.end_ > start + EPS) ret->push_front (b); @@ -367,7 +367,7 @@ Skyline::Skyline () Skyline::Skyline (Skyline const &src) { sky_ = src.sky_; - + /* doesn't a list's copy constructor do this? -- jneem */ for (list::const_iterator i = src.buildings_.begin (); i != src.buildings_.end (); i++) @@ -382,6 +382,37 @@ Skyline::Skyline (Direction sky) empty_skyline (&buildings_); } +/* + build padded skyline from an existing skyline with padding + added to it. +*/ + +Skyline::Skyline (Skyline const &src, Real horizon_padding, Axis a) +{ + /* + We extract boxes from the skyline, then build a new skyline from + the boxes. + A box is created for every horizontal portion of the skyline + Because skylines are defined positive, and then inverted if they + are to be down-facing, we create the new skyline in the UP + direction, then give it the down direction if needed. + */ + Real start = -infinity_f; + list boxes; + + // establish a baseline box + boxes.push_back (Box (Interval (-infinity_f, infinity_f), + Interval (0, 0))); + list::const_iterator end = src.buildings_.end (); + for (list::const_iterator i = src.buildings_.begin (); i != end; start=i->end_, i++ ) + if ((i->slope_ == 0) && !isinf (i->y_intercept_)) + boxes.push_back (Box (Interval (start, i->end_), + Interval (-infinity_f , i->y_intercept_))); + buildings_ = internal_build_skyline (&boxes, horizon_padding, X_AXIS, UP); + sky_ = src.sky_; +} + + /* build skyline from a set of boxes. If horizon_padding > 0, expand all the boxes by that amount and add 45-degree sloped boxes to the edges of each box (of @@ -404,7 +435,7 @@ Skyline::Skyline (vector const &boxes, Real horizon_padding, Axis horizon_a if (iv.length () > EPS && !boxes[i][vert_axis].is_empty ()) filtered_boxes.push_front (boxes[i]); } - + buildings_ = internal_build_skyline (&filtered_boxes, horizon_padding, horizon_axis, sky); } @@ -470,15 +501,31 @@ Skyline::shift (Real s) } Real -Skyline::distance (Skyline const &other) const +Skyline::distance (Skyline const &other, Real horizon_padding) const { assert (sky_ == -other.sky_); - list::const_iterator i = buildings_.begin (); - list::const_iterator j = other.buildings_.begin (); + + Skyline const *padded_this = this; + Skyline const *padded_other = &other; + + /* + For systems, padding is not added at creation time. Padding is + added to AxisGroup objects when outside-staff objects are added. + Thus, when we want to place systems with horizontal padding, + we do it at distance calculation time. + */ + if (horizon_padding != 0.0) + { + padded_this = new Skyline (*padded_this, horizon_padding, X_AXIS); + padded_other = new Skyline (*padded_other, horizon_padding, X_AXIS); + } + + list::const_iterator i = padded_this->buildings_.begin (); + list::const_iterator j = padded_other->buildings_.begin (); Real dist = -infinity_f; Real start = -infinity_f; - while (i != buildings_.end () && j != other.buildings_.end ()) + while (i != padded_this->buildings_.end () && j != padded_other->buildings_.end ()) { Real end = min (i->end_, j->end_); Real start_dist = i->height (start) + j->height (start); diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index ff076f8d15..01a07313b4 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -1937,6 +1937,7 @@ . ( (adjacent-pure-heights . ,ly:axis-group-interface::adjacent-pure-heights) (axes . (,X ,Y)) + (skyline-horizontal-padding . 0.5) (vertical-skylines . ,ly:axis-group-interface::calc-skylines) (X-extent . ,ly:axis-group-interface::width) (Y-extent . ,ly:system::height) -- 2.39.2