(number? string?)
#{
\once \override Score . RehearsalMark #'padding = $padding
- \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \once \override Score . RehearsalMark #'extra-spacing-width = #'(+inf.0 . -inf.0)
\mark \markup { \bold $marktext }
#})
(number? string?)
#{
\once \override Score . RehearsalMark #'padding = $padding
- \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \once \override Score . RehearsalMark #'extra-spacing-width = #'(+inf.0 . -inf.0)
\mark \markup { \bold $marktext }
#})
tempoMark = #(define-music-function (parser location markp) (string?)
#{
\once \override Score . RehearsalMark #'self-alignment-X = #left
- \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \once \override Score . RehearsalMark #'extra-spacing-width = #'(+inf.0 . -inf.0)
\mark \markup { \bold $markp }
#})
tempoMark = #(define-music-function (parser location markp) (string?)
#@{
\once \override Score . RehearsalMark #'self-alignment-X = #left
- \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \once \override Score . RehearsalMark #'extra-spacing-width = #'(+inf.0 . -inf.0)
\mark \markup @{ \bold $markp @}
#@})
@end example
tempoMark = #(define-music-function (parser location markp) (string?)
#{
\once \override Score . RehearsalMark #'self-alignment-X = #left
- \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \once \override Score . RehearsalMark #'extra-spacing-width = #'(+inf.0 . -inf.0)
\mark \markup { \bold $markp }
#})
tempoMark = #(define-music-function (parser location markp) (string?)
#@{
\once \override Score . RehearsalMark #'self-alignment-X = #left
- \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \once \override Score . RehearsalMark #'extra-spacing-width = #'(+inf.0 . -inf.0)
\mark \markup @{ \bold $markp @}
#@})
tempoMark = #(define-music-function (parser location markp) (string?)
#{
\once \override Score . RehearsalMark #'self-alignment-X = #left
- \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \once \override Score . RehearsalMark #'extra-spacing-width = #'(+inf.0 . -inf.0)
\mark \markup { \bold $markp }
#})
tempoMark = #(define-music-function (parser location markp) (string?)
#@{
\once \override Score . RehearsalMark #'self-alignment-X = #left
- \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \once \override Score . RehearsalMark #'extra-spacing-width = #'(+inf.0 . -inf.0)
\mark \markup @{ \bold $markp @}
#@})
tempoMark = #(define-music-function (parser location markp) (string?)
#{
\once \override Score . RehearsalMark #'self-alignment-X = #left
- \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \once \override Score . RehearsalMark #'extra-spacing-width = #'(+inf.0 . -inf.0)
\mark \markup { \bold $markp }
#})
}
}
+vector<Grob*>
+Accidental_placement::get_break_reminder_accidentals (vector<Grob*> const &elts, Grob *left)
+{
+ vector<Grob*> br;
+ vector<Grob*> ra;
+ vector<Grob*> ret;
+
+ if (dynamic_cast<Item *> (left)->break_status_dir () != RIGHT)
+ return vector<Grob*> ();
+
+ for (vsize i = 0; i < elts.size (); i++)
+ {
+ split_accidentals (elts[i], &br, &ra);
+ ret.insert (ret.end (), br.begin (), br.end ());
+ }
+ return ret;
+}
+
/*
Accidentals are special, because they appear and disappear after
ties at will.
v.unite (Interval (where, where));
}
- /*
- TODO: support self-alignment-{Y, X}
- */
for (vsize i = 0; i < translates.size (); i++)
elems[i]->translate_axis (translates[i] - v.center (), a);
}
-/*
- Hairy function to put elements where they should be. Can be tweaked
- from the outside by setting extra-space in its
- children
-
- We assume that the children the refpoints of the children are still
- found at 0.0 -- we will fuck up with thresholds if children's
- extents are already moved to locations such as (-16, -8), since the
- dy needed to put things in a row doesn't relate to the distances
- between original refpoints.
-
- TODO: maybe we should rethink and throw out thresholding altogether.
- The original function has been taken over by
- align_to_fixed_distance ().
-*/
+/* for each grob, find its upper and lower skylines. If the grob has
+ an empty extent, delete it from the list instead. If the extent is
+ non-empty but there is no skyline available (or pure is true), just
+ create a flat skyline from the bounding box */
+static void
+get_skylines (Grob *me,
+ vector<Grob*> *const elements,
+ Axis a,
+ bool pure, int start, int end,
+ vector<Skyline_pair> *const ret)
+{
+ Grob *other_axis_common = common_refpoint_of_array (*elements, me, other_axis (a));
+ for (vsize i = elements->size (); i--;)
+ {
+ Grob *g = (*elements)[i];
+ Interval extent = g->maybe_pure_extent (g, a, pure, start, end);
+ Interval other_extent = pure ? Interval (-infinity_f, infinity_f)
+ : g->extent (other_axis_common, other_axis (a));
+ Box b = (a == X_AXIS) ? Box (extent, other_extent) : Box (other_extent, extent);
+
+ if (extent.is_empty ())
+ {
+ elements->erase (elements->begin () + i);
+ continue;
+ }
+
+ Skyline_pair skylines;
+ if (!pure
+ && Skyline_pair::unsmob (g->get_property ("skylines")))
+ skylines = *Skyline_pair::unsmob (g->get_property ("skylines"));
+ else
+ {
+ if (!pure)
+ programming_error ("no skylines for alignment-child\n");
+
+ skylines = Skyline_pair (b, 0, other_axis (a));
+ }
+
+ /* each skyline is calculated relative to (potentially) a different other_axis
+ coordinate. In order to compare the skylines effectively, we need to shift them
+ to some absolute reference point */
+ if (!pure)
+ {
+ /* this is perhaps an abuse of minimum-?-extent: maybe we should create
+ another property? But it seems that the only (current) use of
+ minimum-Y-extent is to separate vertically-aligned elements */
+ SCM min_extent = g->get_property (a == X_AXIS ? "minimum-X-extent" : "minimum-Y-extent");
+ if (is_number_pair (min_extent))
+ {
+ b[a] = ly_scm2interval (min_extent);
+ skylines.insert (b, 0, other_axis (a));
+ }
+ Real offset = g->relative_coordinate (other_axis_common, other_axis (a));
+ skylines.shift (-offset);
+ }
+
+
+ ret->push_back (skylines);
+ }
+ reverse (*ret);
+}
vector<Real>
Align_interface::get_extents_aligned_translates (Grob *me,
Direction stacking_dir = robust_scm2dir (me->get_property ("stacking-dir"),
DOWN);
- Interval threshold = robust_scm2interval (me->get_property ("threshold"),
- Interval (0, Interval::infinity ()));
+ vector<Grob*> elems (all_grobs); // writable copy
+ vector<Skyline_pair> skylines;
- vector<Interval> dims;
- vector<Grob*> elems;
+ get_skylines (me, &elems, a, pure, start, end, &skylines);
- for (vsize i = 0; i < all_grobs.size (); i++)
- {
- Interval y = all_grobs[i]->maybe_pure_extent (all_grobs[i], a, pure, start, end);
- if (!y.is_empty ())
- {
- Grob *e = dynamic_cast<Grob *> (all_grobs[i]);
-
- elems.push_back (e);
- dims.push_back (y);
- }
- }
-
- /*
- Read self-alignment-X and self-alignment-Y. This may seem like
- code duplication. (and really: it is), but this is necessary to
- prevent ugly cyclic dependencies that arise when you combine
- self-alignment on a child with alignment of children.
- */
- SCM align ((a == X_AXIS)
- ? me->get_property ("self-alignment-X")
- : me->get_property ("self-alignment-Y"));
-
- Interval total;
Real where = 0;
- Real extra_space = 0.0;
SCM extra_space_handle = scm_assq (ly_symbol2scm ("alignment-extra-space"), line_break_details);
+ Real extra_space = robust_scm2double (scm_is_pair (extra_space_handle)
+ ? scm_cdr (extra_space_handle)
+ : SCM_EOL,
+ 0.0);
- extra_space = robust_scm2double (scm_is_pair (extra_space_handle)
- ? scm_cdr (extra_space_handle)
- : SCM_EOL,
- extra_space);
-
- Real padding = robust_scm2double (me->get_property ("padding"),
- 0.0);
+ Real padding = robust_scm2double (me->get_property ("padding"), 0.0);
vector<Real> translates;
for (vsize j = 0; j < elems.size (); j++)
{
- Real dy = -dims[j][-stacking_dir];
- if (j)
- dy += dims[j - 1][stacking_dir];
-
- /*
- we want dy to be > 0
- */
- dy *= stacking_dir;
- if (j)
- dy = min (max (dy, threshold[SMALLER]), threshold[BIGGER]);
-
+ Real dy = 0;
+ if (j == 0)
+ dy = skylines[j][-stacking_dir].max_height ();
+ else
+ dy = skylines[j-1][stacking_dir].distance (skylines[j][-stacking_dir]);
where += stacking_dir * (dy + padding + extra_space / elems.size ());
- total.unite (dims[j] + where);
translates.push_back (where);
}
}
}
-
- Real center_offset = 0.0;
-
- /*
- also move the grobs that were empty, to maintain spatial order.
- */
vector<Real> all_translates;
- if (translates.size ())
+
+ if (!translates.empty ())
{
Real w = translates[0];
-
- if (scm_is_number (align))
- center_offset = total.linear_combination (scm_to_double (align));
-
for (vsize i = 0, j = 0; j < all_grobs.size (); j++)
{
if (i < elems.size () && all_grobs[j] == elems[i])
w = translates[i++];
- all_translates.push_back (w - center_offset);
+ all_translates.push_back (w);
}
}
return all_translates;
return pure_group_height (me, start, end);
}
+
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_skylines, 1);
+SCM
+Axis_group_interface::calc_skylines (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ extract_grob_set (me, "elements", elts);
+ return skyline_spacing (me, elts).smobbed_copy ();
+}
+
+/* whereas calc_skylines calculates skylines for axis-groups with a lot of
+ visible children, combine_skylines is designed for axis-groups whose only
+ children are other axis-groups (ie. VerticalAlignment). Rather than
+ calculating all the skylines from scratch, we just merge the skylines
+ of the children.
+*/
+MAKE_SCHEME_CALLBACK (Axis_group_interface, combine_skylines, 1);
+SCM
+Axis_group_interface::combine_skylines (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ extract_grob_set (me, "elements", elements);
+ Grob *y_common = common_refpoint_of_array (elements, me, Y_AXIS);
+
+ assert (y_common == me);
+
+ Skyline_pair ret;
+ for (vsize i = 0; i < elements.size (); i++)
+ {
+ SCM skyline_scm = elements[i]->get_property ("skylines");
+ if (Skyline_pair::unsmob (skyline_scm))
+ {
+ Real offset = elements[i]->relative_coordinate (y_common, Y_AXIS);
+ Skyline_pair other = *Skyline_pair::unsmob (skyline_scm);
+ other.raise (offset);
+ ret.merge (other);
+ }
+ }
+ return ret.smobbed_copy ();
+}
SCM
Axis_group_interface::generic_group_extent (Grob *me, Axis a)
{
+ /* trigger the callback to do skyline-spacing on the children */
+ (void) me->get_property ("skylines");
+
extract_grob_set (me, "elements", elts);
- if (a == Y_AXIS && to_boolean (me->get_property ("skyline-spacing")))
- skyline_spacing (me, elts);
Grob *common = common_refpoint_of_array (elts, me, a);
Real my_coord = me->relative_coordinate (common, a);
bool
staff_priority_less (Grob * const &g1, Grob * const &g2)
{
- int priority_1 = robust_scm2int (g1->get_property ("outside-staff-priority"), INT_MIN);
- int priority_2 = robust_scm2int (g2->get_property ("outside-staff-priority"), INT_MIN);
+ Real priority_1 = robust_scm2double (g1->get_property ("outside-staff-priority"), -infinity_f);
+ Real priority_2 = robust_scm2double (g2->get_property ("outside-staff-priority"), -infinity_f);
if (priority_1 < priority_2)
return true;
edge of the just-placed grob). Otherwise, we skip it until the next pass.
*/
static void
-add_grobs_of_one_priority (Drul_array<Skyline> *const skylines,
+add_grobs_of_one_priority (Skyline_pair *const skylines,
vector<Grob*> elements,
Grob *x_common,
Grob *y_common)
elements[i]->translate_axis (dir*dist, Y_AXIS);
}
(*skylines)[dir].insert (b, 0, X_AXIS);
- elements[i]->del_property ("outside-staff-padding");
+ elements[i]->set_property ("outside-staff-priority", SCM_BOOL_F);
last_affected_position[dir] = b[X_AXIS][RIGHT];
}
elements.erase (elements.begin () + i);
}
}
-void
+Skyline_pair
Axis_group_interface::skyline_spacing (Grob *me, vector<Grob*> elements)
{
vector_sort (elements, staff_priority_less);
Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS);
Grob *y_common = common_refpoint_of_array (elements, me, Y_AXIS);
+ assert (y_common == me);
+
vsize i = 0;
vector<Box> boxes;
&& !scm_is_number (elements[i]->get_property ("outside-staff-priority")); i++)
add_boxes (elements[i], x_common, y_common, &boxes);
- Drul_array<Skyline> skylines (Skyline (boxes, 0, X_AXIS, DOWN),
- Skyline (boxes, 0, X_AXIS, UP));
+ Skyline_pair skylines (boxes, 0, X_AXIS);
for (; i < elements.size (); i++)
{
SCM priority = elements[i]->get_property ("outside-staff-priority");
add_grobs_of_one_priority (&skylines, current_elts, x_common, y_common);
}
+ return skylines;
}
ADD_INTERFACE (Axis_group_interface,
"elements "
"common-refpoint-of-elements "
"pure-relevant-elements "
- "skyline-spacing "
+ "skylines "
"cached-pure-extents "
);
TRANSLATOR_DECLARATIONS (Dynamic_engraver);
DECLARE_ACKNOWLEDGER (accidental);
- DECLARE_ACKNOWLEDGER (script);
DECLARE_ACKNOWLEDGER (stem_tremolo);
DECLARE_ACKNOWLEDGER (note_column);
DECLARE_ACKNOWLEDGER (slur);
finished_cresc_->set_bound (RIGHT, info.grob ());
}
-void
-Dynamic_engraver::acknowledge_script (Grob_info info)
-{
- if (!line_spanner_ || !script_)
- return;
-
- SCM p = info.grob ()->get_property ("script-priority");
-
- /*
- UGH.
-
- DynamicText doesn't really have a script-priority field.
- */
- if (scm_is_number (p)
- && scm_to_int (p)
- < scm_to_int (script_->get_property ("script-priority")))
- Side_position_interface::add_support (line_spanner_, info.grob ());
-}
-
ADD_ACKNOWLEDGER (Dynamic_engraver, accidental);
-ADD_ACKNOWLEDGER (Dynamic_engraver, script);
ADD_ACKNOWLEDGER (Dynamic_engraver, note_column);
ADD_ACKNOWLEDGER (Dynamic_engraver, slur);
ADD_ACKNOWLEDGER (Dynamic_engraver, stem_tremolo);
DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element));
static void add_accidental (Grob *, Grob *);
+ static vector<Grob*> get_break_reminder_accidentals (vector<Grob*> const &elts,
+ Grob *left);
static Interval get_relevant_accidental_extent (Grob *me,
Item *item_col,
Grob *acc);
#include "std-vector.hh"
#include "lily-proto.hh"
#include "grob-interface.hh"
+#include "skyline.hh"
struct Axis_group_interface
{
DECLARE_SCHEME_CALLBACK (width, (SCM smob));
DECLARE_SCHEME_CALLBACK (height, (SCM smob));
DECLARE_SCHEME_CALLBACK (pure_height, (SCM smob, SCM start, SCM end));
+ DECLARE_SCHEME_CALLBACK (calc_skylines, (SCM smob));
+ DECLARE_SCHEME_CALLBACK (combine_skylines, (SCM smob));
static Interval relative_group_extent (vector<Grob*> const &list,
Grob *common, Axis);
static Interval relative_pure_height (Grob *me, vector<Grob*> const &list,
static Interval cached_pure_height (Grob *me, vector<Grob*> const &list,
Grob *common, int, int);
- static void skyline_spacing (Grob *me, vector<Grob*> elements);
+ static Skyline_pair skyline_spacing (Grob *me, vector<Grob*> elements);
static void add_element (Grob *me, Grob *);
static void set_axes (Grob *, Axis, Axis);
static bool has_axis (Grob *, Axis);
#include "lily-proto.hh"
#include "direction.hh"
#include "grob-interface.hh"
+#include "skyline.hh"
struct Separation_item
{
DECLARE_GROB_INTERFACE();
DECLARE_SCHEME_CALLBACK(calc_skylines, (SCM));
- static vector<Box> boxes (Grob *me);
- static Interval conditional_width (Grob *, Grob *);
+ static vector<Box> boxes (Grob *me, Grob *left);
+ static Skyline conditional_skyline (Grob *, Grob *);
static Interval width (Grob *);
static Interval relative_width (Grob *, Grob *);
static Grob *extremal_break_aligned_grob (Grob *, Direction, Interval *);
void precompute ();
Building (Real start, Real start_height, Real end_height, Real end);
+ Building (Box const &b, Real horizon_padding, Axis a, Direction d);
void print () const;
Real height (Real x) const;
void leading_part (Real chop);
bool conceals_beginning (Building const &other) const;
bool conceals (Building const &other) const;
+ bool sane () const;
Building sloped_neighbour (Real horizon_padding, Direction d) const;
};
Skyline (Skyline const &src);
Skyline (Direction sky);
Skyline (vector<Box> const &bldgs, Real horizon_padding, Axis a, Direction sky);
+ Skyline (Box const &b, Real horizon_padding, Axis a, Direction sky);
vector<Offset> to_points () const;
void merge (Skyline const &);
void insert (Box const &, Real horizon_padding, Axis);
void print () const;
void raise (Real);
+ void shift (Real);
Real distance (Skyline const &) const;
Real height (Real airplane) const;
Real max_height () const;
void set_minimum_height (Real height);
};
+class Skyline_pair
+{
+private:
+ Drul_array<Skyline> skylines_;
+
+ DECLARE_SIMPLE_SMOBS(Skyline_pair);
+public:
+ Skyline_pair ();
+ Skyline_pair (vector<Box> const &boxes, Real horizon_padding, Axis a);
+ Skyline_pair (Box const &, Real horizon_padding, Axis a);
+ void raise (Real);
+ void shift (Real);
+ void insert (Box const &, Real horizon_padding, Axis);
+ void merge (Skyline_pair const &other);
+ Skyline &operator [] (Direction d);
+ Skyline const &operator [] (Direction d) const;
+};
+
#endif /* SKYLINE_HH */
/* properties */
"break-visibility "
- "no-spacing-rods "
+ "extra-spacing-width "
+ "infinite-spacing-height "
"non-musical")
{
Grob *g = unsmob_grob (scm_car (s));
if (last)
- Side_position_interface::add_support (g, last);
+ {
+ SCM outside_staff = last->get_property ("outside-staff-priority");
+ if (scm_is_number (outside_staff))
+ {
+ /* we allow the outside-staff-priority ordering to override the
+ script-priority ordering */
+ if (!scm_is_number (g->get_property ("outside-staff-priority")))
+ g->set_property ("outside-staff-priority",
+ scm_from_double (scm_to_double (outside_staff) + 0.1));
+ }
+ else
+ Side_position_interface::add_support (g, last);
+ }
last = g;
}
Separation_item::set_skyline_distance (Drul_array<Item *> items,
Real padding)
{
- Drul_array<Skyline*> lines;
- Direction d = LEFT;
-
- do
- {
- SCM prop = items[d]->get_property ("skylines");
- lines[d] = Skyline::unsmob (index_get_cell (prop, -d));
- }
- while (flip (&d) != LEFT);
-
- Real dist = padding + lines[LEFT]->distance (*lines[RIGHT]);
+ Drul_array<Skyline_pair*> lines (Skyline_pair::unsmob (items[LEFT]->get_property ("skylines")),
+ Skyline_pair::unsmob (items[RIGHT]->get_property ("skylines")));
+ Skyline right = conditional_skyline (items[RIGHT], items[LEFT]);
+ right.merge ((*lines[RIGHT])[LEFT]);
+
+ Real dist = padding + (*lines[LEFT])[RIGHT].distance (right);
if (dist > 0)
{
Rod rod;
Separation_item::set_distance (Drul_array<Item *> items,
Real padding)
{
- if (!Item::is_non_musical (items[LEFT])
- && !Item::is_non_musical (items[RIGHT]))
- {
- set_skyline_distance (items, padding);
- return true;
- }
-
- Interval li (Separation_item::width (items[LEFT]));
- Interval ri (Separation_item::conditional_width (items[RIGHT], items[LEFT]));
- if (!li.is_empty () && !ri.is_empty ())
- {
- Rod rod;
-
- rod.item_drul_ = items;
-
- rod.distance_ = li[RIGHT] - ri[LEFT] + padding;
-
- if (rod.distance_ > 0)
- rod.add_to_cols ();
- return true;
- }
- return false;
+ set_skyline_distance (items, padding);
+ return true;
}
/*
Return the width of ME given that we are considering the object on
the LEFT.
*/
-Interval
-Separation_item::conditional_width (Grob *me, Grob *left)
+Skyline
+Separation_item::conditional_skyline (Grob *me, Grob *left)
{
- Interval w = width (me);
-
- Item *item = dynamic_cast<Item *> (me);
- Paper_column *pc = item->get_column ();
-
- extract_grob_set (me, "conditional-elements", elts);
- for (vsize i = 0; i < elts.size (); i++)
- {
- Item *il = dynamic_cast<Item *> (elts[i]);
- if (pc != il->get_column ())
- {
- programming_error ("Separation_item element from wrong column");
- continue;
- }
-
- if (to_boolean (il->get_property ("no-spacing-rods")))
- continue;
-
- if (Accidental_placement::has_interface (il))
- w.unite (Accidental_placement::get_relevant_accidental_extent (il, pc, left));
- }
-
- SCM pad = me->get_property ("padding");
-
- w.widen (robust_scm2double (pad, 0.0));
- return w;
+ vector<Box> bs = boxes (me, left);
+ return Skyline (bs, 0.1, Y_AXIS, LEFT);
}
Separation_item::calc_skylines (SCM smob)
{
Item *me = unsmob_item (smob);
- SCM lines = scm_cons (SCM_BOOL_F,SCM_BOOL_F);
-
- Direction d = LEFT;
- vector<Box> bs = boxes (me);
- do
- {
- /* todo: the horizon_padding is somewhat arbitrary */
- Skyline l (bs, 0.1, Y_AXIS, d);
- index_set_cell (lines, d, l.smobbed_copy ());
- }
- while (flip (&d) != LEFT);
-
- return lines;
+ vector<Box> bs = boxes (me, 0);
+ /* todo: the horizon_padding is somewhat arbitrary */
+ return Skyline_pair (bs, 0.1, Y_AXIS).smobbed_copy ();
}
-
+/* if left is non-NULL, get the boxes corresponding to the
+ conditional-elements (conditioned on the grob LEFT). This
+ sounds more general than it is: conditional-elements are
+ always accidentals attached to a tied note.
+*/
vector<Box>
-Separation_item::boxes (Grob *me)
+Separation_item::boxes (Grob *me, Grob *left)
{
Item *item = dynamic_cast<Item *> (me);
int very_large = INT_MAX;
Paper_column *pc = item->get_column ();
vector<Box> out;
- extract_grob_set (me, "elements", elts);
+ extract_grob_set (me, left ? "conditional-elements" : "elements", read_only_elts);
+ vector<Grob*> elts;
+
+ if (left)
+ elts = Accidental_placement::get_break_reminder_accidentals (read_only_elts, left);
+ else
+ elts = read_only_elts;
Grob *ycommon = common_refpoint_of_array (elts, me, Y_AXIS);
continue;
}
- if (to_boolean (il->get_property ("no-spacing-rods")))
- continue;
-
Interval y (il->pure_height (ycommon, 0, very_large));
- Box b (il->extent (pc, X_AXIS), y);
-
- out.push_back (b);
+ Interval x (il->extent (pc, X_AXIS));
+
+ Interval extra = robust_scm2interval (elts[i]->get_property ("extra-spacing-width"),
+ Interval (0, 0));
+ x[LEFT] += extra[LEFT];
+ x[RIGHT] += extra[RIGHT];
+ if (to_boolean (elts[i]->get_property ("infinite-spacing-height")))
+ y = Interval (-infinity_f, infinity_f);
+
+ out.push_back (Box (x, y));
}
return out;
Separation_item::width (Grob *me)
{
SCM sw = me->get_property ("X-extent");
- if (is_number_pair (sw))
- return ly_scm2interval (sw);
-
- Item *item = dynamic_cast<Item *> (me);
- Paper_column *pc = item->get_column ();
- Interval w;
-
- extract_grob_set (me, "elements", elts);
- for (vsize i = 0; i < elts.size (); i++)
- {
- Item *il = dynamic_cast<Item *> (elts[i]);
- if (pc != il->get_column ())
- {
- /* this shouldn't happen, but let's continue anyway. */
- programming_error ("Separation_item: I've been drinking too much");
- continue; /*UGH UGH*/
- }
-
- if (to_boolean (il->get_property ("no-spacing-rods")))
- continue;
-
- Interval iv (il->extent (pc, X_AXIS));
- if (!iv.is_empty ())
- w.unite (iv);
- }
-
- SCM pad = me->get_property ("padding");
-
- w.widen (robust_scm2double (pad, 0.0));
-
- me->set_property ("X-extent", ly_interval2scm (w));
-
- return w;
+ return ly_scm2interval (sw);
}
Interval
precompute ();
}
+Building::Building (Box const &b, Real horizon_padding, Axis horizon_axis, Direction sky)
+{
+ Real height = sky * b[other_axis (horizon_axis)][sky];
+
+ iv_ = b[horizon_axis];
+ iv_.widen (horizon_padding + EPS);
+ height_[LEFT] = height;
+ height_[RIGHT] = height;
+
+ if (sane ())
+ precompute ();
+}
+
void
Building::precompute ()
{
return Building (left, left_height, right_height, right);
}
+bool
+Building::sane () const
+{
+ return approx_less_than (iv_[LEFT], iv_[RIGHT])
+ && !isinf (height_[RIGHT])
+ && !isinf (height_[LEFT]);
+}
+
static void
skyline_trailing_part (list<Building> *sky, Real x)
{
for (vsize i = 0; i < boxes.size (); i++)
{
- Interval iv = boxes[i][horizon_axis];
- Real height = sky * boxes[i][other_axis (horizon_axis)][sky];
-
- iv.widen (horizon_padding);
- if (!iv.is_empty () && !isinf (height) && !approx_equal (iv[LEFT], iv[RIGHT]))
+ Building front (boxes[i], horizon_padding, horizon_axis, sky);
+ if (front.sane ())
{
- iv.widen (EPS);
- Building front = Building (iv[LEFT], height, height, iv[RIGHT]);
bldgs.push_front (front);
if (horizon_padding > 0 && !isinf (front.iv_.length ()))
{
assert (is_legal_skyline ());
}
+Skyline::Skyline (Box const &b, Real horizon_padding, Axis horizon_axis, Direction sky)
+{
+ sky_ = sky;
+ Building front (b, 0, horizon_axis, sky);
+ single_skyline (front, horizon_padding, &buildings_);
+}
+
void
Skyline::merge (Skyline const &other)
{
{
list<Building> other_bld;
list<Building> my_bld;
- Interval iv = b[a];
- Real height = sky_ * b[other_axis (a)][sky_];
-
- assert (!iv.is_empty ());
- iv.widen (EPS);
my_bld.splice (my_bld.begin (), buildings_);
- single_skyline (Building (iv[LEFT], height, height, iv[RIGHT]), horizon_padding, &other_bld);
+ 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 ());
}
+void
+Skyline::shift (Real r)
+{
+ list<Building>::iterator end = buildings_.end ();
+ for (list<Building>::iterator i = buildings_.begin (); i != end; i++)
+ {
+ i->iv_[LEFT] += r;
+ i->iv_[RIGHT] += r;
+ }
+}
+
Real
Skyline::distance (Skyline const &other) const
{
return out;
}
+Skyline_pair::Skyline_pair ()
+ : skylines_ (Skyline (DOWN), Skyline (UP))
+{
+}
+
+Skyline_pair::Skyline_pair (vector<Box> const &boxes, Real padding, Axis a)
+ : skylines_ (Skyline (boxes, padding, a, DOWN), Skyline (boxes, padding, a, UP))
+{
+}
+
+Skyline_pair::Skyline_pair (Box const &b, Real padding, Axis a)
+ : skylines_ (Skyline (b, padding, a, DOWN), Skyline (b, padding, a, UP))
+{
+}
+
+void
+Skyline_pair::raise (Real r)
+{
+ skylines_[UP].raise (r);
+ skylines_[DOWN].raise (r);
+}
+
+void
+Skyline_pair::shift (Real r)
+{
+ skylines_[UP].shift (r);
+ skylines_[DOWN].shift (r);
+}
+
+void
+Skyline_pair::insert (Box const &b, Real padding, Axis a)
+{
+ skylines_[UP].insert (b, padding, a);
+ skylines_[DOWN].insert (b, padding, a);
+}
+
+void
+Skyline_pair::merge (Skyline_pair const &other)
+{
+ skylines_[UP].merge (other[UP]);
+ skylines_[DOWN].merge (other[DOWN]);
+}
+
+Skyline&
+Skyline_pair::operator [] (Direction d)
+{
+ return skylines_[d];
+}
+
+Skyline const&
+Skyline_pair::operator [] (Direction d) const
+{
+ return skylines_[d];
+}
+
/****************************************************************/
IMPLEMENT_TYPE_P (Skyline, "ly:skyline?");
IMPLEMENT_DEFAULT_EQUAL_P (Skyline);
+IMPLEMENT_SIMPLE_SMOBS (Skyline_pair);
+IMPLEMENT_TYPE_P (Skyline_pair, "ly:skyline-pair?");
+IMPLEMENT_DEFAULT_EQUAL_P (Skyline_pair);
+
SCM
Skyline::mark_smob (SCM)
{
return 1;
}
+
+SCM
+Skyline_pair::mark_smob (SCM)
+{
+ return SCM_EOL;
+}
+
+int
+Skyline_pair::print_smob (SCM s, SCM port, scm_print_state *)
+{
+ Skyline_pair *r = (Skyline_pair *) SCM_CELL_WORD_1 (s);
+ (void) r;
+
+ scm_puts ("#<Skyline-pair>", port);
+ return 1;
+}
autoBeamOff = \set autoBeaming = ##f
autoBeamOn = \set autoBeaming = ##t
-fatText = \override TextScript #'no-spacing-rods = ##f
-emptyText = \override TextScript #'no-spacing-rods = ##t
+fatText = { \override TextScript #'extra-spacing-width = #'(0 . 0)
+ \override TextScript #'infinite-spacing-height = ##t }
+
+emptyText = { \override TextScript #'extra-spacing-width = #'(+inf.0 . -inf.0)
+ \override TextScript #'infinite-spacing-height = ##f }
showStaffSwitch = \set followVoice = ##t
hideStaffSwitch = \set followVoice = ##f
(extra-X-extent ,number-pair? "A grob is enlarged in X dimension
by this much.")
(extra-Y-extent ,number-pair? "See @code{extra-X-extent}.")
+ (extra-spacing-width ,number-pair? "In the horizontal spacing problem, we pad each item by this amount (by adding the car on the left side of the item and adding the cdr on the right side of the item). In order to make a grob take up no horizontal space at all, set this to (+inf.0 . -inf.0)")
(X-extent ,number-pair? "Hard coded extent in X direction. ")
(Y-extent ,number-pair? "See @code{X-extent}.")
(extra-offset ,number-pair? "A pair representing an offset. This
Choices are @code{around}, @code{inside}, @code{outside}. If unset, script
and slur ignore eachother.")
(ignore-collision ,boolean? "If set, don't do note collision resolution on this NoteColumn.")
+ (infinite-spacing-height ,boolean? "If true, then for the purposes of
+horizontal spacing, treat this item as though it were infinitely tall. That
+is, no object from another column will be allowed to stick above or below this item.")
(inspect-quants ,number-pair? "If debugging is set,
set beam/slur quant to this position, and print the respective scores.")
(inspect-index ,integer? "If debugging is set,
(note-names ,vector? "Vector of strings containing names for
easy-notation note heads.")
(no-ledgers ,boolean? "If set, don't draw ledger lines on this object.")
- (no-spacing-rods ,boolean? "Items with this property do not cause
-spacing constraints.")
(no-stem-extend ,boolean? "If set, notes with ledger lines do not
get stems extending to the middle staff line.")
(non-musical ,boolean? "True if the grob belongs in a NonMusicalPaperColumn.")
object.")
(side-axis ,number? "If the value is #X (or equivalently 1), the object is placed horizontally next to the other object. If the value is #Y or 0, it is placed vertically.")
(size ,number? "Size of object, relative to standard size.")
- (skylines ,pair? "A pair of lists of (x height) pairs.")
+ (skylines ,ly:skyline-pair? "Two skylines, one above and one below this grob (or, for some grobs, to the left and to the right).")
(slope ,number? "The slope of this object.")
(slur-padding ,number? "Extra distance between slur and script.")
(space-alist ,list? "A table that specifies distances between
(spaceable-staves ,ly:grob-array? "Objects to be spaced during page layout.")
(skyline-distance ,number? "The distance between this staff and the next one, as determined by a skyline algorithm.")
(skyline-horizontal-padding ,number? "For determining the vertical distance between 2 staves, it is possible to have a configuration which would result in a tight interleaving of grobs from the top staff and the bottom staff. The larger this parameter is, the farther apart the staves will be placed in such a configuration.")
- (skyline-spacing ,boolean? "When true, this axis-group will vertically space its children
-using a skyline algorithm.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(layer . 0)
(break-visibility . ,all-visible)
(non-musical . #t)
+ (extra-spacing-width . (-0.3 . 0.3))
(stencil . ,ly:bar-line::print)
(glyph-name . ,bar-line::calc-glyph-name)
. (
(axes . (,Y))
(Y-extent . ,ly:axis-group-interface::height)
+ (skylines . ,ly:axis-group-interface::calc-skylines)
(meta . ((class . Spanner)
(interfaces . (axis-group-interface
))))))
(CombineTextScript
. (
(stencil . ,ly:text-interface::print)
- (no-spacing-rods . #t)
+ (extra-spacing-width . (+inf.0 . -inf.0))
(Y-offset . ,ly:side-position-interface::y-aligned-side)
(X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
(direction . ,UP)
(font-encoding . fetaDynamic)
(font-shape . italic)
(avoid-slur . around)
- (no-spacing-rods . #t)
- (script-priority . 100)
+ (extra-spacing-width . (+inf.0 . -inf.0))
(outside-staff-priority . 250)
(meta . ((class . Item)
(interfaces . (font-interface
(Y-offset . ,ly:side-position-interface::y-aligned-side)
(stencil . ,ly:text-interface::print)
-
- ;; no Y dimensions, because of lyrics under tenor clef.
- (Y-extent . (0 . 0))
(font-shape . italic)
(padding . 0.6)
(staff-padding . 0.2)
(stencil . ,ly:text-interface::print)
(direction . ,RIGHT)
(X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
- (no-spacing-rods . #t)
+ (extra-spacing-width . (+inf.0 . -inf.0))
(padding . 0.0) ;; padding relative to SostenutoPedalLineSpanner
(font-shape . italic)
(self-alignment-X . 0)
(SustainPedal
. (
- (no-spacing-rods . #t)
+ (extra-spacing-width . (+inf.0 . -inf.0))
(stencil . ,ly:sustain-pedal::print)
(self-alignment-X . 0)
(direction . ,RIGHT)
(axes . (0 1))
(X-extent . ,ly:axis-group-interface::width)
(Y-extent . ,ly:axis-group-interface::height)
- (skyline-spacing . #t)
+ (skylines . ,ly:axis-group-interface::calc-skylines)
(skyline-horizontal-padding . 1.0)
(meta . ((class . System)
(interfaces . (system-interface
(TextScript
. (
- (no-spacing-rods . #t)
+ (extra-spacing-width . (+inf.0 . -inf.0))
(X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
(Y-offset . ,ly:side-position-interface::y-aligned-side)
(side-axis . ,Y)
. (
(stencil . ,ly:text-interface::print)
(font-shape . italic)
- (no-spacing-rods . #t)
+ (extra-spacing-width . (+inf.0 . -inf.0))
(self-alignment-X . 0)
(direction . ,RIGHT)
(padding . 0.0) ;; padding relative to UnaCordaPedalLineSpanner
(Y-extent . ,ly:axis-group-interface::height)
(X-extent . ,ly:axis-group-interface::width)
(stacking-dir . -1)
- (padding . 0.1)
+ (padding . 0.1)
+ (skylines . ,ly:axis-group-interface::combine-skylines)
(meta . ((class . Spanner)
(interfaces . (align-interface
axis-group-interface))))))
(Y-offset . ,ly:hara-kiri-group-spanner::force-hara-kiri-callback)
(Y-extent . ,ly:hara-kiri-group-spanner::y-extent)
(X-extent . ,ly:axis-group-interface::width)
- (skyline-spacing . #t)
+ (skylines . ,ly:axis-group-interface::calc-skylines);
(meta . ((class . Spanner)
(interfaces . (axis-group-interface
hara-kiri-group-spanner-interface
(define pure-print-callbacks
(list
+ ly:bar-line::print
ly:note-head::print
ly:accidental-interface::print
ly:dots::print
(ly:stencil? sten)
(memq sten pure-print-callbacks))
(ly:grob::stencil-height grob)
-
'(0 . 0))))
(define pure-conversions-alist