2 spacing-spanner.cc -- implement Spacing_spanner
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #include "spacing-spanner.hh"
14 #include "spacing-options.hh"
15 #include "international.hh"
18 #include "note-spacing.hh"
19 #include "output-def.hh"
20 #include "paper-column.hh"
21 #include "paper-score.hh"
22 #include "pointer-group-interface.hh"
23 #include "separation-item.hh"
24 #include "skyline-pair.hh"
25 #include "spaceable-grob.hh"
26 #include "spacing-interface.hh"
27 #include "staff-spacing.hh"
32 Spacing_spanner::get_columns (Grob *me_grob)
34 Spanner *me = dynamic_cast<Spanner*> (me_grob);
35 vector<Grob*> all (get_root_system (me)->used_columns ());
36 vsize start = binary_search (all, (Grob*)me->get_bound (LEFT),
37 &Paper_column::less_than);
38 vsize end = binary_search (all, (Grob*) me->get_bound (RIGHT),
39 &Paper_column::less_than);
41 all = vector<Grob*>::vector<Grob*> (all.begin () + start,
42 all.begin () + end + 1);
46 MAKE_SCHEME_CALLBACK (Spacing_spanner, set_springs, 1);
48 Spacing_spanner::set_springs (SCM smob)
50 Spanner *me = unsmob_spanner (smob);
53 can't use get_system () ? --hwn.
55 Spacing_options options;
56 options.init_from_grob (me);
57 vector<Grob*> cols = Spacing_spanner::get_columns (me);
58 set_explicit_neighbor_columns (cols);
60 prune_loose_columns (me, &cols, &options);
61 set_implicit_neighbor_columns (cols);
62 generate_springs (me, cols, &options);
64 return SCM_UNSPECIFIED;
68 We want the shortest note that is also "common" in the piece, so we
69 find the shortest in each measure, and take the most frequently
72 This probably gives weird effects with modern music, where every
73 note has a different duration, but hey, don't write that kind of
77 MAKE_SCHEME_CALLBACK (Spacing_spanner, calc_common_shortest_duration, 1);
79 Spacing_spanner::calc_common_shortest_duration (SCM grob)
81 Spanner *me = unsmob_spanner (grob);
83 vector<Grob*> cols (get_columns (me));
88 vector<Rational> durations;
91 Rational shortest_in_measure;
92 shortest_in_measure.set_infinite (1);
94 for (vsize i = 0; i < cols.size (); i++)
96 if (Paper_column::is_musical (cols[i]))
98 Moment *when = unsmob_moment (cols[i]->get_property ("when"));
101 ignore grace notes for shortest notes.
103 if (when && when->grace_part_)
106 SCM st = cols[i]->get_property ("shortest-starter-duration");
107 Moment this_shortest = *unsmob_moment (st);
108 assert (this_shortest.to_bool ());
109 shortest_in_measure = min (shortest_in_measure, this_shortest.main_part_);
111 else if (!shortest_in_measure.is_infinity ()
112 && Paper_column::is_breakable (cols[i]))
115 for (; j < durations.size (); j++)
117 if (durations[j] > shortest_in_measure)
119 counts.insert (counts.begin () + j, 1);
120 durations.insert (durations.begin () + j, shortest_in_measure);
123 else if (durations[j] == shortest_in_measure)
130 if (durations.size () == j)
132 durations.push_back (shortest_in_measure);
133 counts.push_back (1);
136 shortest_in_measure.set_infinite (1);
140 vsize max_idx = VPOS;
142 for (vsize i = durations.size (); i--;)
144 if (counts[i] >= max_count)
147 max_count = counts[i];
151 SCM bsd = me->get_property ("base-shortest-duration");
152 Rational d = Rational (1, 8);
153 if (Moment *m = unsmob_moment (bsd))
157 d = min (d, durations[max_idx]);
159 return Moment (d).smobbed_copy ();
163 Spacing_spanner::generate_pair_spacing (Grob *me,
164 Paper_column *left_col, Paper_column *right_col,
165 Paper_column *after_right_col,
166 Spacing_options const *options)
168 if (Paper_column::is_musical (left_col))
170 if (!Paper_column::is_musical (right_col)
171 && options->float_nonmusical_columns_
173 && Paper_column::is_musical (after_right_col))
176 TODO: should generate rods to prevent collisions.
178 musical_column_spacing (me, left_col, after_right_col, options);
179 right_col->set_object ("between-cols", scm_cons (left_col->self_scm (),
180 after_right_col->self_scm ()));
183 musical_column_spacing (me, left_col, right_col, options);
185 if (Item *rb = right_col->find_prebroken_piece (LEFT))
186 musical_column_spacing (me, left_col, rb, options);
191 The case that the right part is broken as well is rather
192 rare, but it is possible, eg. with a single empty measure,
193 or if one staff finishes a tad earlier than the rest.
195 Item *lb = left_col->find_prebroken_piece (RIGHT);
196 Item *rb = right_col->find_prebroken_piece (LEFT);
198 if (left_col && right_col)
199 breakable_column_spacing (me, left_col, right_col, options);
202 breakable_column_spacing (me, lb, right_col, options);
205 breakable_column_spacing (me, left_col, rb, options);
208 breakable_column_spacing (me, lb, rb, options);
213 set_column_rods (vector<Grob*> const &cols, Real padding)
215 /* distances[i] will be the minimum distance between column i and column i+1 */
216 vector<Real> distances;
218 for (vsize i = 1; i < cols.size (); i++)
220 assert (distances.size () == i-1);
222 Item *r = dynamic_cast<Item*> (cols[i]);
223 Item *rb = r->find_prebroken_piece (LEFT);
225 if (Separation_item::is_empty (r) && (!rb || Separation_item::is_empty (rb)))
227 distances.push_back (0);
231 Skyline_pair *skys = Skyline_pair::unsmob (r->get_property ("horizontal-skylines"));
232 Real right_stickout = skys ? (*skys)[LEFT].max_height () : 0.0;
234 /* min rather than max because right-stickout will be negative if the right-hand column
235 sticks out a lot to the left */
236 right_stickout = min (right_stickout,
237 Separation_item::conditional_skyline (r, cols[i-1]).max_height ());
239 Drul_array<Item*> r_cols (r, rb);
240 Drul_array<Real> cur_dist (0.0, 0.0);
242 /* This is an inner loop and hence it is potentially quadratic. However, we only continue
243 as long as there is a rod to insert. Therefore, this loop will usually only execute
244 a constant number of times per iteration of the outer loop. */
245 for (vsize j = i; j--;)
247 Item *l = dynamic_cast<Item*> (cols[j]);
248 Item *lb = l->find_prebroken_piece (RIGHT);
249 Skyline_pair *skys = Skyline_pair::unsmob (l->get_property ("horizontal-skylines"));
250 Real left_stickout = skys ? (*skys)[RIGHT].max_height () : 0.0;
257 cur_dist[d] += distances[j];
259 Item *r_col = r_cols[d];
260 bool touches = right_stickout - left_stickout + cur_dist[d] < 0.0;
263 /* we set a distance for the line-starter column even if it's non-broken counterpart
264 doesn't touch the right column. */
266 Separation_item::set_distance (lb, r_col, padding);
268 if (touches || j == i-1)
269 dist = Separation_item::set_distance (l, r_col, padding);
271 if (j == i-1 && d == LEFT)
272 distances.push_back (dist);
275 cur_dist[d] = distances[j];
277 done = done && !touches;
279 while (flip (&d) != LEFT && rb);
281 /* we need the empty check for gregorian notation, where there are a lot of
282 extraneous paper-columns that we need to skip over */
283 if (done && !Separation_item::is_empty (l))
291 Spacing_spanner::generate_springs (Grob *me,
292 vector<Grob*> const &cols,
293 Spacing_options const *options)
295 Paper_column *prev = dynamic_cast<Paper_column*> (cols[0]);
296 for (vsize i = 1; i < cols.size (); i++)
298 Paper_column *col = dynamic_cast<Paper_column *> (cols[i]);
299 Paper_column *next = (i + 1 < cols.size ()) ? dynamic_cast<Paper_column *> (cols[i+1]) : 0;
301 generate_pair_spacing (me, prev, col, next, options);
306 set_column_rods (cols, 0.1); // FIXME: padding
310 Generate the space between two musical columns LEFT_COL and RIGHT_COL.
313 Spacing_spanner::musical_column_spacing (Grob *me,
316 Spacing_options const *options)
318 Real base_note_space = note_spacing (me, left_col, right_col, options);
321 if (options->stretch_uniformly_)
322 spring = Spring (base_note_space, 0.0);
325 vector<Spring> springs;
326 extract_grob_set (left_col, "right-neighbors", neighbors);
328 for (vsize i = 0; i < neighbors.size (); i++)
330 Grob *wish = neighbors[i];
332 Item *wish_rcol = Spacing_interface::right_column (wish);
333 if (Spacing_interface::left_column (wish) != left_col
334 || (wish_rcol != right_col && wish_rcol != right_col->original ()))
338 This is probably a waste of time in the case of polyphonic
340 if (Note_spacing::has_interface (wish))
342 Real inc = options->increment_;
343 Grob *gsp = unsmob_grob (left_col->get_object ("grace-spacing"));
344 if (gsp && Paper_column::when_mom (left_col).grace_part_)
346 Spacing_options grace_opts;
347 grace_opts.init_from_grob (gsp);
348 inc = grace_opts.increment_;
350 springs.push_back (Note_spacing::get_spacing (wish, right_col, base_note_space, inc));
354 if (springs.empty ())
357 if (!Paper_column::is_musical (right_col))
360 There used to be code that examined left_col->extent
361 (X_AXIS), but this is resulted in unexpected wide
362 spacing, because the width of s^"text" output is also
363 taken into account here.
365 spring = Spring (max (base_note_space, options->increment_),
366 options->increment_);
371 Min distance should be 0.0. If there are no spacing
372 wishes, we're probably dealing with polyphonic spacing
375 spring = Spring (base_note_space, 0.0);
379 spring = merge_springs (springs);
382 if (Paper_column::when_mom (right_col).grace_part_
383 && !Paper_column::when_mom (left_col).grace_part_)
386 Ugh. 0.8 is arbitrary.
392 TODO: make sure that the space doesn't exceed the right margin.
394 if (options->packed_)
397 In packed mode, pack notes as tight as possible. This makes
398 sense mostly in combination with ragged-right mode: the notes
399 are then printed at minimum distance. This is mostly useful
400 for ancient notation, but may also be useful for some flavours
401 of contemporary music. If not in ragged-right mode, lily will
402 pack as many bars of music as possible into a line, but the
403 line will then be stretched to fill the whole linewidth.
405 Note that we don't actually pack things as tightly as possible:
406 we don't allow the next column to begin before this one ends.
408 /* FIXME: the else clause below is the "right" thing to do,
409 but we can't do it because of all the empty columns that the
410 ligature-engravers leave lying around. In that case, the extent of
411 the column is incorrect because it includes note-heads that aren't
412 there. We get around this by only including the column extent if
413 the left-hand column is "genuine". This is a dirty hack and it
414 should be fixed in the ligature-engravers. --jneem
416 if (Paper_column::is_extraneous_column_from_ligature (left_col))
417 spring.set_distance (spring.min_distance ());
419 spring.set_distance (max (left_col->extent (left_col, X_AXIS)[RIGHT],
420 spring.min_distance ()));
422 spring.set_inverse_stretch_strength (1.0);
425 Spaceable_grob::add_spring (left_col, right_col, spring);
429 Check if COL fills the whole measure.
432 Spacing_spanner::fills_measure (Grob *me, Item *left, Item *col)
434 System *sys = get_root_system (me);
435 Item *next = sys->column (col->get_column ()->get_rank () + 1);
439 if (Paper_column::is_musical (next)
440 || Paper_column::is_musical (left)
441 || !Paper_column::is_musical (col)
442 || !Paper_column::is_used (next))
446 Paper_column::when_mom (next) - Paper_column::when_mom (col);
448 Moment *len = unsmob_moment (left->get_property ("measure-length"));
453 Don't check for exact measure length, since ending measures are
454 often shortened due to pickups.
456 if (dt.main_part_ > len->main_part_ / Rational (2)
457 && (next->is_broken ()
458 || next->break_status_dir ()))
465 Read hints from L and generate springs.
468 Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r,
469 Spacing_options const *options)
471 vector<Spring> springs;
474 Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l);
476 if (dt == Moment (0, 0))
478 extract_grob_set (l, "spacing-wishes", wishes);
480 for (vsize i = 0; i < wishes.size (); i++)
482 Item *spacing_grob = dynamic_cast<Item *> (wishes[i]);
484 if (!spacing_grob || !Staff_spacing::has_interface (spacing_grob))
488 column for the left one settings should be ok due automatic
491 assert (spacing_grob->get_column () == l);
493 springs.push_back (Staff_spacing::get_spacing (spacing_grob, r));
497 if (springs.empty ())
498 spring = standard_breakable_column_spacing (me, l, r, options);
500 spring = merge_springs (springs);
502 if (Paper_column::when_mom (r).grace_part_)
505 Correct for grace notes.
507 Ugh. The 0.8 is arbitrary.
512 if (Paper_column::is_musical (r)
513 && l->break_status_dir () == CENTER
514 && fills_measure (me, l, r))
516 Real full_measure_extra_space = robust_scm2double (l->get_property ("full-measure-extra-space"), 1.0);
517 spring.set_distance (spring.distance () + full_measure_extra_space);
518 spring.set_default_strength ();
521 if (options->stretch_uniformly_ && l->break_status_dir () != RIGHT)
523 spring.set_min_distance (0.0);
524 spring.set_default_strength ();
527 Spaceable_grob::add_spring (l, r, spring);
530 ADD_INTERFACE (Spacing_spanner,
531 "The space taken by a note is dependent on its duration."
532 " Doubling a duration adds @code{spacing-increment} to the"
533 " space. The most common shortest note gets"
534 " @code{shortest-duration-space}. Notes that are even shorter"
535 " are spaced proportonial to their duration.\n"
537 "Typically, the increment is the width of a black note head."
538 " In a piece with lots of 8th notes, and some 16th notes, the"
539 " eighth note gets a 2@tie{}note heads width (i.e., the space"
540 " following a note is a 1@tie{}note head width). A 16th note"
541 " is followed by 0.5 note head width. The quarter note is"
542 " followed by 3@tie{}NHW, the half by 4@tie{}NHW, etc.",
545 "average-spacing-wishes "
546 "base-shortest-duration "
547 "common-shortest-duration "
549 "shortest-duration-space "
551 "strict-grace-spacing "
552 "strict-note-spacing "
553 "uniform-stretching "