cd $resultdir
-echo 'foo = \new Staff \new Voice \repeat unfold 50 \relative { c4 d8[ d16( e]~ e16[ e e) f] g8 }
+cat > long-score.ly << EOF
+\version "2.10.0"
+foo = \new Staff \new Voice \repeat unfold 50 \relative { c4 d8[ d16( e]~ e16[ e e) f] g8 }
\new ChoirStaff <<
\foo \foo \foo \foo
\foo \foo \foo \foo
->>' > long-score.ly
+>>
+EOF
rm gmon.sum
return SCM_UNSPECIFIED;
}
+/* This callback exists for the sole purpose of allowing us to override
+ its pure equivalent to accidental-interface::pure-height */
+MAKE_SCHEME_CALLBACK (Accidental_interface, height, 1);
+SCM
+Accidental_interface::height (SCM smob)
+{
+ return Grob::stencil_height (smob);
+}
+
MAKE_SCHEME_CALLBACK (Accidental_interface, pure_height, 3);
SCM
Accidental_interface::pure_height (SCM smob, SCM start_scm, SCM)
Grob::pure_height (Grob *refp, int start, int end)
{
SCM proc = get_property_data (ly_symbol2scm ("Y-extent"));
- SCM pure_proc = get_property_data (ly_symbol2scm ("pure-Y-extent"));
- SCM iv_scm;
-
- if (ly_is_procedure (pure_proc))
- iv_scm = scm_apply_3 (pure_proc,
- self_scm (),
- scm_from_int (start),
- scm_from_int (end), SCM_EOL);
- else
- iv_scm = call_pure_function (proc,
- scm_list_1 (self_scm ()),
- start, end);
-
+ SCM iv_scm = call_pure_function (proc,
+ scm_list_1 (self_scm ()),
+ start, end);
Interval iv = robust_scm2interval (iv_scm, Interval (0, 0));
Real offset = pure_relative_y_coordinate (refp, start, end);
"outside-staff-horizontal-padding "
"outside-staff-padding "
"outside-staff-priority "
- "pure-Y-extent "
"rotation "
"springs-and-rods "
"staff-symbol "
DECLARE_SCHEME_CALLBACK (print, (SCM));
DECLARE_SCHEME_CALLBACK (calc_stencils, (SCM));
DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM));
+ DECLARE_SCHEME_CALLBACK (height, (SCM));
DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM));
DECLARE_GROB_INTERFACE();
bool conceals (Building const &other) const;
bool sane () const;
Building sloped_neighbour (Real horizon_padding, Direction d) const;
+
+ bool operator< (Building const &other)
+ {
+ return iv_[LEFT] < other.iv_[LEFT];
+ }
};
class Skyline
void internal_merge_skyline (list<Building>*, list<Building>*,
list<Building> *const result);
- void internal_build_skyline (list<Building>*, list<Building> *const result);
- bool is_legal_skyline () const;
+ list<Building> internal_build_skyline (list<Building>*);
DECLARE_SIMPLE_SMOBS(Skyline);
public:
*/
#include "skyline.hh"
+#include <deque>
#include "ly-smobs.icc"
}
}
-bool
-Skyline::is_legal_skyline () const
+static bool
+is_legal_skyline (list<Building> const &buildings)
{
list<Building>::const_iterator i;
Real last_x = -infinity_f;
- for (i = buildings_.begin (); i != buildings_.end (); i++)
+ for (i = buildings.begin (); i != buildings.end (); i++)
{
if (i->iv_[LEFT] != last_x)
return false;
-infinity_f, b.iv_[LEFT]));
}
-void
-Skyline::internal_build_skyline (list<Building> *buildings, list<Building> *const result)
+/* remove a non-overlapping set of buildings from BUILDINGS and build a skyline
+ out of them */
+static list<Building>
+non_overlapping_skyline (list<Building> *const buildings)
+{
+ list<Building> result;
+ Real last_end = -infinity_f;
+ list<Building>::iterator i = buildings->begin ();
+ while (i != buildings->end ())
+ {
+ if (approx_less_than (i->iv_[LEFT], last_end))
+ {
+ i++;
+ continue;
+ }
+
+ if (approx_greater_than (i->iv_[LEFT], last_end))
+ result.push_back (Building (last_end, -infinity_f, -infinity_f, i->iv_[LEFT]));
+ else
+ i->iv_[LEFT] = last_end;
+
+ last_end = i->iv_[RIGHT];
+ list<Building>::iterator j = i;
+ i++;
+ result.splice (result.end (), *buildings, j);
+ }
+ if (last_end < infinity_f)
+ result.push_back (Building (last_end, -infinity_f, -infinity_f, infinity_f));
+ assert (is_legal_skyline (result));
+ return result;
+}
+
+list<Building>
+Skyline::internal_build_skyline (list<Building> *buildings)
{
vsize size = buildings->size ();
if (size == 0)
{
- empty_skyline (result);
- return;
+ list<Building> result;
+ empty_skyline (&result);
+ return result;
}
else if (size == 1)
{
- single_skyline (buildings->front (), 0, result);
- return;
+ list<Building> result;
+ single_skyline (buildings->front (), 0, &result);
+ return result;
}
- list<Building> right_half;
- list<Building>::iterator i = buildings->begin ();
+ deque<list<Building> > partials;
+ buildings->sort ();
+ while (!buildings->empty ())
+ partials.push_back (non_overlapping_skyline (buildings));
- for (vsize s = 0; s < size/2; s++)
- i++;
- right_half.splice (right_half.end (), *buildings, i, buildings->end ());
-
- list<Building> right;
- list<Building> left;
- internal_build_skyline (&right_half, &right);
- internal_build_skyline (buildings, &left);
- internal_merge_skyline (&right, &left, result);
+ /* we'd like to say while (partials->size () > 1) but that's O(n).
+ Instead, we exit in the middle of the loop */
+ while (!partials.empty ())
+ {
+ list<Building> merged;
+ list<Building> one = partials.front ();
+ partials.pop_front ();
+ if (partials.empty ())
+ return one;
+
+ list<Building> two = partials.front ();
+ partials.pop_front ();
+ internal_merge_skyline (&one, &two, &merged);
+ partials.push_back (merged);
+ }
+ assert (0);
+ return list<Building> ();
}
Skyline::Skyline ()
}
}
- internal_build_skyline (&bldgs, &buildings_);
- assert (is_legal_skyline ());
+ buildings_ = internal_build_skyline (&bldgs);
+ assert (is_legal_skyline (buildings_));
}
Skyline::Skyline (Box const &b, Real horizon_padding, Axis horizon_axis, Direction sky)
list<Building> my_bld;
my_bld.splice (my_bld.begin (), buildings_);
internal_merge_skyline (&other_bld, &my_bld, &buildings_);
- assert (is_legal_skyline ());
+ assert (is_legal_skyline (buildings_));
}
void
my_bld.splice (my_bld.begin (), buildings_);
single_skyline (Building (b, 0, a, sky_), horizon_padding, &other_bld);
internal_merge_skyline (&other_bld, &my_bld, &buildings_);
- assert (is_legal_skyline ());
+ assert (is_legal_skyline (buildings_));
}
void
i->height_[RIGHT] += sky_ * r;
i->y_intercept_ += sky_ * r;
}
- assert (is_legal_skyline ());
+ assert (is_legal_skyline (buildings_));
}
void
(glyph-name-alist . ,standard-alteration-glyph-name-alist)
(alteration . ,accidental-interface::calc-alteration)
(stencil . ,ly:accidental-interface::print)
- (pure-Y-extent . ,ly:accidental-interface::pure-height)
+ (Y-extent . ,ly:accidental-interface::height)
(after-line-breaking
. ,ly:accidental-interface::after-line-breaking)
(meta . ((class . Item)
(glyph-name-alist . ,standard-alteration-glyph-name-alist)
(alteration . ,accidental-interface::calc-alteration)
(stencil . ,ly:accidental-interface::print)
- (pure-Y-extent . ,ly:accidental-interface::pure-height)
+ (Y-extent . ,ly:accidental-interface::height)
(after-line-breaking
. ,ly:accidental-interface::after-line-breaking)
(meta . ((class . Item)
(AccidentalSuggestion
. (
(stencil . ,ly:accidental-interface::print)
+ (Y-extent . ,ly:accidental-interface::height)
(X-offset . ,(ly:make-simple-closure
`(,+
,(ly:make-simple-closure (list ly:self-alignment-interface::centered-on-x-parent))
(X-offset . ,ly:side-position-interface::x-aligned-side)
(direction . ,LEFT)
(stencil . ,ly:accidental-interface::print)
- (pure-Y-extent . ,ly:accidental-interface::pure-height)
+ (Y-extent . ,ly:accidental-interface::height)
(glyph-name-alist . ,standard-alteration-glyph-name-alist)
(after-line-breaking . ,ly:accidental-interface::after-line-breaking)
(side-axis . ,X)
(font-size . -4)
(side-axis . ,X)
(stencil . ,ly:accidental-interface::print)
+ (Y-extent . ,ly:accidental-interface::height)
(glyph-name-alist . ,standard-alteration-glyph-name-alist)
(meta . ((class . Item)
(interfaces . (trill-pitch-accidental-interface
(list
ly:bar-line::print
ly:note-head::print
- ly:accidental-interface::print
ly:dots::print
ly:clef::print
ly:text-interface::print
'(0 . 0))))
(define pure-conversions-alist
- (list
- `(,ly:slur::outside-slur-callback . ,ly:slur::pure-outside-slur-callback)
- `(,ly:stem::height . ,ly:stem::pure-height)
- `(,ly:rest::height . ,ly:rest::pure-height)
- `(,ly:grob::stencil-height . ,pure-stencil-height)
- `(,ly:side-position-interface::y-aligned-side . ,ly:side-position-interface::pure-y-aligned-side)
- `(,ly:axis-group-interface::height . ,ly:axis-group-interface::pure-height)
- `(,ly:hara-kiri-group-spanner::y-extent . ,ly:hara-kiri-group-spanner::pure-height)
- `(,ly:slur::height . ,ly:slur::pure-height)
- `(,ly:side-position-interface::y-aligned-side . ,ly:side-position-interface::pure-y-aligned-side)))
+ `(
+ (,ly:accidental-interface::height . ,ly:accidental-interface::pure-height)
+ (,ly:slur::outside-slur-callback . ,ly:slur::pure-outside-slur-callback)
+ (,ly:stem::height . ,ly:stem::pure-height)
+ (,ly:rest::height . ,ly:rest::pure-height)
+ (,ly:grob::stencil-height . ,pure-stencil-height)
+ (,ly:side-position-interface::y-aligned-side . ,ly:side-position-interface::pure-y-aligned-side)
+ (,ly:axis-group-interface::height . ,ly:axis-group-interface::pure-height)
+ (,ly:hara-kiri-group-spanner::y-extent . ,ly:hara-kiri-group-spanner::pure-height)
+ (,ly:slur::height . ,ly:slur::pure-height)
+ (,ly:side-position-interface::y-aligned-side . ,ly:side-position-interface::pure-y-aligned-side)))
(define pure-functions
(list