Index: ChangeLog =================================================================== RCS file: /sources/lilypond/lilypond/ChangeLog,v retrieving revision 1.5101 diff -u -r1.5101 ChangeLog --- ChangeLog 7 Jun 2006 22:01:13 -0000 1.5101 +++ ChangeLog 7 Jun 2006 22:54:54 -0000 @@ -1,3 +1,39 @@ +2006-06-08 Joe Neeman + + * scm/paper-system.scm (paper-system-annotate): also annotate the + estimated pure-Y-extent + + * scm/define-grobs.scm: add pure-Y-extent and pure-Y-offset functions + + * lily/system.cc (break_into_pieces): set the estimated height + of each child system + + * lily/stem.cc (pure_height): new pure-Y-extent callback + + * lily/staff-symbol-referencer.cc (callback): don't destroy + the staff-position property + + * lily/hara-kiri-group-spanner.cc (request_suicide): split + consider_suicide into two functions + + * lily/constrained-breaking.cc (resize): use the new pure + callbacks to estimate the height of a system + + * lily/axis-group-interface.cc (pure_group_height): new + side-effect-free VerticalAxisGroup height-callback + + * lily/align-interface.cc (get_extents_aligned_translates): + split align_elements_to_extents into two functions + (get_pure_child_y_translation): new function + + * lily/grob.cc: new functions for pure-Y-extent and pure-Y-offset + + * lily/item.cc: new functions pure_is_visible and spanned_rank_iv + + * lily/paper-score.cc: cache break_indices and columns + + * lily/side-position-interface.cc: new pure-Y-extent callbacks + 2006-06-07 Graham Percival * input/test/ add-staccato.ly, add-text-script.ly, Index: lily/align-interface.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/align-interface.cc,v retrieving revision 1.97 diff -u -r1.97 align-interface.cc --- lily/align-interface.cc 19 Feb 2006 00:14:59 -0000 1.97 +++ lily/align-interface.cc 7 Jun 2006 22:54:55 -0000 @@ -14,6 +14,7 @@ #include "hara-kiri-group-spanner.hh" #include "grob-array.hh" #include "international.hh" +#include "warn.hh" /* TODO: for vertical spacing, should also include a rod & spring @@ -145,8 +146,11 @@ align_to_fixed_distance (). */ -void -Align_interface::align_elements_to_extents (Grob *me, Axis a) +vector +Align_interface::get_extents_aligned_translates (Grob *me, + vector const &all_grobs, + Axis a, + bool pure, int start, int end) { Spanner *me_spanner = dynamic_cast (me); @@ -156,7 +160,7 @@ { line_break_details = me_spanner->get_bound (LEFT)->get_property ("line-break-system-details"); - if (!me->get_system ()) + if (!me->get_system () && !pure) me->warning (_ ("vertical alignment called before line-breaking.\n" "Only do cross-staff spanners with PianoStaff.")); @@ -171,10 +175,9 @@ vector dims; vector elems; - extract_grob_set (me, "elements", all_grobs); for (vsize i = 0; i < all_grobs.size (); i++) { - Interval y = all_grobs[i]->extent (me, a); + 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]); @@ -245,24 +248,68 @@ if (translates.size ()) { 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); + all_translates.push_back (w - center_offset); } + } + return all_translates; +} - /* - FIXME: uncommenting freaks out the Y-alignment of - line-of-score. - */ - if (scm_is_number (align)) - center_offset = total.linear_combination (scm_to_double (align)); +void +Align_interface::align_elements_to_extents (Grob *me, Axis a) +{ + extract_grob_set (me, "elements", all_grobs); + vector translates = get_extents_aligned_translates (me, all_grobs, a, false, 0, 0); + if (translates.size ()) for (vsize j = 0; j < all_grobs.size (); j++) - all_grobs[j]->translate_axis (all_translates[j] - center_offset, a); + all_grobs[j]->translate_axis (translates[j], a); +} + +Real +Align_interface::get_pure_child_y_translation (Grob *me, Grob *ch, int start, int end) +{ + extract_grob_set (me, "elements", all_grobs); + SCM dy_scm = me->get_property ("forced-distance"); + + if (scm_is_number (dy_scm)) + { + Real dy = scm_to_double (dy_scm) * robust_scm2dir (me->get_property ("stacking-dir"), DOWN); + Real pos = 0; + for (vsize i = 0; i < all_grobs.size (); i++) + { + if (all_grobs[i] == ch) + return pos; + if (!Hara_kiri_group_spanner::has_interface (all_grobs[i]) + || !Hara_kiri_group_spanner::request_suicide (all_grobs[i], start, end)) + pos += dy; + } } + else + { + vector translates = get_extents_aligned_translates (me, all_grobs, Y_AXIS, true, start, end); + + if (translates.size ()) + { + for (vsize i = 0; i < all_grobs.size (); i++) + if (all_grobs[i] == ch) + return translates[i]; + } + else + return 0; + } + + programming_error (_ ("tried to get a translation for something that isn't my child")); + return 0; } + Axis Align_interface::axis (Grob *me) { Index: lily/axis-group-interface.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/axis-group-interface.cc,v retrieving revision 1.76 diff -u -r1.76 axis-group-interface.cc --- lily/axis-group-interface.cc 16 Mar 2006 14:39:46 -0000 1.76 +++ lily/axis-group-interface.cc 7 Jun 2006 22:54:55 -0000 @@ -8,9 +8,16 @@ #include "axis-group-interface.hh" +#include "align-interface.hh" #include "pointer-group-interface.hh" #include "grob.hh" +#include "grob-array.hh" #include "hara-kiri-group-spanner.hh" +#include "international.hh" +#include "item.hh" +#include "paper-column.hh" +#include "paper-score.hh" +#include "system.hh" #include "warn.hh" void @@ -61,6 +68,89 @@ return r; } +Interval +Axis_group_interface::cached_pure_height (Grob *me, + vector const &elts, + Grob *common, + int start, int end) +{ + Paper_score *ps = get_root_system (me)->paper_score (); + vector breaks = ps->get_break_indices (); + vector cols = ps->get_columns (); + vsize start_index = VPOS; + vsize end_index = VPOS; + + for (vsize i = 0; i < breaks.size (); i++) + { + int r = Paper_column::get_rank (cols[breaks[i]]); + if (start == r) + start_index = i; + if (end == r) + end_index = i; + } + + if (start_index == VPOS || end_index == VPOS) + { + programming_error (_ ("tried to calculate pure-height at a non-breakpoint")); + return Interval (0, 0); + } + + SCM extents = me->get_property ("cached-pure-extents"); + if (!scm_is_vector (extents)) + { + extents = scm_c_make_vector (breaks.size () - 1, SCM_EOL); + for (vsize i = 0; i < breaks.size () - 1; i++) + { + int st = Paper_column::get_rank (cols[breaks[i]]); + int ed = Paper_column::get_rank (cols[breaks[i+1]]); + Interval iv = relative_pure_height (me, elts, common, st, ed, false); + scm_vector_set_x (extents, scm_from_int (i), ly_interval2scm (iv)); + } + me->set_property ("cached-pure-extents", extents); + } + + Interval ext (0, 0); + for (vsize i = start_index; i < end_index; i++) + ext.unite (ly_scm2interval (scm_c_vector_ref (extents, i))); + return ext; +} + +Interval +Axis_group_interface::relative_pure_height (Grob *me, + vector const &elts, + Grob *common, + int start, int end, + bool use_cache) +{ + /* It saves a _lot_ of time if we assume a VerticalAxisGroup is additive + (ie. height (i, k) = height (i, j) + height (j, k) for all i <= j <= k). + Unfortunately, it isn't always true, particularly if there is a + VerticalAlignment somewhere in the descendants. + + Apart from PianoStaff, which has a fixed VerticalAlignment so it doesn't + count, the only VerticalAlignment comes from Score. This makes it + reasonably safe to assume that if our parent is a VerticalAlignment, + we can assume additivity and cache things nicely. */ + Grob *p = me->get_parent (Y_AXIS); + if (use_cache && p && Align_interface::has_interface (p)) + return Axis_group_interface::cached_pure_height (me, elts, common, start, end); + + Interval r; + + for (vsize i = 0; i < elts.size (); i++) + { + Interval_t rank_span = elts[i]->spanned_rank_iv (); + Item *it = dynamic_cast (elts[i]); + if (rank_span[LEFT] <= end && rank_span[RIGHT] >= start && (!it || it->pure_is_visible (start, end))) + { + Interval dims = elts[i]->pure_height (common, start, end); + if (!dims.is_empty ()) + r.unite (dims); + } + } + return r; +} + MAKE_SCHEME_CALLBACK (Axis_group_interface, width, 1); SCM Axis_group_interface::width (SCM smob) @@ -76,6 +166,17 @@ Grob *me = unsmob_grob (smob); return generic_group_extent (me, Y_AXIS); } + +MAKE_SCHEME_CALLBACK (Axis_group_interface, pure_height, 3); +SCM +Axis_group_interface::pure_height (SCM smob, SCM start_scm, SCM end_scm) +{ + int start = robust_scm2int (start_scm, 0); + int end = robust_scm2int (end_scm, INT_MAX); + Grob *me = unsmob_grob (smob); + + return pure_group_height (me, start, end); +} SCM Axis_group_interface::generic_group_extent (Grob *me, Axis a) @@ -89,6 +190,38 @@ return ly_interval2scm (r - my_coord); } +SCM +Axis_group_interface::pure_group_height (Grob *me, int start, int end) +{ + Grob *common = unsmob_grob (me->get_object ("common-refpoint-of-elements")); + + if (!common) + { + extract_grob_set (me, "elements", elts); + + vector relevant_elts; + SCM is_relevant = ly_lily_module_constant ("pure-relevant"); + + for (vsize i = 0; i < elts.size (); i++) + if (to_boolean (scm_apply_1 (is_relevant, elts[i]->self_scm (), SCM_EOL))) + relevant_elts.push_back (elts[i]); + + common = common_refpoint_of_array (relevant_elts, me, Y_AXIS); + me->set_object ("common-refpoint-of-elements", common->self_scm ()); + + SCM ga_scm = Grob_array::make_array (); + Grob_array *ga = unsmob_grob_array (ga_scm); + ga->set_array (relevant_elts); + me->set_object ("pure-relevant-elements", ga_scm); + } + + extract_grob_set (me, "pure-relevant-elements", elts); + Real my_coord = me->relative_coordinate (common, Y_AXIS); + Interval r (relative_pure_height (me, elts, common, start, end, true)); + + return ly_interval2scm (r - my_coord); +} + void Axis_group_interface::get_children (Grob *me, vector *found) { @@ -111,4 +244,8 @@ /* properties */ "axes " - "elements "); + "elements " + "common-refpoint-of-elements " + "pure-relevant-elements " + "cached-pure-extents " + ); Index: lily/constrained-breaking.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/constrained-breaking.cc,v retrieving revision 1.6 diff -u -r1.6 constrained-breaking.cc --- lily/constrained-breaking.cc 9 May 2006 02:15:56 -0000 1.6 +++ lily/constrained-breaking.cc 7 Jun 2006 22:54:55 -0000 @@ -147,9 +147,9 @@ if (!breaks_.size () && pscore_) { Output_def *l = pscore_->layout (); - Real extent = scm_to_double (l->c_variable ("system-height")); - Real padding = scm_to_double (l->c_variable ("between-system-padding")); - Real space = scm_to_double (l->c_variable ("between-system-space")); + System *sys = pscore_->root_system (); + Real padding = robust_scm2double (l->c_variable ("between-system-padding"), 0); + Real space = robust_scm2double (l->c_variable ("ideal-system-space"), 0); bool ragged_right = to_boolean (pscore_->layout ()->c_variable ("ragged-right")); bool ragged_last = to_boolean (pscore_->layout ()->c_variable ("ragged-last")); @@ -167,8 +167,12 @@ ragged_right); for (vsize i = 0; i < breaks_.size () - 1; i++) { + Real max_ext = 0; for (vsize j = i + 1; j < breaks_.size (); j++) { + int start = Paper_column::get_rank (all_[breaks_[i]]); + int end = Paper_column::get_rank (all_[breaks_[j]]); + Interval extent = sys->pure_height (sys, start, end); bool last = j == breaks_.size () - 1; bool ragged = ragged_right || (last && ragged_last); int k = i*lines_rank_ + j; @@ -176,11 +180,12 @@ if (scm_is_number (pen)) lines_[k].break_penalty_ = scm_to_double (pen); + max_ext = max (max_ext, extent.length ()); lines_[k].force_ = forces[k]; - lines_[k].extent_ = extent; + lines_[k].extent_ = extent.length (); lines_[k].padding_ = padding; lines_[k].space_ = space; - lines_[k].inverse_hooke_ = 3; // FIXME: somewhat arbitrary + lines_[k].inverse_hooke_ = 1; if (ragged && lines_[k].force_ < 0) lines_[k].force_ = infinity_f; if (isinf (lines_[k].force_)) @@ -335,6 +340,6 @@ Real Constrained_breaking::combine_demerits (Real force, Real prev_force) { - return force * force + fabs (prev_force - force); + return force * force + (prev_force - force) * (prev_force - force); } Index: lily/grob.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/grob.cc,v retrieving revision 1.170 diff -u -r1.170 grob.cc --- lily/grob.cc 28 May 2006 22:13:20 -0000 1.170 +++ lily/grob.cc 7 Jun 2006 22:54:56 -0000 @@ -10,6 +10,7 @@ #include +#include "align-interface.hh" #include "input-smob.hh" #include "international.hh" #include "item.hh" @@ -278,6 +279,37 @@ return off; } +Real +Grob::pure_relative_y_coordinate (Grob const *refp, int start, int end) +{ + if (refp == this) + return 0.0; + + SCM pure_off = ly_lily_module_constant ("pure-Y-offset"); + Real off = 0; + + if (dim_cache_[Y_AXIS].offset_) + off = *dim_cache_[Y_AXIS].offset_; + else if (ly_is_procedure (pure_off)) + { + dim_cache_[Y_AXIS].offset_ = new Real (0.0); + off = scm_to_double (scm_apply_3 (pure_off, self_scm (), + scm_from_int (start), scm_from_int (end), + SCM_EOL)); + delete dim_cache_[Y_AXIS].offset_; + dim_cache_[Y_AXIS].offset_ = 0; + } + + /* we simulate positioning-done if we are the child of a VerticalAlignment */ + Grob *p = get_parent (Y_AXIS); + Real trans = 0; + if (Align_interface::has_interface (p)) + trans = Align_interface::get_pure_child_y_translation (p, this, start, end); + + return off + trans + + dim_cache_[Y_AXIS].parent_->pure_relative_y_coordinate (refp, start, end); +} + /* Invoke callbacks to get offset relative to parent. */ Real Grob::get_offset (Axis a) const @@ -305,6 +337,14 @@ return 0.0; } +Real +Grob::maybe_pure_coordinate (Grob const *refp, Axis a, bool pure, int start, int end) +{ + if (pure && a != Y_AXIS) + programming_error ("tried to get pure X-offset"); + return (pure && a == Y_AXIS) ? pure_relative_y_coordinate (refp, start, end) + : relative_coordinate (refp, a); +} /**************************************************************** extents @@ -358,7 +398,6 @@ SCM min_ext = internal_get_property (min_ext_sym); if (is_number_pair (min_ext)) real_ext.unite (ly_scm2interval (min_ext)); - ((Grob*)this)->del_property (ext_sym); ((Grob*)this)->dim_cache_[a].extent_ = new Interval (real_ext); } @@ -367,6 +406,36 @@ return real_ext; } +Interval +Grob::pure_height (Grob *refp, int start, int end) +{ + SCM pure_height = ly_lily_module_constant ("pure-Y-extent"); + Interval iv (0, 0); + + if (ly_is_procedure (pure_height)) + iv = ly_scm2interval (scm_apply_3 (pure_height, self_scm (), + scm_from_int (start), scm_from_int (end), + SCM_EOL)); + Real offset = pure_relative_y_coordinate (refp, start, end); + + iv.translate (offset); + return iv; +} + +Interval +Grob::maybe_pure_extent (Grob *refp, Axis a, bool pure, int start, int end) +{ + if (pure && a != Y_AXIS) + programming_error ("tried to get pure width"); + return (pure && a == Y_AXIS) ? pure_height (refp, start, end) : extent (refp, a); +} + +Interval_t +Grob::spanned_rank_iv () +{ + return Interval_t (INT_MIN, INT_MAX); +} + /**************************************************************** REFPOINTS ****************************************************************/ Index: lily/hara-kiri-group-spanner.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/hara-kiri-group-spanner.cc,v retrieving revision 1.54 diff -u -r1.54 hara-kiri-group-spanner.cc --- lily/hara-kiri-group-spanner.cc 16 Mar 2006 14:39:46 -0000 1.54 +++ lily/hara-kiri-group-spanner.cc 7 Jun 2006 22:54:56 -0000 @@ -25,22 +25,84 @@ return Axis_group_interface::generic_group_extent (me, Y_AXIS); } -void -Hara_kiri_group_spanner::consider_suicide (Grob *me) +MAKE_SCHEME_CALLBACK (Hara_kiri_group_spanner, pure_height, 3); +SCM +Hara_kiri_group_spanner::pure_height (SCM smob, SCM start_scm, SCM end_scm) { - Spanner *sp = dynamic_cast (me); - if (!to_boolean (me->get_property ("remove-empty"))) - return ; + Grob *me = unsmob_grob (smob); + int start = robust_scm2int (start_scm, 0); + int end = robust_scm2int (end_scm, INT_MAX); - extract_grob_set (me, "items-worth-living", worth); - if (worth.size ()) - return; + if (request_suicide (me, start, end)) + return ly_interval2scm (Interval ()); + return Axis_group_interface::pure_group_height (me, start, end); +} + +/* there is probably a way that doesn't involve re-implementing a binary + search (I would love some proper closures right now) */ +bool find_in_range (SCM vector, int low, int hi, int min, int max) +{ + if (low >= hi) + return false; + + int mid = low + (hi - low) / 2; + int val = scm_to_int (scm_c_vector_ref (vector, mid)); + if (val >= min && val <= max) + return true; + else if (val < min) + return find_in_range (vector, mid+1, hi, min, max); + return find_in_range (vector, low, mid, min, max); +} + +bool +Hara_kiri_group_spanner::request_suicide (Grob *me, int start, int end) +{ + if (!to_boolean (me->get_property ("remove-empty"))) + return false; bool remove_first = to_boolean (me->get_property ("remove-first")); - if (!remove_first - && ((sp->original () && broken_spanner_index (sp) == 0) - || Paper_column::get_rank (sp->get_bound (LEFT)->get_column ()) - == 0)) + if (!remove_first && start <= 0) + return false; + + SCM important = me->get_property ("important-column-ranks"); + if (scm_is_vector (important)) + { + int len = scm_c_vector_length (important); + if (find_in_range (important, 0, len-1, start, end)) + return false; + } + else /* build the important-columns-cache */ + { + extract_grob_set (me, "items-worth-living", worth); + vector ranks; + + for (vsize i = 0; i < worth.size (); i++) + { + Item *it = dynamic_cast (worth[i]); + if (it) + ranks.push_back (Paper_column::get_rank (it->get_column ())); + } + vector_sort (ranks, default_compare); + uniq (ranks); + + SCM scm_vec = scm_c_make_vector (ranks.size (), SCM_EOL); + for (vsize i = 0; i < ranks.size (); i++) + scm_vector_set_x (scm_vec, scm_from_int (i), scm_from_int (ranks[i])); + me->set_property ("important-column-ranks", scm_vec); + + return request_suicide (me, start, end); + } + + return true; +} + +void +Hara_kiri_group_spanner::consider_suicide (Grob *me) +{ + Spanner *sp = dynamic_cast (me); + int left = sp->get_bound (LEFT)->get_column ()->get_rank (); + int right = sp->get_bound (RIGHT)->get_column ()->get_rank (); + if (!request_suicide (me, left, right)) return; vector childs; @@ -99,6 +161,7 @@ /* properties */ "items-worth-living " + "important-column-ranks " "remove-empty " "remove-first " ); Index: lily/item.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/item.cc,v retrieving revision 1.124 diff -u -r1.124 item.cc --- lily/item.cc 9 May 2006 02:15:56 -0000 1.124 +++ lily/item.cc 7 Jun 2006 22:54:56 -0000 @@ -8,6 +8,7 @@ #include "item.hh" +#include "axis-group-interface.hh" #include "paper-score.hh" #include "warn.hh" #include "paper-column.hh" @@ -149,13 +150,47 @@ SCM vis = get_property ("break-visibility"); if (scm_is_vector (vis)) { - bool visible = to_boolean (scm_vector_ref (vis, scm_from_int (break_status_dir () + 1))); + bool visible = to_boolean (scm_c_vector_ref (vis, break_status_dir () + 1)); if (!visible) - suicide (); + { + Grob *p = unsmob_grob (get_object ("axis-group-parent-Y")); + if (!original () && p) + { + if (to_boolean (scm_c_vector_ref (vis, LEFT + 1))) + Axis_group_interface::add_element (p, broken_to_drul_[LEFT]); + else if (to_boolean (scm_c_vector_ref (vis, RIGHT + 1))) + Axis_group_interface::add_element (p, broken_to_drul_[RIGHT]); + } + suicide (); + } } } +bool +Item::pure_is_visible (int start, int end) const +{ + SCM vis = get_property ("break-visibility"); + if (scm_is_vector (vis)) + { + int pos = 1; + int pc_rank = Paper_column::get_rank (get_column ()); + if (pc_rank == start) + pos = 2; + else if (pc_rank == end) + pos = 0; + return to_boolean (scm_vector_ref (vis, scm_from_int (pos))); + } + return true; +} + +Interval_t +Item::spanned_rank_iv () +{ + int c = get_column ()->get_rank (); + return Interval_t (c, c); +} + void Item::derived_mark () const { Index: lily/paper-score.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/paper-score.cc,v retrieving revision 1.102 diff -u -r1.102 paper-score.cc --- lily/paper-score.cc 9 May 2006 02:15:56 -0000 1.102 +++ lily/paper-score.cc 7 Jun 2006 22:54:56 -0000 @@ -75,9 +75,27 @@ retval.push_back (i); } + cols_ = all; + break_indices_ = retval; + return retval; } +vector +Paper_score::get_break_indices () const +{ + if (break_indices_.empty ()) + find_break_indices (); + return break_indices_; +} + +vector +Paper_score::get_columns () const +{ + if (cols_.empty ()) + find_break_indices (); + return cols_; +} vector Paper_score::calc_breaking () Index: lily/side-position-interface.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/side-position-interface.cc,v retrieving revision 1.124 diff -u -r1.124 side-position-interface.cc --- lily/side-position-interface.cc 16 Mar 2006 14:39:46 -0000 1.124 +++ lily/side-position-interface.cc 7 Jun 2006 22:54:56 -0000 @@ -48,7 +48,8 @@ /* Put the element next to the support, optionally taking in account the extent of the support. */ SCM -Side_position_interface::general_side_position (Grob *me, Axis a, bool use_extents) +Side_position_interface::general_side_position (Grob *me, Axis a, bool use_extents, + bool pure, int start, int end) { Real ss = Staff_symbol_referencer::staff_space (me); @@ -67,7 +68,7 @@ if (include_staff) { common = staff_symbol->common_refpoint (common, Y_AXIS); - staff_extents = staff_symbol->extent (common, Y_AXIS); + staff_extents = staff_symbol->maybe_pure_extent (common, Y_AXIS, pure, start, end); if (include_staff) dim.unite (staff_extents); @@ -78,10 +79,10 @@ Grob *e = support[i]; if (e) if (use_extents) - dim.unite (e->extent (common, a)); + dim.unite (e->maybe_pure_extent (common, a, pure, start, end)); else { - Real x = e->relative_coordinate (common, a); + Real x = e->maybe_pure_coordinate (common, a, pure, start, end); dim.unite (Interval (x, x)); } } @@ -91,7 +92,7 @@ Direction dir = get_grob_direction (me); - Real off = me->get_parent (a)->relative_coordinate (common, a); + Real off = me->get_parent (a)->maybe_pure_coordinate (common, a, pure, start, end); Real minimum_space = ss * robust_scm2double (me->get_property ("minimum-space"), -1); Real total_off = dim.linear_combination (dir) - off; @@ -118,13 +119,19 @@ MAKE_SCHEME_CALLBACK (Side_position_interface, y_aligned_on_support_refpoints, 1); - SCM Side_position_interface::y_aligned_on_support_refpoints (SCM smob) { - return general_side_position (unsmob_grob (smob), Y_AXIS, false); + return general_side_position (unsmob_grob (smob), Y_AXIS, false, false, 0, 0); } +MAKE_SCHEME_CALLBACK (Side_position_interface, pure_y_aligned_on_support_refpoints, 3); +SCM +Side_position_interface::pure_y_aligned_on_support_refpoints (SCM smob, SCM start, SCM end) +{ + return general_side_position (unsmob_grob (smob), Y_AXIS, false, + true, scm_to_int (start), scm_to_int (end)); +} /* @@ -135,23 +142,30 @@ SCM Side_position_interface::x_aligned_side (SCM smob) { - return aligned_side (unsmob_grob (smob), X_AXIS); + return aligned_side (unsmob_grob (smob), X_AXIS, false, 0, 0); } MAKE_SCHEME_CALLBACK (Side_position_interface, y_aligned_side, 1); SCM Side_position_interface::y_aligned_side (SCM smob) { - return aligned_side (unsmob_grob (smob), Y_AXIS); + return aligned_side (unsmob_grob (smob), Y_AXIS, false, 0, 0); +} + +MAKE_SCHEME_CALLBACK (Side_position_interface, pure_y_aligned_side, 3); +SCM +Side_position_interface::pure_y_aligned_side (SCM smob, SCM start, SCM end) +{ + return aligned_side (unsmob_grob (smob), Y_AXIS, true, scm_to_int (start), scm_to_int (end)); } SCM -Side_position_interface::aligned_side (Grob *me, Axis a) +Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, int end) { Direction dir = get_grob_direction (me); - Real o = scm_to_double (general_side_position (me, a, true)); - Interval iv = me->extent (me, a); + Real o = scm_to_double (general_side_position (me, a, true, pure, start, end)); + Interval iv = me->maybe_pure_extent (me, a, pure, start, end); if (!iv.is_empty ()) { @@ -174,8 +188,8 @@ if (to_boolean (me->get_property ("quantize-position"))) { Grob *common = me->common_refpoint (staff, Y_AXIS); - Real my_off = me->relative_coordinate (common, Y_AXIS); - Real staff_off = staff->relative_coordinate (common, Y_AXIS); + Real my_off = me->get_parent (Y_AXIS)->maybe_pure_coordinate (common, Y_AXIS, pure, start, end); + Real staff_off = staff->maybe_pure_coordinate (common, Y_AXIS, pure, start, end); Real ss = Staff_symbol::staff_space (staff); Real position = 2 * (my_off + o - staff_off) / ss; Real rounded = directed_round (position, dir); @@ -198,7 +212,7 @@ Grob *common = me->common_refpoint (staff, Y_AXIS); - Interval staff_size = staff->extent (common, Y_AXIS); + Interval staff_size = staff->maybe_pure_extent (common, Y_AXIS, pure, start, end); Real diff = dir*staff_size[dir] + padding - dir * (o + iv[-dir]); o += dir * max (diff, 0.0); } Index: lily/staff-symbol-referencer.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/staff-symbol-referencer.cc,v retrieving revision 1.87 diff -u -r1.87 staff-symbol-referencer.cc --- lily/staff-symbol-referencer.cc 6 Feb 2006 01:13:58 -0000 1.87 +++ lily/staff-symbol-referencer.cc 7 Jun 2006 22:54:56 -0000 @@ -110,7 +110,6 @@ { Real space = Staff_symbol_referencer::staff_space (me); off = scm_to_double (pos) * space / 2.0; - me->set_property ("staff-position", scm_from_int (0)); } return scm_from_double (off); Index: lily/stem.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/stem.cc,v retrieving revision 1.307 diff -u -r1.307 stem.cc --- lily/stem.cc 22 May 2006 17:45:40 -0000 1.307 +++ lily/stem.cc 7 Jun 2006 22:54:58 -0000 @@ -225,6 +225,28 @@ && scm_to_int (me->get_property ("duration-log")) >= 1); } +MAKE_SCHEME_CALLBACK (Stem, pure_height, 3) +SCM +Stem::pure_height (SCM smob, SCM start, SCM end) +{ + Grob *me = unsmob_grob (smob); + Real ss = Staff_symbol_referencer::staff_space (me); + Real len = scm_to_double (calc_length (smob)) * ss / 2; + Direction dir = get_grob_direction (me); + + Interval iv; + Interval hp = head_positions (me); + if (dir == UP) + iv = Interval (0, len); + else + iv = Interval (-len, 0); + + if (!hp.is_empty ()) + iv.translate (hp[dir] * ss / 2); + + return ly_interval2scm (iv); +} + MAKE_SCHEME_CALLBACK (Stem, calc_stem_end_position, 1) SCM Stem::calc_stem_end_position (SCM smob) Index: lily/system.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/system.cc,v retrieving revision 1.143 diff -u -r1.143 system.cc --- lily/system.cc 28 May 2006 18:03:49 -0000 1.143 +++ lily/system.cc 7 Jun 2006 22:54:58 -0000 @@ -23,7 +23,6 @@ #include "staff-symbol-referencer.hh" #include "tweak-registration.hh" #include "warn.hh" -#include "warn.hh" System::System (System const &src, int count) : Spanner (src, count) @@ -206,6 +205,11 @@ vector c (breaking[i].cols_); pscore_->typeset_system (system); + int st = Paper_column::get_rank (c[0]); + int end = Paper_column::get_rank (c.back ()); + Interval iv (pure_height (this, st, end)); + system->set_property ("pure-Y-extent", ly_interval2scm (iv)); + system->set_bound (LEFT, c[0]); system->set_bound (RIGHT, c.back ()); for (vsize j = 0; j < c.size (); j++) @@ -504,5 +508,6 @@ /* properties */ "all-elements " "columns " + "pure-Y-extent " "spaceable-staves " ) Index: lily/include/align-interface.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/align-interface.hh,v retrieving revision 1.29 diff -u -r1.29 align-interface.hh --- lily/include/align-interface.hh 6 Jan 2006 09:13:24 -0000 1.29 +++ lily/include/align-interface.hh 7 Jun 2006 22:54:58 -0000 @@ -11,6 +11,7 @@ #include "lily-proto.hh" #include "lily-guile.hh" +#include "std-vector.hh" struct Align_interface { @@ -18,12 +19,17 @@ DECLARE_SCHEME_CALLBACK (stretch_after_break, (SCM element)); static void align_to_fixed_distance (Grob *, Axis a); static void align_elements_to_extents (Grob *, Axis a); + static vector get_extents_aligned_translates (Grob *, vector const&, + Axis a, + bool safe, int start, int end); static void set_ordered (Grob *); static Axis axis (Grob *); static void add_element (Grob *, Grob *); static int get_count (Grob *, Grob *); static bool has_interface (Grob *); + + static Real get_pure_child_y_translation (Grob *, Grob *child, int start, int end); }; Grob *find_fixed_alignment_parent (Grob *g); Index: lily/include/axis-group-interface.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/axis-group-interface.hh,v retrieving revision 1.30 diff -u -r1.30 axis-group-interface.hh --- lily/include/axis-group-interface.hh 16 Feb 2006 11:54:21 -0000 1.30 +++ lily/include/axis-group-interface.hh 7 Jun 2006 22:54:58 -0000 @@ -18,10 +18,17 @@ struct Axis_group_interface { static SCM generic_group_extent (Grob *me, Axis a); + static SCM pure_group_height (Grob *me, int start, int end); DECLARE_SCHEME_CALLBACK (width, (SCM smob)); DECLARE_SCHEME_CALLBACK (height, (SCM smob)); + DECLARE_SCHEME_CALLBACK (pure_height, (SCM smob, SCM start, SCM end)); static Interval relative_group_extent (vector const &list, Grob *common, Axis); + static Interval relative_pure_height (Grob *me, vector const &list, + Grob *common, int start, int end, + bool use_cache); + static Interval cached_pure_height (Grob *me, vector const &list, + Grob *common, int, int); static void add_element (Grob *me, Grob *); static void set_axes (Grob *, Axis, Axis); Index: lily/include/constrained-breaking.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/constrained-breaking.hh,v retrieving revision 1.7 diff -u -r1.7 constrained-breaking.hh --- lily/include/constrained-breaking.hh 9 May 2006 02:15:56 -0000 1.7 +++ lily/include/constrained-breaking.hh 7 Jun 2006 22:54:58 -0000 @@ -17,7 +17,8 @@ Real force_; Real extent_; /* Y-extent of the system */ Real padding_; /* compulsory space after this system (if we're not last on a page) */ - Real space_; /* spring length (stretches over extent_ but not over padding_) */ + Real bottom_padding_; + Real space_; /* spring length */ Real inverse_hooke_; SCM break_permission_; @@ -32,6 +33,7 @@ force_ = infinity_f; extent_ = 0; padding_ = 0; + bottom_padding_ = 0; space_ = 0; inverse_hooke_ = 1; break_permission_ = ly_symbol2scm ("allow"); Index: lily/include/grob.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/grob.hh,v retrieving revision 1.80 diff -u -r1.80 grob.hh --- lily/include/grob.hh 11 Feb 2006 11:35:16 -0000 1.80 +++ lily/include/grob.hh 7 Jun 2006 22:54:58 -0000 @@ -109,16 +109,22 @@ /* offsets */ void translate_axis (Real, Axis); Real relative_coordinate (Grob const *refp, Axis) const; + Real pure_relative_y_coordinate (Grob const *refp, int start, int end); + Real maybe_pure_coordinate (Grob const *refp, Axis a, bool pure, int start, int end); /* extents */ Interval extent (Grob *refpoint, Axis) const; void flush_extent_cache (Axis); + Interval pure_height (Grob *refpoint, int start_col, int end_col); + Interval maybe_pure_extent (Grob *refpoint, Axis, bool pure, int start, int end); /* refpoints */ Grob *common_refpoint (Grob const *s, Axis a) const; void set_parent (Grob *e, Axis); Grob *get_parent (Axis a) const; void fixup_refpoint (); + + virtual Interval_t spanned_rank_iv (); }; /* smob utilities */ Index: lily/include/hara-kiri-group-spanner.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/hara-kiri-group-spanner.hh,v retrieving revision 1.21 diff -u -r1.21 hara-kiri-group-spanner.hh --- lily/include/hara-kiri-group-spanner.hh 5 Feb 2006 00:23:21 -0000 1.21 +++ lily/include/hara-kiri-group-spanner.hh 7 Jun 2006 22:54:58 -0000 @@ -17,9 +17,11 @@ public: DECLARE_SCHEME_CALLBACK (force_hara_kiri_callback, (SCM)); DECLARE_SCHEME_CALLBACK (y_extent, (SCM smob)); + DECLARE_SCHEME_CALLBACK (pure_height, (SCM smob, SCM start, SCM end)); DECLARE_SCHEME_CALLBACK (force_hara_kiri_in_y_parent_callback, (SCM)); DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM)); static bool has_interface (Grob *); + static bool request_suicide (Grob *me, int start, int end); static void consider_suicide (Grob *me); static void add_interesting_item (Grob *me, Grob *n); }; Index: lily/include/item.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/item.hh,v retrieving revision 1.62 diff -u -r1.62 item.hh --- lily/include/item.hh 9 May 2006 02:15:56 -0000 1.62 +++ lily/include/item.hh 7 Jun 2006 22:54:58 -0000 @@ -30,6 +30,7 @@ static bool is_non_musical (Grob *); bool is_broken () const; + bool pure_is_visible (int start, int end) const; Direction break_status_dir () const; @@ -38,6 +39,7 @@ virtual System *get_system () const; virtual Paper_column *get_column () const; virtual void handle_prebroken_dependencies (); + virtual Interval_t spanned_rank_iv (); static bool has_interface (Grob *); protected: virtual void discretionary_processing (); Index: lily/include/paper-score.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/paper-score.hh,v retrieving revision 1.41 diff -u -r1.41 paper-score.hh --- lily/include/paper-score.hh 4 May 2006 09:49:38 -0000 1.41 +++ lily/include/paper-score.hh 7 Jun 2006 22:54:58 -0000 @@ -19,6 +19,9 @@ System *system_; SCM systems_; SCM paper_systems_; + + mutable vector cols_; + mutable vector break_indices_; public: Paper_score (Output_def *); @@ -30,6 +33,8 @@ void typeset_system (System *); vector calc_breaking (); vector find_break_indices () const; + vector get_break_indices () const; + vector get_columns () const; SCM get_paper_systems (); protected: virtual void process (); Index: lily/include/side-position-interface.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/side-position-interface.hh,v retrieving revision 1.33 diff -u -r1.33 side-position-interface.hh --- lily/include/side-position-interface.hh 18 Jan 2006 13:41:06 -0000 1.33 +++ lily/include/side-position-interface.hh 7 Jun 2006 22:54:58 -0000 @@ -22,12 +22,14 @@ public: DECLARE_SCHEME_CALLBACK (y_aligned_on_support_refpoints, (SCM element)); + DECLARE_SCHEME_CALLBACK (pure_y_aligned_on_support_refpoints, (SCM element, SCM start, SCM end)); DECLARE_SCHEME_CALLBACK (x_aligned_side, (SCM element)); DECLARE_SCHEME_CALLBACK (y_aligned_side, (SCM element)); + DECLARE_SCHEME_CALLBACK (pure_y_aligned_side, (SCM element, SCM start, SCM end)); - static SCM aligned_side (Grob*me, Axis a); + static SCM aligned_side (Grob*me, Axis a, bool pure, int start, int end); - static SCM general_side_position (Grob *, Axis, bool); + static SCM general_side_position (Grob *, Axis, bool, bool pure, int start, int end); static Axis get_axis (Grob *); static void set_axis (Grob *, Axis); static bool has_interface (Grob *); Index: lily/include/spanner.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/spanner.hh,v retrieving revision 1.81 diff -u -r1.81 spanner.hh --- lily/include/spanner.hh 11 Feb 2006 11:35:16 -0000 1.81 +++ lily/include/spanner.hh 7 Jun 2006 22:54:58 -0000 @@ -45,8 +45,7 @@ void substitute_one_mutable_property (SCM sym, SCM val); bool fast_substitute_grob_array (SCM sym, Grob_array *); - // TODO: make virtual and do this for Items as well. - Interval_t spanned_rank_iv (); + virtual Interval_t spanned_rank_iv (); void set_bound (Direction d, Grob *); Item *get_bound (Direction d) const; Index: lily/include/stem.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/stem.hh,v retrieving revision 1.103 diff -u -r1.103 stem.hh --- lily/include/stem.hh 16 Feb 2006 11:54:21 -0000 1.103 +++ lily/include/stem.hh 7 Jun 2006 22:54:58 -0000 @@ -50,6 +50,7 @@ DECLARE_SCHEME_CALLBACK (calc_stem_info, (SCM)); DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM)); DECLARE_SCHEME_CALLBACK (width, (SCM smob)); + DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM)); DECLARE_SCHEME_CALLBACK (height, (SCM)); }; #endif Index: scm/define-grob-properties.scm =================================================================== RCS file: /sources/lilypond/lilypond/scm/define-grob-properties.scm,v retrieving revision 1.167 diff -u -r1.167 define-grob-properties.scm --- scm/define-grob-properties.scm 2 Jun 2006 00:34:28 -0000 1.167 +++ scm/define-grob-properties.scm 7 Jun 2006 22:54:59 -0000 @@ -484,6 +484,9 @@ (apply define-internal-grob-property x)) `( + (pure-relevant-elements ,ly:grob-array? "The subset of elements that are relevant for finding the pure-Y-extent.") + (cached-pure-extents ,vector? "Used by a VerticalAxisGroup to cache the Y-extents of different column ranges.") + (common-refpoint-of-elements ,ly:grob? "Caches the common_refpoint_of_array of the elements grob-set") (axis-group-parent-X ,ly:grob? "Containing X axis group") (axis-group-parent-Y ,ly:grob? "Containing Y axis group") (accidental-grobs ,list? "Alist with (NOTENAME . GROBLIST) entries") @@ -498,6 +501,7 @@ (dot ,ly:grob? "reference to Dots object.") (dots ,ly:grob-array? "multiple Dots objects.") (figures ,ly:grob-array? "Figured bass objects for continuation line.") + (important-column-ranks ,vector? "Cache of columns that contain items-worth-living.") (glyph-name ,string? "a name of character within font.") (pedal-text ,ly:grob? "Pointer to the text of a mixed-style piano pedal.") (stem ,ly:grob? "pointer to Stem object.") @@ -555,6 +559,7 @@ (positioning-done ,boolean? "Used to signal that a positioning element did its job. This ensures that a positioning is only done once.") + (pure-Y-extent ,number-pair? "The estimated height of a system") (script-stencil ,pair? "Pair (@code{type} . @code{arg}), which Index: scm/define-grobs.scm =================================================================== RCS file: /sources/lilypond/lilypond/scm/define-grobs.scm,v retrieving revision 1.334 diff -u -r1.334 define-grobs.scm --- scm/define-grobs.scm 30 May 2006 15:47:16 -0000 1.334 +++ scm/define-grobs.scm 7 Jun 2006 22:55:00 -0000 @@ -67,7 +67,7 @@ . ( (axes . (0 1)) (X-extent . ,ly:axis-group-interface::width) - (X-extent . ,ly:axis-group-interface::height) + (Y-extent . ,ly:axis-group-interface::height) (space-alist . ( (clef . (extra-space . 0.5)) (key-signature . (extra-space . 0.0)) @@ -1314,7 +1314,7 @@ (meta . ((class . Spanner) (interfaces . (slur-interface)))))) - (SostenutoPedal + (SostenutoPedal . ( (stencil . ,ly:text-interface::print) (direction . ,RIGHT) @@ -1938,3 +1938,68 @@ (set! all-grob-descriptions (sort all-grob-descriptions alist