2 spacing-spanner.cc -- implement Spacing_spanner
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2007 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 "spaceable-grob.hh"
25 #include "spacing-interface.hh"
26 #include "staff-spacing.hh"
31 Spacing_spanner::get_columns (Grob *me_grob)
33 Spanner *me = dynamic_cast<Spanner*> (me_grob);
34 vector<Grob*> all (get_root_system (me)->used_columns ());
35 vsize start = binary_search (all, (Grob*)me->get_bound (LEFT),
36 &Paper_column::less_than);
37 vsize end = binary_search (all, (Grob*) me->get_bound (RIGHT),
38 &Paper_column::less_than);
40 all = vector<Grob*>::vector<Grob*> (all.begin () + start,
41 all.begin () + end + 1);
45 MAKE_SCHEME_CALLBACK (Spacing_spanner, set_springs, 1);
47 Spacing_spanner::set_springs (SCM smob)
49 Spanner *me = unsmob_spanner (smob);
52 can't use get_system () ? --hwn.
54 Spacing_options options;
55 options.init_from_grob (me);
56 vector<Grob*> cols = Spacing_spanner::get_columns (me);
57 set_explicit_neighbor_columns (cols);
59 prune_loose_columns (me, &cols, &options);
60 set_implicit_neighbor_columns (cols);
61 generate_springs (me, cols, &options);
63 return SCM_UNSPECIFIED;
67 We want the shortest note that is also "common" in the piece, so we
68 find the shortest in each measure, and take the most frequently
71 This probably gives weird effects with modern music, where every
72 note has a different duration, but hey, don't write that kind of
76 MAKE_SCHEME_CALLBACK (Spacing_spanner, calc_common_shortest_duration, 1);
78 Spacing_spanner::calc_common_shortest_duration (SCM grob)
80 Spanner *me = unsmob_spanner (grob);
82 vector<Grob*> cols (get_columns (me));
87 vector<Rational> durations;
90 Rational shortest_in_measure;
91 shortest_in_measure.set_infinite (1);
93 for (vsize i = 0; i < cols.size (); i++)
95 if (Paper_column::is_musical (cols[i]))
97 Moment *when = unsmob_moment (cols[i]->get_property ("when"));
100 ignore grace notes for shortest notes.
102 if (when && when->grace_part_)
105 SCM st = cols[i]->get_property ("shortest-starter-duration");
106 Moment this_shortest = *unsmob_moment (st);
107 assert (this_shortest.to_bool ());
108 shortest_in_measure = min (shortest_in_measure, this_shortest.main_part_);
110 else if (!shortest_in_measure.is_infinity ()
111 && Paper_column::is_breakable (cols[i]))
114 for (; j < durations.size (); j++)
116 if (durations[j] > shortest_in_measure)
118 counts.insert (counts.begin () + j, 1);
119 durations.insert (durations.begin () + j, shortest_in_measure);
122 else if (durations[j] == shortest_in_measure)
129 if (durations.size () == j)
131 durations.push_back (shortest_in_measure);
132 counts.push_back (1);
135 shortest_in_measure.set_infinite (1);
141 for (vsize i = durations.size (); i--;)
143 if (counts[i] >= max_count)
146 max_count = counts[i];
150 SCM bsd = me->get_property ("base-shortest-duration");
151 Rational d = Rational (1, 8);
152 if (Moment *m = unsmob_moment (bsd))
156 d = min (d, durations[max_idx]);
158 return Moment (d).smobbed_copy ();
162 Spacing_spanner::generate_pair_spacing (Grob *me,
163 Paper_column *left_col, Paper_column *right_col,
164 Paper_column *after_right_col,
165 Spacing_options const *options)
167 if (Paper_column::is_musical (left_col))
169 if (!Paper_column::is_musical (right_col)
170 && options->float_nonmusical_columns_
172 && Paper_column::is_musical (after_right_col))
175 TODO: should generate rods to prevent collisions.
177 musical_column_spacing (me, left_col, after_right_col, options);
178 right_col->set_object ("between-cols", scm_cons (left_col->self_scm (),
179 after_right_col->self_scm ()));
182 musical_column_spacing (me, left_col, right_col, options);
184 if (Item *rb = right_col->find_prebroken_piece (LEFT))
185 musical_column_spacing (me, left_col, rb, options);
190 The case that the right part is broken as well is rather
191 rare, but it is possible, eg. with a single empty measure,
192 or if one staff finishes a tad earlier than the rest.
194 Item *lb = left_col->find_prebroken_piece (RIGHT);
195 Item *rb = right_col->find_prebroken_piece (LEFT);
197 if (left_col && right_col)
198 breakable_column_spacing (me, left_col, right_col, options);
201 breakable_column_spacing (me, lb, right_col, options);
204 breakable_column_spacing (me, left_col, rb, options);
207 breakable_column_spacing (me, lb, rb, options);
212 set_column_rods (vector<Grob*> const &cols, Real padding)
214 /* distances[i] will be the minimum distance between column i and column i+1 */
215 vector<Real> distances;
217 for (vsize i = 1; i < cols.size (); i++)
219 assert (distances.size () == i-1);
221 Item *r = dynamic_cast<Item*> (cols[i]);
222 Item *rb = r->find_prebroken_piece (LEFT);
224 if (Separation_item::is_empty (r) && (!rb || Separation_item::is_empty (rb)))
226 distances.push_back (0);
230 Skyline_pair *skys = Skyline_pair::unsmob (r->get_property ("horizontal-skylines"));
231 Real right_stickout = skys ? (*skys)[LEFT].max_height () : 0.0;
233 /* min rather than max because right-stickout will be negative if the right-hand column
234 sticks out a lot to the left */
235 right_stickout = min (right_stickout,
236 Separation_item::conditional_skyline (r, cols[i-1]).max_height ());
238 Drul_array<Item*> r_cols (r, rb);
239 Drul_array<Real> cur_dist (0.0, 0.0);
241 /* This is an inner loop and hence it is potentially quadratic. However, we only continue
242 as long as there is a rod to insert. Therefore, this loop will usually only execute
243 a constant number of times per iteration of the outer loop. */
244 for (vsize j = i; j--;)
246 Item *l = dynamic_cast<Item*> (cols[j]);
247 Item *lb = l->find_prebroken_piece (RIGHT);
248 Skyline_pair *skys = Skyline_pair::unsmob (l->get_property ("horizontal-skylines"));
249 Real left_stickout = skys ? (*skys)[RIGHT].max_height () : 0.0;
256 cur_dist[d] += distances[j];
258 Item *r_col = r_cols[d];
259 bool touches = right_stickout - left_stickout + cur_dist[d] < 0.0;
262 /* we set a distance for the line-starter column even if it's non-broken counterpart
263 doesn't touch the right column. */
265 Separation_item::set_distance (lb, r_col, padding);
267 if (touches || j == i-1)
268 dist = Separation_item::set_distance (l, r_col, padding);
270 if (j == i-1 && d == LEFT)
271 distances.push_back (dist);
274 cur_dist[d] = distances[j];
276 done = done && !touches;
278 while (flip (&d) != LEFT && rb);
280 /* we need the empty check for gregorian notation, where there are a lot of
281 extraneous paper-columns that we need to skip over */
282 if (done && !Separation_item::is_empty (l))
290 Spacing_spanner::generate_springs (Grob *me,
291 vector<Grob*> const &cols,
292 Spacing_options const *options)
294 Paper_column *prev = dynamic_cast<Paper_column*> (cols[0]);
295 for (vsize i = 1; i < cols.size (); i++)
297 Paper_column *col = dynamic_cast<Paper_column *> (cols[i]);
298 Paper_column *next = (i + 1 < cols.size ()) ? dynamic_cast<Paper_column *> (cols[i+1]) : 0;
300 generate_pair_spacing (me, prev, col, next, options);
305 set_column_rods (cols, 0.1); // FIXME: padding
309 Generate the space between two musical columns LEFT_COL and RIGHT_COL.
312 Spacing_spanner::musical_column_spacing (Grob *me,
315 Spacing_options const *options)
317 Real base_note_space = note_spacing (me, left_col, right_col, options);
320 if (options->stretch_uniformly_)
321 spring = Spring (base_note_space, 0.0);
324 vector<Spring> springs;
325 extract_grob_set (left_col, "right-neighbors", neighbors);
327 for (vsize i = 0; i < neighbors.size (); i++)
329 Grob *wish = neighbors[i];
331 Item *wish_rcol = Spacing_interface::right_column (wish);
332 if (Spacing_interface::left_column (wish) != left_col
333 || (wish_rcol != right_col && wish_rcol != right_col->original ()))
337 This is probably a waste of time in the case of polyphonic
339 if (Note_spacing::has_interface (wish))
341 Real inc = options->increment_;
342 if (Grob *gsp = unsmob_grob (left_col->get_object ("grace-spacing")))
344 Spacing_options grace_opts;
345 grace_opts.init_from_grob (gsp);
346 inc = grace_opts.increment_;
348 springs.push_back (Note_spacing::get_spacing (wish, right_col, base_note_space, inc));
352 if (springs.empty ())
355 if (!Paper_column::is_musical (right_col))
358 There used to be code that examined left_col->extent
359 (X_AXIS), but this is resulted in unexpected wide
360 spacing, because the width of s^"text" output is also
361 taken into account here.
363 spring = Spring (max (base_note_space, options->increment_),
364 options->increment_);
369 Fixed should be 0.0. If there are no spacing wishes, we're
370 likely dealing with polyphonic spacing of hemiolas.
372 We used to have min_distance_ = options->increment_
374 but this can lead to numeric instability problems when we
377 inverse_strength = (distance_ - min_distance_)
380 spring = Spring (base_note_space, 0.0);
384 spring = merge_springs (springs);
387 if (Paper_column::when_mom (right_col).grace_part_
388 && !Paper_column::when_mom (left_col).grace_part_)
391 Ugh. 0.8 is arbitrary.
397 TODO: make sure that the space doesn't exceed the right margin.
399 if (options->packed_)
402 In packed mode, pack notes as tight as possible. This makes
403 sense mostly in combination with raggedright mode: the notes
404 are then printed at minimum distance. This is mostly useful
405 for ancient notation, but may also be useful for some flavours
406 of contemporary music. If not in raggedright mode, lily will
407 pack as much bars of music as possible into a line, but the
408 line will then be stretched to fill the whole linewidth.
410 spring.set_distance (spring.min_distance ());
411 spring.set_inverse_stretch_strength (1.0);
414 Spaceable_grob::add_spring (left_col, right_col, spring);
418 Check if COL fills the whole measure.
421 Spacing_spanner::fills_measure (Grob *me, Item *left, Item *col)
423 System *sys = get_root_system (me);
424 Item *next = sys->column (col->get_column ()->get_rank () + 1);
428 if (Paper_column::is_musical (next)
429 || Paper_column::is_musical (left)
430 || !Paper_column::is_musical (col)
431 || !Paper_column::is_used (next))
435 Paper_column::when_mom (next) - Paper_column::when_mom (col);
437 Moment *len = unsmob_moment (left->get_property ("measure-length"));
442 Don't check for exact measure length, since ending measures are
443 often shortened due to pickups.
445 if (dt.main_part_ > len->main_part_ / Rational (2)
446 && (next->is_broken ()
447 || next->break_status_dir ()))
454 Read hints from L and generate springs.
457 Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r,
458 Spacing_options const *options)
460 vector<Spring> springs;
463 Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l);
465 if (dt == Moment (0, 0))
467 extract_grob_set (l, "spacing-wishes", wishes);
469 for (vsize i = 0; i < wishes.size (); i++)
471 Item *spacing_grob = dynamic_cast<Item *> (wishes[i]);
473 if (!spacing_grob || !Staff_spacing::has_interface (spacing_grob))
477 column for the left one settings should be ok due automatic
480 assert (spacing_grob->get_column () == l);
482 springs.push_back (Staff_spacing::get_spacing (spacing_grob, r));
486 if (springs.empty ())
487 spring = standard_breakable_column_spacing (me, l, r, options);
489 spring = merge_springs (springs);
491 if (Paper_column::when_mom (r).grace_part_)
494 Correct for grace notes.
496 Ugh. The 0.8 is arbitrary.
501 if (Paper_column::is_musical (r)
502 && l->break_status_dir () == CENTER
503 && fills_measure (me, l, r))
505 spring.set_distance (spring.distance () + 1.0);
506 spring.set_default_strength ();
509 if (options->stretch_uniformly_ && l->break_status_dir () != RIGHT)
511 spring.set_min_distance (0.0);
512 spring.set_default_strength ();
515 Spaceable_grob::add_spring (l, r, spring);
518 ADD_INTERFACE (Spacing_spanner,
519 "The space taken by a note is dependent on its duration. Doubling a\n"
520 "duration adds spacing-increment to the space. The most common shortest\n"
521 "note gets @code{shortest-duration-space}. Notes that are even shorter are\n"
522 "spaced proportonial to their duration.\n"
524 "Typically, the increment is the width of a black note head. In a\n"
525 "piece with lots of 8th notes, and some 16th notes, the eighth note\n"
526 "gets 2 note heads width (i.e. the space following a note is 1 note\n"
527 "head width) A 16th note is followed by 0.5 note head width. The\n"
528 "quarter note is followed by 3 NHW, the half by 4 NHW, etc.\n",
531 "average-spacing-wishes "
532 "base-shortest-duration "
533 "common-shortest-duration "
535 "shortest-duration-space "
537 "strict-grace-spacing "
538 "strict-note-spacing "
539 "uniform-stretching "