From 8a1a5b054688384ead32745e7f48f7f072fabeb6 Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Tue, 19 Jun 2007 10:38:23 +1000 Subject: [PATCH] use springs instead of fixed/distance pairs --- lily/include/note-spacing.hh | 3 +- lily/include/spaceable-grob.hh | 2 + lily/include/spring.hh | 21 ++++- lily/include/staff-spacing.hh | 2 +- lily/note-spacing.cc | 22 ++--- lily/paper-column.cc | 6 +- lily/spaceable-grob.cc | 35 +++----- lily/spacing-determine-loose-columns.cc | 15 +--- lily/spacing-interface.cc | 2 +- lily/spacing-spanner.cc | 110 +++++------------------- lily/spring-smob.cc | 9 -- lily/staff-spacing.cc | 8 +- 12 files changed, 80 insertions(+), 155 deletions(-) diff --git a/lily/include/note-spacing.hh b/lily/include/note-spacing.hh index dcc9b2fe5a..a14c43c8b7 100644 --- a/lily/include/note-spacing.hh +++ b/lily/include/note-spacing.hh @@ -11,13 +11,14 @@ #include "grob-interface.hh" #include "lily-proto.hh" +#include "spring.hh" class Note_spacing { public: DECLARE_GROB_INTERFACE(); - static void get_spacing (Grob *me, Item *, Real, Real, Real *, Real *); + static Spring get_spacing (Grob *me, Item *, Real, Real); static void stem_dir_correction (Grob *me, Item *next_col, Real incr, Real *, Real *); }; diff --git a/lily/include/spaceable-grob.hh b/lily/include/spaceable-grob.hh index 5625bfd61e..98d4def1bc 100644 --- a/lily/include/spaceable-grob.hh +++ b/lily/include/spaceable-grob.hh @@ -11,12 +11,14 @@ #include "lily-proto.hh" #include "grob-interface.hh" +#include "spring.hh" struct Spaceable_grob { /// set a minimum distance static void add_rod (Grob *me, Grob *to, Real distance); static void add_spring (Grob *me, Grob *to, Real dist, Real strength); + static void add_spring (Grob *me, Grob *to, Spring sp); static void get_spring (Grob *me, Grob *other, Real *dist, Real *inv_strength); DECLARE_GROB_INTERFACE(); diff --git a/lily/include/spring.hh b/lily/include/spring.hh index b49d3de1f4..d9b40cca46 100644 --- a/lily/include/spring.hh +++ b/lily/include/spring.hh @@ -1,5 +1,5 @@ /* - spring.hh -- declare Spring, Column_spring + spring.hh -- declare Spring source file of the GNU LilyPond music typesetter @@ -12,9 +12,8 @@ #include "lily-proto.hh" #include "smobs.hh" -struct Spring +class Spring { - Grob *other_; Real distance_; Real min_distance_; @@ -24,8 +23,24 @@ struct Spring DECLARE_SIMPLE_SMOBS (Spring); public: Spring (); + Spring (Real distance, Real min_distance); + + Real distance () const {return distance_;} + Real min_distance () const {return min_distance_;} + Real inverse_stretch_strength () const {return inverse_stretch_strength_;} + Real inverse_compress_strength () const {return inverse_compress_strength_;} + + void set_distance (Real); + void set_min_distance (Real); + void set_inverse_stretch_strength (Real); + void set_inverse_compress_strength (Real); + + void operator*= (Real); + Grob *other_; }; DECLARE_UNSMOB (Spring, spring); +Spring merge_springs (vector const &springs); + #endif /* SPRING_HH */ diff --git a/lily/include/staff-spacing.hh b/lily/include/staff-spacing.hh index 1553129b57..12472cc065 100644 --- a/lily/include/staff-spacing.hh +++ b/lily/include/staff-spacing.hh @@ -20,7 +20,7 @@ class Staff_spacing public: DECLARE_GROB_INTERFACE(); - static Spring get_spacing_params (Grob *); + static Spring get_spacing (Grob *); static Interval bar_y_positions (Grob *); }; diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc index a886c31a41..1274fe98c4 100644 --- a/lily/note-spacing.cc +++ b/lily/note-spacing.cc @@ -27,9 +27,9 @@ spacing? */ -void +Spring Note_spacing::get_spacing (Grob *me, Item *right_col, - Real base_space, Real increment, Real *space, Real *fixed) + Real base_space, Real increment) { vector note_columns = Spacing_interface::left_note_columns (me); Real left_head_end = 0; @@ -65,19 +65,15 @@ Note_spacing::get_spacing (Grob *me, Item *right_col, the full amount of space. */ Real min_dist = Spacing_interface::minimum_distance (me); + Real min_desired_space = max (left_head_end + (min_dist - left_head_end) / 2, + min_dist - (base_space - increment) / 2); + Real ideal = base_space - increment + min_desired_space; - *fixed = max (left_head_end + (min_dist - left_head_end) / 2, - min_dist - (base_space - increment) / 2); - - /* - We don't do complicated stuff: (base_space - increment) is the - normal amount of white, which also determines the amount of - stretch. Upon (extreme) stretching, notes with accidentals should - stretch as much as notes without accidentals. - */ - *space = (base_space - increment) + *fixed; + stem_dir_correction (me, right_col, increment, &ideal, &min_desired_space); - stem_dir_correction (me, right_col, increment, space, fixed); + Spring ret (ideal, min_dist); + ret.set_inverse_compress_strength (ideal - max (min_dist, min_desired_space)); + return ret; } diff --git a/lily/paper-column.cc b/lily/paper-column.cc index 62f68b105e..e3f462894a 100644 --- a/lily/paper-column.cc +++ b/lily/paper-column.cc @@ -184,7 +184,7 @@ Paper_column::print (SCM p) vector pts; pts.push_back (Offset (0, y)); - Offset p2 (sp->distance_, y); + Offset p2 (sp->distance (), y); pts.push_back (p2); Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts); @@ -192,9 +192,9 @@ Paper_column::print (SCM p) SCM distance_stc = Text_interface::interpret_markup (me->layout ()->self_scm (), small_letters, - ly_string2scm (String_convert::form_string ("%5.2lf", sp->distance_))); + ly_string2scm (String_convert::form_string ("%5.2lf", sp->distance ()))); - id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (sp->distance_/3, y+1))); + id_stencil.add_stencil (unsmob_stencil (distance_stc)->translated (Offset (sp->distance ()/3, y+1))); id_stencil.add_stencil (head.translated (p2)); id_stencil = id_stencil.in_color (0,0,1); l.add_stencil (id_stencil); diff --git a/lily/spaceable-grob.cc b/lily/spaceable-grob.cc index 77793e5492..464e0d3b1c 100644 --- a/lily/spaceable-grob.cc +++ b/lily/spaceable-grob.cc @@ -59,22 +59,6 @@ void Spaceable_grob::add_spring (Grob *me, Grob *other, Real distance, Real inverse_strength) { - if (distance < 0.0 || inverse_strength < 0.0) - { - programming_error ("adding reverse spring, setting to unit"); - distance = 1.0; - inverse_strength = 1.0; - } - - if (isinf (distance) || isnan (distance) - || isnan (inverse_strength)) - { - /* strength == INF is possible. It means fixed distance. */ - programming_error ("insane distance found"); - distance = 1.0; - inverse_strength = 1.0; - } - #ifndef NDEBUG SCM mins = me->get_object ("ideal-distances"); for (SCM s = mins; scm_is_pair (s); s = scm_cdr (s)) @@ -89,9 +73,9 @@ Spaceable_grob::add_spring (Grob *me, Grob *other, #endif Spring spring; - spring.inverse_stretch_strength_ = inverse_strength; - spring.inverse_compress_strength_ = inverse_strength; - spring.distance_ = distance; + spring.set_inverse_stretch_strength (inverse_strength); + spring.set_inverse_compress_strength (inverse_strength); + spring.set_distance (distance); spring.other_ = other; SCM ideal = me->get_object ("ideal-distances"); @@ -99,6 +83,15 @@ Spaceable_grob::add_spring (Grob *me, Grob *other, me->set_object ("ideal-distances", ideal); } +void +Spaceable_grob::add_spring (Grob *me, Grob *other, Spring sp) +{ + SCM ideal = me->get_object ("ideal-distances"); + sp.other_ = other; + ideal = scm_cons (sp.smobbed_copy (), ideal); + me->set_object ("ideal-distances", ideal); +} + void Spaceable_grob::get_spring (Grob *this_col, Grob *next_col, Real *dist, Real *inv_strength) { @@ -118,8 +111,8 @@ Spaceable_grob::get_spring (Grob *this_col, Grob *next_col, Real *dist, Real *in programming_error (_f ("No spring between column %d and next one", Paper_column::get_rank (this_col))); - *dist = (spring) ? spring->distance_ : 5.0; - *inv_strength = (spring) ? spring->inverse_stretch_strength_ : 1.0; + *dist = (spring) ? spring->distance () : 5.0; + *inv_strength = (spring) ? spring->inverse_stretch_strength () : 1.0; } diff --git a/lily/spacing-determine-loose-columns.cc b/lily/spacing-determine-loose-columns.cc index 7274ef1363..ef5e8c71de 100644 --- a/lily/spacing-determine-loose-columns.cc +++ b/lily/spacing-determine-loose-columns.cc @@ -154,23 +154,16 @@ Spacing_spanner::set_distances_for_loose_col (Grob *me, Grob *c, The note spacing should be taken from the musical columns. */ - Real space = 0.0; - Real fixed = 0.0; - Real base = note_spacing (me, lc, rc, options); - Note_spacing::get_spacing (sp, rc, base, options->increment_, - &space, &fixed); + Spring spring = Note_spacing::get_spacing (sp, rc, base, options->increment_); - space -= options->increment_; - - dists[d] = max (dists[d], space); + dists[d] = max (dists[d], spring.distance () - options->increment_); } else if (Staff_spacing::has_interface (sp)) { - Spring spring = Staff_spacing::get_spacing_params (sp); - Real fixed = spring.distance_ - spring.inverse_compress_strength_; + Spring spring = Staff_spacing::get_spacing (sp); - dists[d] = max (dists[d], fixed); + dists[d] = max (dists[d], spring.min_distance ()); } else programming_error ("Subversive spacing wish"); diff --git a/lily/spacing-interface.cc b/lily/spacing-interface.cc index 82f6fccdb7..33a4e14d39 100644 --- a/lily/spacing-interface.cc +++ b/lily/spacing-interface.cc @@ -66,7 +66,7 @@ Spacing_interface::minimum_distance (Grob *me) } while (flip (&d) != LEFT); - return skylines[LEFT].distance (skylines[RIGHT]); + return max (0.0, skylines[LEFT].distance (skylines[RIGHT])); } /* diff --git a/lily/spacing-spanner.cc b/lily/spacing-spanner.cc index 69b0de980b..d158883dad 100644 --- a/lily/spacing-spanner.cc +++ b/lily/spacing-spanner.cc @@ -237,37 +237,15 @@ Spacing_spanner::musical_column_spacing (Grob *me, Spacing_options const *options) { Real base_note_space = note_spacing (me, left_col, right_col, options); - - Real max_fixed = 0; - Real max_space = 0; - Real compound_note_space = 0.0; - Real compound_fixed_note_space = 0.0; + Spring spring; if (options->stretch_uniformly_) - { - compound_note_space = base_note_space; - - if (!Paper_column::is_musical (right_col)) - { - /* - Crude fix for notes that lead up to barlines and time sigs. - */ - Interval lext = right_col->extent (right_col, X_AXIS); - if (!lext.is_empty ()) - compound_note_space += -lext[LEFT]; - } - } + spring = Spring (base_note_space, 0.0); else { - int wish_count = 0; - + vector springs; extract_grob_set (left_col, "right-neighbors", neighbors); - /* - We adjust the space following a note only if the next note - happens after the current note (this is set in the grob - property SPACING-SEQUENCE. - */ for (vsize i = 0; i < neighbors.size (); i++) { Grob *wish = neighbors[i]; @@ -281,32 +259,10 @@ Spacing_spanner::musical_column_spacing (Grob *me, This is probably a waste of time in the case of polyphonic music. */ if (Note_spacing::has_interface (wish)) - { - Real space = 0.0; - Real fixed = 0.0; - - Note_spacing::get_spacing (wish, right_col, base_note_space, options->increment_, &space, &fixed); - - - max_space = max (max_space, space); - max_fixed = max (max_fixed, fixed); - - compound_note_space += space; - compound_fixed_note_space += fixed; - wish_count++; - } - } - - if (Paper_column::when_mom (right_col).grace_part_ - && !Paper_column::when_mom (left_col).grace_part_) - { - /* - Ugh. 0.8 is arbitrary. - */ - compound_note_space *= 0.8; + springs.push_back (Note_spacing::get_spacing (wish, right_col, base_note_space, options->increment_)); } - if (compound_note_space < 0 || wish_count == 0) + if (springs.empty ()) { if (!Paper_column::is_musical (right_col)) @@ -317,9 +273,8 @@ Spacing_spanner::musical_column_spacing (Grob *me, spacing, because the width of s^"text" output is also taken into account here. */ - compound_fixed_note_space = options->increment_; - compound_note_space = max (base_note_space, - options->increment_); + spring = Spring (max (base_note_space, options->increment_), + options->increment_); } else { @@ -327,44 +282,30 @@ Spacing_spanner::musical_column_spacing (Grob *me, Fixed should be 0.0. If there are no spacing wishes, we're likely dealing with polyphonic spacing of hemiolas. - We used to have compound_fixed_note_space = options->increment_ + We used to have min_distance_ = options->increment_ but this can lead to numeric instability problems when we do - inverse_strength = (compound_note_space - compound_fixed_note_space) + inverse_strength = (distance_ - min_distance_) */ - - compound_note_space = base_note_space; - compound_fixed_note_space = 0.0; + spring = Spring (base_note_space, 0.0); } } - else if (to_boolean (me->get_property ("average-spacing-wishes"))) - { - compound_note_space /= wish_count; - compound_fixed_note_space /= wish_count; - } else - { - compound_fixed_note_space = max_fixed; - compound_note_space = max_space; - } + spring = merge_springs (springs); + } + if (Paper_column::when_mom (right_col).grace_part_ + && !Paper_column::when_mom (left_col).grace_part_) + { /* - Whatever we do, the fixed space is smaller than the real - space. - - TODO: this criterion is discontinuous in the derivative. - Maybe it should be continuous? + Ugh. 0.8 is arbitrary. */ - compound_fixed_note_space = min (compound_fixed_note_space, - compound_note_space); + spring *= 0.8; } - Real inverse_strength = 1.0; - Real distance = 1.0; - /* TODO: make sure that the space doesn't exceed the right margin. */ @@ -379,16 +320,11 @@ Spacing_spanner::musical_column_spacing (Grob *me, pack as much bars of music as possible into a line, but the line will then be stretched to fill the whole linewidth. */ - inverse_strength = 1.0; - distance = compound_fixed_note_space; - } - else - { - inverse_strength = (compound_note_space - compound_fixed_note_space); - distance = compound_note_space; + spring.set_distance (spring.min_distance ()); + spring.set_inverse_stretch_strength (1.0); } - Spaceable_grob::add_spring (left_col, right_col, distance, inverse_strength); + Spaceable_grob::add_spring (left_col, right_col, spring); } /* @@ -460,9 +396,9 @@ Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r, */ assert (spacing_grob->get_column () == l); - Spring sp = Staff_spacing::get_spacing_params (spacing_grob); - Real space = sp.distance_; - Real fixed = sp.distance_ - sp.inverse_compress_strength_; + Spring sp = Staff_spacing::get_spacing (spacing_grob); + Real space = sp.distance (); + Real fixed = sp.min_distance (); if (Paper_column::when_mom (r).grace_part_) { diff --git a/lily/spring-smob.cc b/lily/spring-smob.cc index a466fb44bb..5639a1cd07 100644 --- a/lily/spring-smob.cc +++ b/lily/spring-smob.cc @@ -10,15 +10,6 @@ #include "warn.hh" #include "ly-smobs.icc" -Spring::Spring () -{ - distance_ = 1.0; - min_distance_ = 1.0; - inverse_stretch_strength_ = 1.0; - inverse_compress_strength_ = 1.0; - other_ = 0; -} - IMPLEMENT_SIMPLE_SMOBS (Spring); SCM diff --git a/lily/staff-spacing.cc b/lily/staff-spacing.cc index 08ef578399..b9fd874b9e 100644 --- a/lily/staff-spacing.cc +++ b/lily/staff-spacing.cc @@ -107,7 +107,7 @@ Staff_spacing::next_notes_correction (Grob *me, will be the distance between columns if there is a compression force of 1.0 applied to the line. */ Spring -Staff_spacing::get_spacing_params (Grob *me) +Staff_spacing::get_spacing (Grob *me) { Grob *separation_item = 0; Item *me_item = dynamic_cast (me); @@ -199,10 +199,8 @@ Staff_spacing::get_spacing_params (Grob *me) fixed += correction; ideal += correction; - Spring ret; - ret.min_distance_ = max (min_dist, fixed); - ret.distance_ = ideal; - ret.inverse_stretch_strength_ = ret.inverse_compress_strength_ = ideal - fixed; + Spring ret (ideal, min_dist); + ret.set_inverse_stretch_strength (ideal - fixed); return ret; } -- 2.39.5