X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fspacing-spanner.cc;h=2f2724689d6e99cf1493fd3259694d2eec34547b;hb=0b544cfb7332615ef809b71b57ab656741311ae1;hp=75dc166925eb5a2e6ab1d9057688eb277548c4d8;hpb=4a401ca1c60f428daa242dbdd102fdb3f327ebfb;p=lilypond.git diff --git a/lily/spacing-spanner.cc b/lily/spacing-spanner.cc index 75dc166925..2f2724689d 100644 --- a/lily/spacing-spanner.cc +++ b/lily/spacing-spanner.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 1999--2011 Han-Wen Nienhuys + Copyright (C) 1999--2014 Han-Wen Nienhuys LilyPond is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -223,78 +223,66 @@ Spacing_spanner::generate_pair_spacing (Grob *me, static void set_column_rods (vector const &cols, Real padding) { - /* distances[i] will be the minimum distance between column i and column i+1 */ - vector distances; + /* distances[i] will be the distance betwen cols[i-1] and cols[i], and + overhangs[j] the amount by which cols[0 thru j] extend beyond cols[j] + when each column is placed as far to the left as possible. */ + vector distances (cols.size ()); + vector overhangs (cols.size ()); - for (vsize i = 1; i < cols.size (); i++) + for (vsize i = 0; i < cols.size (); i++) { - assert (distances.size () == i - 1); - Item *r = dynamic_cast (cols[i]); Item *rb = r->find_prebroken_piece (LEFT); if (Separation_item::is_empty (r) && (!rb || Separation_item::is_empty (rb))) - { - distances.push_back (0); - continue; - } + continue; Skyline_pair *skys = Skyline_pair::unsmob (r->get_property ("horizontal-skylines")); - Real right_stickout = skys ? (*skys)[LEFT].max_height () : 0.0; + overhangs[i] = skys ? (*skys)[RIGHT].max_height () : 0.0; - /* min rather than max because right-stickout will be negative if the right-hand column + if (0 == i) continue; + + /* min rather than max because stickout will be negative if the right-hand column sticks out a lot to the left */ - right_stickout = min (right_stickout, - Separation_item::conditional_skyline (r, cols[i - 1]).max_height ()); + Real stickout = min (skys ? (*skys)[LEFT].max_height () : 0.0, + Separation_item::conditional_skyline (r, cols[i - 1]).max_height ()); - Drul_array r_cols (r, rb); - Drul_array cur_dist (0.0, 0.0); + Real prev_distances = 0.0; /* This is an inner loop and hence it is potentially quadratic. However, we only continue as long as there is a rod to insert. Therefore, this loop will usually only execute a constant number of times per iteration of the outer loop. */ for (vsize j = i; j--;) { + if (overhangs[j] + padding <= prev_distances + distances[i] + stickout) + break; // cols[0 thru j] cannot reach cols[i] + Item *l = dynamic_cast (cols[j]); Item *lb = l->find_prebroken_piece (RIGHT); - Skyline_pair *skys = Skyline_pair::unsmob (l->get_property ("horizontal-skylines")); - Real left_stickout = skys ? (*skys)[RIGHT].max_height () : 0.0; - bool done = true; - - Direction d = LEFT; - do - { - if (j < i - 1) - cur_dist[d] += distances[j]; - Item *r_col = r_cols[d]; - bool touches = right_stickout - left_stickout + cur_dist[d] < 0.0; - Real dist = 0.0; + Real dist = Separation_item::set_distance (l, r, padding); + distances[i] = max (distances[i], dist - prev_distances); - /* we set a distance for the line-starter column even if its non-broken counterpart - doesn't touch the right column. */ - if (lb) - Separation_item::set_distance (lb, r_col, padding); - - if (touches || j == i - 1) - dist = Separation_item::set_distance (l, r_col, padding); - - if (j == i - 1 && d == LEFT) - distances.push_back (dist); - - if (j == i - 1) - cur_dist[d] = distances[j]; - - cur_dist[d] = max (cur_dist[d], dist); - done = done && !touches; + if (lb) + { + dist = Separation_item::set_distance (lb, r, padding); + // The left-broken version might reach more columns to the + // right than the unbroken version, by extending farther and/or + // nesting more closely; + if (j == i - 1) // check this, the first time we see each lb. + overhangs[j] = max (overhangs[j], + lb->extent (lb, X_AXIS)[RIGHT] + + distances[i] - dist); } - while (flip (&d) != LEFT && rb); + if (rb) + Separation_item::set_distance (l, rb, padding); + if (lb && rb) + Separation_item::set_distance (lb, rb, padding); - /* we need the empty check for gregorian notation, where there are a lot of - extraneous paper-columns that we need to skip over */ - if (done && !Separation_item::is_empty (l)) - break; + prev_distances += distances[j]; } + overhangs[i] = max (overhangs[i], + overhangs[i - 1] - distances[i]); } } @@ -327,11 +315,13 @@ Spacing_spanner::musical_column_spacing (Grob *me, Item *right_col, Spacing_options const *options) { - Real base_note_space = note_spacing (me, left_col, right_col, options); - Spring spring; + Spring spring = note_spacing (me, left_col, right_col, options); if (options->stretch_uniformly_) - spring = Spring (base_note_space, 0.0); + { + spring.set_min_distance (0.0); + spring.set_default_strength (); + } else { vector springs; @@ -371,32 +361,20 @@ Spacing_spanner::musical_column_spacing (Grob *me, grace_opts.init_from_grob (gsp); inc = grace_opts.increment_; } - springs.push_back (Note_spacing::get_spacing (wish, right_col, base_note_space, inc)); + springs.push_back (Note_spacing::get_spacing (wish, right_col, spring, inc)); } } if (springs.empty ()) { - - if (!Paper_column::is_musical (right_col)) - { - /* - There used to be code that examined left_col->extent - (X_AXIS), but this is resulted in unexpected wide - spacing, because the width of s^"text" output is also - taken into account here. - */ - spring = Spring (max (base_note_space, options->increment_), - options->increment_); - } - else + if (Paper_column::is_musical (right_col)) { /* Min distance should be 0.0. If there are no spacing wishes, we're probably dealing with polyphonic spacing of hemiolas. */ - spring = Spring (base_note_space, 0.0); + spring.set_min_distance (0.0); } } else @@ -495,6 +473,12 @@ Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r, vector springs; Spring spring; + Real full_measure_space = 0.0; + if (Paper_column::is_musical (r) + && l->break_status_dir () == CENTER + && fills_measure (me, l, r)) + full_measure_space = robust_scm2double (l->get_property ("full-measure-extra-space"), 1.0); + Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l); if (dt == Moment (0, 0)) @@ -514,7 +498,8 @@ Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r, */ assert (spacing_grob->get_column () == l); - springs.push_back (Staff_spacing::get_spacing (spacing_grob, r)); + springs.push_back (Staff_spacing::get_spacing (spacing_grob, r, + full_measure_space)); } } @@ -533,15 +518,6 @@ Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r, spring *= 0.8; } - if (Paper_column::is_musical (r) - && l->break_status_dir () == CENTER - && fills_measure (me, l, r)) - { - Real full_measure_extra_space = robust_scm2double (l->get_property ("full-measure-extra-space"), 1.0); - spring.set_distance (spring.distance () + full_measure_extra_space); - spring.set_default_compress_strength (); - } - if (options->stretch_uniformly_ && l->break_status_dir () != RIGHT) { spring.set_min_distance (0.0);