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 3 Jun 2006 02:10:06 -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,50 @@ 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); + 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 3 Jun 2006 02:10:06 -0000 @@ -8,10 +8,17 @@ #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 "item.hh" +#include "paper-column.hh" +#include "paper-score.hh" +#include "system.hh" #include "warn.hh" +#include "international.hh" void Axis_group_interface::add_element (Grob *me, Grob *e) @@ -61,6 +68,92 @@ 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_brk = VPOS; + vsize end_brk = VPOS; + + for (vsize i = 0; i < breaks.size (); i++) + { + int r = Paper_column::get_rank (cols[breaks[i]]); + if (start == r) + start_brk = i; + if (end == r) + end_brk = i; + } + + if (start_brk == VPOS || end_brk == 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_brk; i < end_brk; 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 ()) + { + message (_f ("%s %d-%d has child %s with extent (%f,%f)", me->name().c_str(), start, end, elts[i]->name().c_str(), dims[UP], dims[DOWN])); + r.unite (dims); + } + } + } + return r; +} + MAKE_SCHEME_CALLBACK (Axis_group_interface, width, 1); SCM Axis_group_interface::width (SCM smob) @@ -76,6 +169,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 +193,41 @@ 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)); + + // ly_display_scm (me->self_scm ()); + // message (_f ("has pure-extent (%f,%f)\n", r[UP], r[DOWN])); + + return ly_interval2scm (r - my_coord); +} + void Axis_group_interface::get_children (Grob *me, vector *found) { @@ -111,4 +250,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 3 Jun 2006 02:10:07 -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,13 @@ ragged_right); for (vsize i = 0; i < breaks_.size () - 1; i++) { + //message (_f ("extents starting at %d", Paper_column::get_rank (all_[breaks_[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,16 +181,18 @@ 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_)) break; } + //message (_f ("max extent was %f", max_ext)); } /* work out all the starting indices */ @@ -335,6 +342,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 3 Jun 2006 02:10:16 -0000 @@ -10,6 +10,7 @@ #include +#include "align-interface.hh" #include "input-smob.hh" #include "international.hh" #include "item.hh" @@ -278,6 +279,49 @@ return off; } +Real +Grob::pure_relative_y_coordinate (Grob const *refp, int start, int end) +{ + if (refp == this) + return 0.0; + + SCM cached = get_property ("pure-Y-offset-cache"); + Real off = 0; + if (scm_is_number (cached)) + off = scm_to_double (cached); + else + { + SCM pure_offsets = ly_lily_module_constant ("pure-Y-offsets"); + SCM conversions = ly_lily_module_constant ("Y-offset-conversions"); + SCM y_offset = get_property_data (ly_symbol2scm ("Y-offset")); + + if (scm_is_pair (scm_assq (y_offset, pure_offsets))) + off = scm_to_double (get_property ("Y-offset")); + else + { + SCM conv = scm_assq (y_offset, conversions); + if (scm_is_pair (conv)) + { + SCM proc = scm_cdr (conv); + set_property ("pure-Y-offset-cache", scm_from_double (0)); + SCM soff = scm_apply_3 (proc, self_scm (), scm_from_int (start), scm_from_int (end), SCM_EOL); + off = scm_to_double (soff); + } + } + } + + /* pure-Y-offset is always cacheable? (pure Alignment is not included yet) */ + set_property ("pure-Y-offset-cache", scm_from_double (off)); + + 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 +349,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 (_f ("tried to get pure X-offset")); + return (pure && a == Y_AXIS) ? pure_relative_y_coordinate (refp, start, end) + : relative_coordinate (refp, a); +} /**************************************************************** extents @@ -367,6 +419,58 @@ return real_ext; } +Interval +Grob::pure_height (Grob *refp, int start, int end) +{ + SCM cached = get_property ("pure-Y-extent-cache"); + Interval iv = robust_scm2interval (cached, Interval ()); + if (!iv.is_empty ()) + return iv; + + SCM pure_extents = ly_lily_module_constant ("pure-Y-extents"); + SCM conversions = ly_lily_module_constant ("Y-extent-conversions"); + SCM y_extent = get_property_data (ly_symbol2scm ("Y-extent")); + + if (scm_is_pair (y_extent)) + iv = ly_scm2interval (y_extent); + else if (scm_is_pair (scm_assq (y_extent, pure_extents))) + iv = ly_scm2interval (get_property ("Y-extent")); + else + { + SCM conv = scm_assq (y_extent, conversions); + if (scm_is_pair (conv)) + { + SCM proc = scm_cdr (conv); + set_property ("pure-Y-extent-cache", ly_interval2scm (Interval (0, 0))); + SCM siv = scm_apply_3 (proc, self_scm (), scm_from_int (start), scm_from_int (end), SCM_EOL); + if (to_boolean (get_property ("pure-cacheable"))) + set_property ("pure-Y-extent-cache", siv); + else + del_property (ly_symbol2scm ("pure-Y-extent-cache")); + + iv = ly_scm2interval (siv); + } + } + 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 (_f ("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 ****************************************************************/ @@ -535,6 +639,9 @@ "staff-symbol " "stencil " "transparent " + "pure-Y-extent-cache " + "pure-Y-offset-cache " + "pure-cacheable " ); 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 3 Jun 2006 02:10:16 -0000 @@ -25,22 +25,77 @@ 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); +} + +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-columns"); + vsize ustart = (vsize) max (start, 0); + vsize uend = (end >= 0) ? end : VPOS; + if (scm_is_vector (important)) + { + vsize imp_size = scm_c_vector_length (important); + for (vsize i = ustart; i <= uend; i++) + { + if (i >= imp_size) + break; + if (to_boolean (scm_c_vector_ref (important, i))) + return false; + } + } + else /* build the important-columns-cache */ + { + extract_grob_set (me, "items-worth-living", worth); + vector important_cols; + + for (vsize i = 0; i < worth.size (); i++) + { + Item *it = dynamic_cast (worth[i]); + if (it) + { + vsize col = Paper_column::get_rank (it->get_column ()); + important_cols.resize (max (important_cols.size (), col+1)); + important_cols[col] = 1; + } + } + + SCM scm_vec = scm_c_make_vector (important_cols.size (), SCM_EOL); + for (vsize i = 0; i < important_cols.size (); i++) + scm_vector_set_x (scm_vec, scm_from_int (i), scm_from_bool (important_cols[i])); + me->set_property ("important-columns", 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 +154,7 @@ /* properties */ "items-worth-living " + "important-columns " "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 3 Jun 2006 02:10:16 -0000 @@ -8,6 +8,7 @@ #include "item.hh" +#include "axis-group-interface.hh" #include "paper-score.hh" #include "warn.hh" #include "paper-column.hh" @@ -72,6 +73,12 @@ Item *item = dynamic_cast (dolly); get_root_system (this)->typeset_grob (item); new_copies[i] = item; + + /* if we end up suiciding, our Y-axis-parent won't get the correct + Y-extent unless we add our child to it */ + Grob *p = unsmob_grob (get_object ("axis-group-parent-Y")); + if (p) + Axis_group_interface::add_element (p, dolly); } while (flip (&i) != LEFT); @@ -156,6 +163,30 @@ } } +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 3 Jun 2006 02:10:16 -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/pointer-group-interface.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/pointer-group-interface.cc,v retrieving revision 1.17 diff -u -r1.17 pointer-group-interface.cc --- lily/pointer-group-interface.cc 16 Mar 2006 14:39:46 -0000 1.17 +++ lily/pointer-group-interface.cc 3 Jun 2006 02:10:16 -0000 @@ -12,6 +12,8 @@ #include "item.hh" #include "grob-array.hh" #include "grob.hh" +#include "warn.hh" +#include "international.hh" int Pointer_group_interface::count (Grob *me, SCM sym) @@ -52,6 +54,10 @@ { Grob_array *arr = get_grob_array (me, sym); arr->add (p); + + // message ( _f("grob %s adds grob %s", me->name ().c_str (), p->name ().c_str ())); + // if (me->name() == "System") + // message ("hi"); } void 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 3 Jun 2006 02:10:16 -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->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/simple-spacer.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/simple-spacer.cc,v retrieving revision 1.98 diff -u -r1.98 simple-spacer.cc --- lily/simple-spacer.cc 9 May 2006 02:15:56 -0000 1.98 +++ lily/simple-spacer.cc 3 Jun 2006 02:10:17 -0000 @@ -305,6 +305,7 @@ Real inverse_hooke_; Real end_ideal_; Real end_inverse_hooke_; + SCM break_permission_; Interval keep_inside_line_; }; @@ -401,6 +402,7 @@ } if (!line_starter && to_boolean (col->get_property ("keep-inside-line"))) desc.keep_inside_line_ = col->extent (col, X_AXIS); + desc.break_permission_ = col->get_property ("line-break-permission"); return desc; } @@ -409,10 +411,12 @@ Real line_len, Real indent, bool ragged) { vector force; - force.resize (breaks.size () * breaks.size ()); + force.resize (breaks.size () * breaks.size (), infinity_f); vector cols; vsize b = 1; + SCM force_break = ly_symbol2scm ("force"); + cols.push_back (Column_desc ()); for (vsize i = 1; i < icols.size () - 1; i++) { 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 3 Jun 2006 02:10:17 -0000 @@ -110,7 +110,7 @@ { 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)); + //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 3 Jun 2006 02:10:17 -0000 @@ -225,6 +225,29 @@ && 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); + iv = Interval (-len, 0); + + if (!hp.is_empty ()) + iv.translate (hp[dir] * ss / 2); + + SCM scm_iv = ly_interval2scm (iv); + me->set_property ("pure-Y-extent-cache", scm_iv); + return scm_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 3 Jun 2006 02:10:17 -0000 @@ -206,6 +206,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)); + message ( _f("system from %d to %d has extent (%f,%f)", st, end, iv[UP], iv[DOWN])); + system->set_bound (LEFT, c[0]); system->set_bound (RIGHT, c.back ()); for (vsize j = 0; j < c.size (); j++) 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 3 Jun 2006 02:10:17 -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 3 Jun 2006 02:10:17 -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 3 Jun 2006 02:10:17 -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 3 Jun 2006 02:10:17 -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 3 Jun 2006 02:10:17 -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 3 Jun 2006 02:10:17 -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 3 Jun 2006 02:10:17 -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 3 Jun 2006 02:10:17 -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 3 Jun 2006 02:10:17 -0000 @@ -46,7 +46,7 @@ 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 3 Jun 2006 02:10:17 -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 3 Jun 2006 02:10:27 -0000 @@ -484,6 +484,12 @@ (apply define-internal-grob-property x)) `( + (pure-Y-offset-cache ,number? "Caches a pure-Y-offset") + (pure-Y-extent-cache ,pair? "Caches a pure Y-extent") + (pure-cacheable ,boolean? "Whether the pure Y-extent and offset are cacheable (ie. they don't depend on the start and end of the line)") + (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 +504,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-columns ,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.") 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 3 Jun 2006 02:10:27 -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)) @@ -994,6 +994,7 @@ (axes . (0 1)) (X-extent . ,ly:axis-group-interface::width) (Y-extent . ,ly:axis-group-interface::height) + (pure-cacheable . #t) (meta . ((class . Item) (interfaces . (axis-group-interface note-column-interface)))))) @@ -1314,7 +1315,7 @@ (meta . ((class . Spanner) (interfaces . (slur-interface)))))) - (SostenutoPedal + (SostenutoPedal . ( (stencil . ,ly:text-interface::print) (direction . ,RIGHT) @@ -1938,3 +1939,54 @@ (set! all-grob-descriptions (sort all-grob-descriptions alist