From: Joe Neeman Date: Mon, 18 Dec 2006 18:59:33 +0000 (+0200) Subject: Merge branch 'master' of git+ssh://jneem@git.sv.gnu.org/srv/git/lilypond X-Git-Tag: release/2.11.4-1~16 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=a3bb260f7e9420412dc1fa05afc92eeb1dbed32f;hp=8d905755acd00880fe10f4a4a2c82f77ebd4ca01;p=lilypond.git Merge branch 'master' of git+ssh://jneem@git.sv.gnu.org/srv/git/lilypond --- diff --git a/lily/accidental-placement.cc b/lily/accidental-placement.cc index f6bfefff5d..6aaf49b2e6 100644 --- a/lily/accidental-placement.cc +++ b/lily/accidental-placement.cc @@ -75,6 +75,24 @@ Accidental_placement::split_accidentals (Grob *accs, } } +vector +Accidental_placement::get_break_reminder_accidentals (vector const &elts, Grob *left) +{ + vector br; + vector ra; + vector ret; + + if (dynamic_cast (left)->break_status_dir () != RIGHT) + return vector (); + + 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. diff --git a/lily/align-interface.cc b/lily/align-interface.cc index f2eacf7608..2f23220c5a 100644 --- a/lily/align-interface.cc +++ b/lily/align-interface.cc @@ -123,28 +123,71 @@ Align_interface::align_to_fixed_distance (Grob *me, Axis a) 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 *const elements, + Axis a, + bool pure, int start, int end, + vector *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 Align_interface::get_extents_aligned_translates (Grob *me, @@ -169,63 +212,29 @@ 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 elems (all_grobs); // writable copy + vector skylines; - vector dims; - vector 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 (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 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); } @@ -243,25 +252,16 @@ Align_interface::get_extents_aligned_translates (Grob *me, } } - - Real center_offset = 0.0; - - /* - also move the grobs that were empty, to maintain spatial order. - */ vector 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; diff --git a/lily/axis-group-interface.cc b/lily/axis-group-interface.cc index 9149f667bc..4319bb8b92 100644 --- a/lily/axis-group-interface.cc +++ b/lily/axis-group-interface.cc @@ -179,13 +179,54 @@ Axis_group_interface::pure_height (SCM smob, SCM start_scm, SCM end_scm) 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); @@ -258,8 +299,8 @@ Axis_group_interface::get_children (Grob *me, vector *found) 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; @@ -307,7 +348,7 @@ add_boxes (Grob *me, Grob *x_common, Grob *y_common, vector *const boxes) edge of the just-placed grob). Otherwise, we skip it until the next pass. */ static void -add_grobs_of_one_priority (Drul_array *const skylines, +add_grobs_of_one_priority (Skyline_pair *const skylines, vector elements, Grob *x_common, Grob *y_common) @@ -354,7 +395,7 @@ add_grobs_of_one_priority (Drul_array *const skylines, 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); @@ -362,13 +403,15 @@ add_grobs_of_one_priority (Drul_array *const skylines, } } -void +Skyline_pair Axis_group_interface::skyline_spacing (Grob *me, vector 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 boxes; @@ -376,8 +419,7 @@ Axis_group_interface::skyline_spacing (Grob *me, vector elements) && !scm_is_number (elements[i]->get_property ("outside-staff-priority")); i++) add_boxes (elements[i], x_common, y_common, &boxes); - Drul_array 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"); @@ -389,6 +431,7 @@ Axis_group_interface::skyline_spacing (Grob *me, vector elements) add_grobs_of_one_priority (&skylines, current_elts, x_common, y_common); } + return skylines; } ADD_INTERFACE (Axis_group_interface, @@ -400,6 +443,6 @@ ADD_INTERFACE (Axis_group_interface, "elements " "common-refpoint-of-elements " "pure-relevant-elements " - "skyline-spacing " + "skylines " "cached-pure-extents " ); diff --git a/lily/dynamic-engraver.cc b/lily/dynamic-engraver.cc index 5c3d0feecd..8f64db1136 100644 --- a/lily/dynamic-engraver.cc +++ b/lily/dynamic-engraver.cc @@ -64,7 +64,6 @@ class Dynamic_engraver : public Engraver TRANSLATOR_DECLARATIONS (Dynamic_engraver); DECLARE_ACKNOWLEDGER (accidental); - DECLARE_ACKNOWLEDGER (script); DECLARE_ACKNOWLEDGER (stem_tremolo); DECLARE_ACKNOWLEDGER (note_column); DECLARE_ACKNOWLEDGER (slur); @@ -454,27 +453,7 @@ Dynamic_engraver::acknowledge_note_column (Grob_info info) 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); diff --git a/lily/include/accidental-placement.hh b/lily/include/accidental-placement.hh index c34fc0b766..5d09bdc2df 100644 --- a/lily/include/accidental-placement.hh +++ b/lily/include/accidental-placement.hh @@ -18,6 +18,8 @@ public: DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element)); static void add_accidental (Grob *, Grob *); + static vector get_break_reminder_accidentals (vector const &elts, + Grob *left); static Interval get_relevant_accidental_extent (Grob *me, Item *item_col, Grob *acc); diff --git a/lily/include/axis-group-interface.hh b/lily/include/axis-group-interface.hh index b38537c661..4272b1a890 100644 --- a/lily/include/axis-group-interface.hh +++ b/lily/include/axis-group-interface.hh @@ -12,6 +12,7 @@ #include "std-vector.hh" #include "lily-proto.hh" #include "grob-interface.hh" +#include "skyline.hh" struct Axis_group_interface { @@ -20,6 +21,8 @@ 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 const &list, Grob *common, Axis); static Interval relative_pure_height (Grob *me, vector const &list, @@ -28,7 +31,7 @@ struct Axis_group_interface static Interval cached_pure_height (Grob *me, vector const &list, Grob *common, int, int); - static void skyline_spacing (Grob *me, vector elements); + static Skyline_pair skyline_spacing (Grob *me, vector elements); static void add_element (Grob *me, Grob *); static void set_axes (Grob *, Axis, Axis); static bool has_axis (Grob *, Axis); diff --git a/lily/include/separation-item.hh b/lily/include/separation-item.hh index ca63294852..4fb59b5e62 100644 --- a/lily/include/separation-item.hh +++ b/lily/include/separation-item.hh @@ -12,14 +12,15 @@ #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 boxes (Grob *me); - static Interval conditional_width (Grob *, Grob *); + static vector 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 *); diff --git a/lily/include/skyline.hh b/lily/include/skyline.hh index 7f3130ecab..36fd9d23e4 100644 --- a/lily/include/skyline.hh +++ b/lily/include/skyline.hh @@ -28,6 +28,7 @@ struct Building 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; @@ -35,6 +36,7 @@ struct Building 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; }; @@ -55,16 +57,36 @@ public: Skyline (Skyline const &src); 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 () 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 skylines_; + + DECLARE_SIMPLE_SMOBS(Skyline_pair); +public: + Skyline_pair (); + Skyline_pair (vector 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 */ diff --git a/lily/script-column.cc b/lily/script-column.cc index 726b327276..a8fc0c3fc4 100644 --- a/lily/script-column.cc +++ b/lily/script-column.cc @@ -133,7 +133,19 @@ Script_column::order_grobs (vector grobs) { 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; } diff --git a/lily/separation-item.cc b/lily/separation-item.cc index 20de8fbbd5..0a6c085afc 100644 --- a/lily/separation-item.cc +++ b/lily/separation-item.cc @@ -31,17 +31,12 @@ void Separation_item::set_skyline_distance (Drul_array items, Real padding) { - Drul_array 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 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; @@ -57,63 +52,19 @@ bool Separation_item::set_distance (Drul_array 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 (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 (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 bs = boxes (me, left); + return Skyline (bs, 0.1, Y_AXIS, LEFT); } @@ -122,31 +73,31 @@ SCM 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 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 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 -Separation_item::boxes (Grob *me) +Separation_item::boxes (Grob *me, Grob *left) { Item *item = dynamic_cast (me); int very_large = INT_MAX; Paper_column *pc = item->get_column (); vector out; - extract_grob_set (me, "elements", elts); + extract_grob_set (me, left ? "conditional-elements" : "elements", read_only_elts); + vector 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); @@ -162,9 +113,12 @@ Separation_item::boxes (Grob *me) continue; Interval y (il->pure_height (ycommon, 0, very_large)); - Box b (il->extent (pc, X_AXIS), y); + Interval x (il->extent (pc, X_AXIS)); - out.push_back (b); + SCM padding = elts[i]->get_property ("padding"); + x.widen (robust_scm2double (padding, 0)); + + out.push_back (Box (x, y)); } return out; @@ -174,39 +128,7 @@ Interval 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 (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 (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 diff --git a/lily/skyline.cc b/lily/skyline.cc index ab877f28ce..6b53a62ef8 100644 --- a/lily/skyline.cc +++ b/lily/skyline.cc @@ -111,6 +111,19 @@ Building::Building (Real start, Real start_height, Real end_height, Real end) 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 () { @@ -174,6 +187,14 @@ Building::sloped_neighbour (Real horizon_padding, Direction d) const 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 *sky, Real x) { @@ -341,14 +362,9 @@ Skyline::Skyline (vector const &boxes, Real horizon_padding, Axis horizon_a 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 ())) { @@ -362,6 +378,13 @@ Skyline::Skyline (vector const &boxes, Real horizon_padding, Axis horizon_a 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) { @@ -379,14 +402,9 @@ Skyline::insert (Box const &b, Real horizon_padding, Axis a) { list other_bld; list 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 ()); } @@ -404,6 +422,17 @@ Skyline::raise (Real r) assert (is_legal_skyline ()); } +void +Skyline::shift (Real r) +{ + list::iterator end = buildings_.end (); + for (list::iterator i = buildings_.begin (); i != end; i++) + { + i->iv_[LEFT] += r; + i->iv_[RIGHT] += r; + } +} + Real Skyline::distance (Skyline const &other) const { @@ -476,6 +505,61 @@ Skyline::to_points () const return out; } +Skyline_pair::Skyline_pair () + : skylines_ (Skyline (DOWN), Skyline (UP)) +{ +} + +Skyline_pair::Skyline_pair (vector 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]; +} + /****************************************************************/ @@ -483,6 +567,10 @@ IMPLEMENT_SIMPLE_SMOBS (Skyline); 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) { @@ -499,3 +587,19 @@ Skyline::print_smob (SCM s, SCM port, scm_print_state *) 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 ("#", port); + return 1; +} diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 7fe48c14c5..b46dc5aae7 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -349,7 +349,7 @@ note that starts here.") 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 @@ -563,8 +563,6 @@ than a whole rest.") (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.") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index 7aad372102..47ef19a696 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -275,6 +275,7 @@ . ( (axes . (,Y)) (Y-extent . ,ly:axis-group-interface::height) + (skylines . ,ly:axis-group-interface::calc-skylines) (meta . ((class . Spanner) (interfaces . (axis-group-interface )))))) @@ -601,7 +602,6 @@ (font-shape . italic) (avoid-slur . around) (no-spacing-rods . #t) - (script-priority . 100) (outside-staff-priority . 250) (meta . ((class . Item) (interfaces . (font-interface @@ -1132,9 +1132,6 @@ (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) @@ -1656,7 +1653,7 @@ (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 @@ -1977,7 +1974,8 @@ (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)))))) @@ -1987,7 +1985,7 @@ (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 @@ -2083,6 +2081,7 @@ (define pure-print-callbacks (list + ly:bar-line::print ly:note-head::print ly:accidental-interface::print ly:dots::print @@ -2097,7 +2096,6 @@ (ly:stencil? sten) (memq sten pure-print-callbacks)) (ly:grob::stencil-height grob) - '(0 . 0)))) (define pure-conversions-alist