2 spacing-spanner.cc -- implement Spacing_spanner
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
15 #include "output-def.hh"
16 #include "paper-score.hh"
17 #include "paper-column.hh"
19 #include "note-spacing.hh"
22 #include "staff-spacing.hh"
24 #include "paper-column.hh"
25 #include "spaceable-grob.hh"
26 #include "break-align-interface.hh"
27 #include "spacing-interface.hh"
28 #include "pointer-group-interface.hh"
29 #include "grob-array.hh"
32 TODO: this file/class is too complex. Should figure out how to chop
39 static void standard_breakable_column_spacing (Grob *me, Item *l, Item *r,
40 Real *fixed, Real *space, Moment);
42 static Real default_bar_spacing (Grob *, Grob *, Grob *, Moment);
43 static Real note_spacing (Grob *, Grob *, Grob *, Moment, bool *);
44 static Real get_duration_space (Grob *, Moment dur, Rational shortest, bool *);
45 static Rational find_shortest (Grob *, Link_array<Grob> const &);
46 static void breakable_column_spacing (Grob *, Item *l, Item *r, Moment);
47 static void prune_loose_columns (Grob *, Link_array<Grob> *cols, Rational);
48 static void set_explicit_neighbor_columns (Link_array<Grob> const &cols);
49 static void set_implicit_neighbor_columns (Link_array<Grob> const &cols);
50 static void do_measure (Rational, Grob *me, Link_array<Grob> *cols);
51 static void musical_column_spacing (Grob *, Item *, Item *, Real, Rational);
52 DECLARE_SCHEME_CALLBACK (set_springs, (SCM));
53 static bool has_interface (Grob *);
57 Return whether COL is fixed to its neighbors by some kind of spacing
61 If in doubt, then we're not loose; the spacing engine should space
62 for it, risking suboptimal spacing.
64 (Otherwise, we might risk core dumps, and other weird stuff.)
67 loose_column (Grob *l, Grob *c, Grob *r)
69 extract_grob_set (c, "right-neighbors", rns);
70 extract_grob_set (c, "left-neighbors", lns);
73 If this column doesn't have a proper neighbor, we should really
74 make it loose, but spacing it correctly is more than we can
77 (this happens in the following situation:
88 the column containing the clef is really loose, and should be
89 attached right to the first column, but that is a lot of work for
90 such a borderline case.)
93 if (lns.is_empty () || rns.is_empty ())
96 Item *l_neighbor = dynamic_cast<Item *> (lns[0]);
97 Item *r_neighbor = dynamic_cast<Item *> (rns[0]);
99 if (!l_neighbor || !r_neighbor)
102 l_neighbor = l_neighbor->get_column ();
103 r_neighbor = dynamic_cast<Item *> (Note_spacing::right_column (r_neighbor));
105 if (l == l_neighbor && r == r_neighbor)
108 if (!l_neighbor || !r_neighbor)
112 Only declare loose if the bounds make a little sense. This means
113 some cases (two isolated, consecutive clef changes) won't be
114 nicely folded, but hey, then don't do that.
116 if (! ((Paper_column::is_musical (l_neighbor) || Item::is_breakable (l_neighbor))
117 && (Paper_column::is_musical (r_neighbor) || Item::is_breakable (r_neighbor))))
123 A rather hairy check, but we really only want to move around
124 clefs. (anything else?)
126 in any case, we don't want to move bar lines.
128 extract_grob_set (c, "elements", elts);
129 for (int i = elts.size (); i--; )
132 if (g && Break_align_interface::has_interface (g))
134 extract_grob_set (g, "elements", gelts);
135 for (int j = gelts.size (); j--; )
140 ugh. -- fix staff-bar name?
142 if (h && h->get_property ("break-align-symbol") == ly_symbol2scm ("staff-bar"))
152 Remove columns that are not tightly fitting from COLS. In the
153 removed columns, set 'between-cols to the columns where it is in
157 Spacing_spanner::prune_loose_columns (Grob *me, Link_array<Grob> *cols, Rational shortest)
159 Link_array<Grob> newcols;
160 Real increment = robust_scm2double (me->get_property ("spacing-increment"), 1.2);
161 for (int i = 0; i < cols->size (); i++)
163 if (Item::is_breakable (cols->elem (i))
164 || Paper_column::is_musical (cols->elem (i)))
166 newcols.push (cols->elem (i));
170 Grob *c = cols->elem (i);
171 if (loose_column (cols->elem (i - 1), c, cols->elem (i + 1)))
173 extract_grob_set (c, "right-neighbors", rns_arr);
174 extract_grob_set (c, "left-neighbors", lns_arr);
176 SCM lns = lns_arr.size () ? lns_arr.top()->self_scm () : SCM_BOOL_F;
177 SCM rns = rns_arr.size () ? rns_arr.top()->self_scm () : SCM_BOOL_F;
180 Either object can be non existent, if the score ends
184 extract_grob_set (unsmob_grob (rns), "right-items", right_items);
185 c->set_object ("between-cols", scm_cons (lns,
186 right_items[0]->self_scm ()));
189 Set distance constraints for loose columns
191 Drul_array<Grob *> next_door;
192 next_door[LEFT] = cols->elem (i - 1);
193 next_door[RIGHT] = cols->elem (i + 1);
195 Drul_array<Real> dists (0, 0);
200 Item *lc = dynamic_cast<Item *> ((d == LEFT) ? next_door[LEFT] : c);
201 Item *rc = dynamic_cast<Item *> (d == LEFT ? c : next_door[RIGHT]);
204 extract_grob_set (lc, "spacing-wishes", wishes);
205 for (int k = wishes.size(); k--;)
207 Grob *sp = wishes[k];
208 if (Note_spacing::left_column (sp) != lc
209 || Note_spacing::right_column (sp) != rc)
219 The note spacing should be taken from the musical
223 Real base = note_spacing (me, lc, rc, shortest, &dummy);
224 Note_spacing::get_spacing (sp, rc, base, increment, &space, &fixed);
228 dists[d] = max (dists[d], space);
232 Real space, fixed_space;
233 Staff_spacing::get_spacing_params (sp,
234 &space, &fixed_space);
236 dists[d] = max (dists[d], fixed_space);
240 while (flip (&d) != LEFT);
243 r.distance_ = dists[LEFT] + dists[RIGHT];
244 r.item_drul_[LEFT] = dynamic_cast<Item *> (cols->elem (i - 1));
245 r.item_drul_[RIGHT] = dynamic_cast<Item *> (cols->elem (i + 1));
259 Set neighboring columns determined by the spacing-wishes grob property.
262 Spacing_spanner::set_explicit_neighbor_columns (Link_array<Grob> const &cols)
264 for (int i = 0; i < cols.size (); i++)
266 SCM right_neighbors = Grob_array::make_array ();
267 Grob_array *rn_arr = unsmob_grob_array (right_neighbors);
268 int min_rank = 100000; // inf.
270 extract_grob_set (cols[i], "spacing-wishes", wishes);
271 for (int k = wishes.size(); k--;)
273 Item *wish = dynamic_cast<Item *> ( wishes[k]);
275 Item *lc = wish->get_column ();
276 Grob *right = Note_spacing::right_column (wish);
281 Item *rc = dynamic_cast<Item *> (right);
283 int right_rank = Paper_column::get_rank (rc);
284 int left_rank = Paper_column::get_rank (lc);
287 update the left column.
289 if (right_rank <= min_rank)
291 if (right_rank < min_rank)
294 min_rank = right_rank;
299 update the right column of the wish.
303 extract_grob_set (rc, "left-neighbors", lns_arr);
306 Item *it = dynamic_cast<Item *> (lns_arr.top());
307 maxrank = Paper_column::get_rank (it->get_column ());
310 if (left_rank >= maxrank)
313 if (left_rank > maxrank)
315 Grob_array *ga = unsmob_grob_array (rc->get_object ("left-neighbors"));
320 Pointer_group_interface::add_grob (rc, ly_symbol2scm ("left-neighbors"), wish);
326 cols[i]->set_object ("right-neighbors", right_neighbors);
332 Set neighboring columns that have no left/right-neighbor set
333 yet. Only do breakable non-musical columns, and musical columns.
336 Spacing_spanner::set_implicit_neighbor_columns (Link_array<Grob> const &cols)
338 for (int i = 0; i < cols.size (); i++)
340 Item *it = dynamic_cast<Item *> (cols[i]);
341 if (!Item::is_breakable (it) && !Paper_column::is_musical (it))
344 // it->breakable || it->musical
347 sloppy with typing left/right-neighbors should take list, but paper-column found instead.
349 extract_grob_set (cols[i], "left-neighbors", lns);
350 if (lns.is_empty () && i )
352 SCM ga_scm = Grob_array::make_array();
353 Grob_array *ga = unsmob_grob_array (ga_scm);
355 cols[i]->set_object ("left-neighbors", ga_scm);
357 extract_grob_set (cols[i], "right-neighbors", rns);
358 if (rns.is_empty () && i < cols.size () - 1)
360 SCM ga_scm = Grob_array::make_array();
361 Grob_array *ga = unsmob_grob_array (ga_scm);
363 cols[i]->set_object ("right-neighbors", ga_scm);
368 MAKE_SCHEME_CALLBACK (Spacing_spanner, set_springs, 1);
370 Spacing_spanner::set_springs (SCM smob)
372 Grob *me = unsmob_grob (smob);
375 can't use get_system() ? --hwn.
377 Link_array<Grob> all (me->pscore_->root_system ()->columns ());
379 set_explicit_neighbor_columns (all);
381 SCM preset_shortest = me->get_property ("common-shortest-duration");
382 Rational global_shortest;
383 if (unsmob_moment (preset_shortest))
385 global_shortest = unsmob_moment (preset_shortest)->main_part_;
389 global_shortest = find_shortest (me, all);
390 if (be_verbose_global)
391 message (_f ("Global shortest duration is %s", global_shortest.to_string ()) + "\n");
393 prune_loose_columns (me, &all, global_shortest);
394 set_implicit_neighbor_columns (all);
397 for (int i = 1; i < all.size (); i++)
400 if (Item::is_breakable (sc))
402 Link_array<Grob> measure (all.slice (j, i + 1));
403 do_measure (global_shortest, me, &measure);
408 return SCM_UNSPECIFIED;
412 We want the shortest note that is also "common" in the piece, so we
413 find the shortest in each measure, and take the most frequently
416 This probably gives weird effects with modern music, where every
417 note has a different duration, but hey, don't write that kind of
421 Spacing_spanner::find_shortest (Grob *me, Link_array<Grob> const &cols)
424 ascending in duration
426 Array<Rational> durations;
429 Rational shortest_in_measure;
430 shortest_in_measure.set_infinite (1);
432 for (int i = 0; i < cols.size (); i++)
434 if (Paper_column::is_musical (cols[i]))
436 Moment *when = unsmob_moment (cols[i]->get_property ("when"));
439 ignore grace notes for shortest notes.
441 if (when && when->grace_part_)
444 SCM st = cols[i]->get_property ("shortest-starter-duration");
445 Moment this_shortest = *unsmob_moment (st);
446 assert (this_shortest.to_bool ());
447 shortest_in_measure = min (shortest_in_measure, this_shortest.main_part_);
449 else if (!shortest_in_measure.is_infinity ()
450 && Item::is_breakable (cols[i]))
453 for (; j < durations.size (); j++)
455 if (durations[j] > shortest_in_measure)
457 counts.insert (1, j);
458 durations.insert (shortest_in_measure, j);
461 else if (durations[j] == shortest_in_measure)
468 if (durations.size () == j)
470 durations.push (shortest_in_measure);
474 shortest_in_measure.set_infinite (1);
480 for (int i = durations.size (); i--;)
482 if (counts[i] >= max_count)
485 max_count = counts[i];
488 // printf ("duration %d/%d, count %d\n", durations[i].num (), durations[i].den (), counts[i]);
491 SCM bsd = me->get_property ("base-shortest-duration");
492 Rational d = Rational (1, 8);
493 if (Moment *m = unsmob_moment (bsd))
497 d = min (d, durations[max_idx]);
503 Generate spacing for a single measure. We used to have code that did
504 per-measure spacing. Now we have piecewise spacing. We should fix
505 this to support "spacing-regions": some regions have different notes
506 (different time sigs) than others, and should be spaced differently.
509 Spacing_spanner::do_measure (Rational global_shortest, Grob *me,
510 Link_array<Grob> *cols)
512 Real headwid = robust_scm2double (me->get_property ("spacing-increment"), 1);
513 for (int i = 0; i < cols->size () - 1; i++)
515 Item *l = dynamic_cast<Item *> (cols->elem (i));
516 Item *r = dynamic_cast<Item *> (cols->elem (i + 1));
518 Paper_column *lc = dynamic_cast<Paper_column *> (l);
519 Paper_column *rc = dynamic_cast<Paper_column *> (r);
521 if (Paper_column::is_musical (l))
523 musical_column_spacing (me, lc, rc, headwid, global_shortest);
524 if (Item *rb = r->find_prebroken_piece (LEFT))
525 musical_column_spacing (me, lc, rb, headwid, global_shortest);
530 The case that the right part is broken as well is rather
531 rare, but it is possible, eg. with a single empty measure,
532 or if one staff finishes a tad earlier than the rest.
534 Item *lb = l->find_prebroken_piece (RIGHT);
535 Item *rb = r->find_prebroken_piece (LEFT);
537 if (i == 0 && Paper_column::get_rank (l) == 0)
541 breakable_column_spacing (me, l, r, global_shortest);
544 breakable_column_spacing (me, lb, r, global_shortest);
547 breakable_column_spacing (me, l, rb, global_shortest);
550 breakable_column_spacing (me, lb, rb, global_shortest);
556 Generate the space between two musical columns LC and RC, given
557 spacing parameters INCR and SHORTEST.
560 Spacing_spanner::musical_column_spacing (Grob *me, Item *lc, Item *rc, Real increment, Rational global_shortest)
562 bool expand_only = false;
563 Real base_note_space = note_spacing (me, lc, rc, global_shortest, &expand_only);
565 Real compound_note_space = 0.0;
566 Real compound_fixed_note_space = 0.0;
569 extract_grob_set (lc, "right-neighbors", neighbors);
572 We adjust the space following a note only if the next note
573 happens after the current note (this is set in the grob
574 property SPACING-SEQUENCE.
576 for (int i = 0; i < neighbors.size (); i++)
578 Grob *wish = neighbors[i];
580 Item *wish_rcol = Note_spacing::right_column (wish);
581 if (Note_spacing::left_column (wish) != lc
582 || (wish_rcol != rc && wish_rcol != rc->original_))
586 This is probably a waste of time in the case of polyphonic
588 if (Note_spacing::has_interface (wish))
593 Note_spacing::get_spacing (wish, rc, base_note_space, increment, &space, &fixed);
595 compound_note_space = compound_note_space + space;
596 compound_fixed_note_space = compound_fixed_note_space + fixed;
601 if (Paper_column::when_mom (rc).grace_part_
602 && !Paper_column::when_mom (lc).grace_part_)
605 Ugh. 0.8 is arbitrary.
607 compound_note_space *= 0.8;
610 if (compound_note_space < 0 || wish_count == 0)
612 compound_note_space = base_note_space;
613 compound_fixed_note_space = increment;
617 compound_note_space /= wish_count;
618 compound_fixed_note_space /= wish_count;
622 Whatever we do, the fixed space is smaller than the real
625 TODO: this criterion is discontinuous in the derivative.
626 Maybe it should be continuous?
628 compound_fixed_note_space = min (compound_fixed_note_space, compound_note_space);
630 bool packed = to_boolean (me->get_layout ()->c_variable ("packed"));
631 Real inverse_strength = 1.0;
635 TODO: make sure that the space doesn't exceed the right margin.
640 In packed mode, pack notes as tight as possible. This makes
641 sense mostly in combination with raggedright mode: the notes
642 are then printed at minimum distance. This is mostly useful
643 for ancient notation, but may also be useful for some flavours
644 of contemporary music. If not in raggedright mode, lily will
645 pack as much bars of music as possible into a line, but the
646 line will then be stretched to fill the whole linewidth.
648 inverse_strength = 1.0;
649 distance = compound_fixed_note_space;
653 inverse_strength = (compound_note_space - compound_fixed_note_space);
654 distance = compound_note_space;
657 Spaceable_grob::add_spring (lc, rc, distance, inverse_strength);
661 The one-size-fits all spacing. It doesn't take into account
662 different spacing wishes from one to the next column.
665 Spacing_spanner::standard_breakable_column_spacing (Grob *me, Item *l, Item *r,
666 Real *fixed, Real *space,
671 Drul_array<Item *> cols (l, r);
675 if (!Paper_column::is_musical (cols[d]))
678 Tied accidentals over barlines cause problems, so lets see
679 what happens if we do this for non musical columns only.
681 Interval lext = cols[d]->extent (cols [d], X_AXIS);
682 if (!lext.is_empty ())
683 *fixed += -d * lext[-d];
686 while (flip (&d) != LEFT);
688 if (l->is_breakable (l) && r->is_breakable (r))
690 Moment *dt = unsmob_moment (l->get_property ("measure-length"));
695 Real incr = robust_scm2double (me->get_property ("spacing-increment"), 1);
697 *space = *fixed + incr * double (mlen.main_part_ / shortest.main_part_) * 0.8;
701 Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l);
703 if (dt == Moment (0, 0))
706 In this case, Staff_spacing should handle the job,
707 using dt when it is 0 is silly.
709 *space = *fixed + 0.5;
714 *space = *fixed + get_duration_space (me, dt, shortest.main_part_, &dummy);
720 Read hints from L and generate springs.
723 Spacing_spanner::breakable_column_spacing (Grob *me, Item *l, Item *r, Moment shortest)
725 Real compound_fixed = 0.0;
726 Real compound_space = 0.0;
729 Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l);
731 if (dt == Moment (0, 0))
733 extract_grob_set (l, "spacing-wishes", wishes);
735 for (int i = 0; i < wishes.size (); i++)
737 Item *spacing_grob = dynamic_cast<Item *> (wishes[i]);
739 if (!spacing_grob || !Staff_spacing::has_interface (spacing_grob))
746 column for the left one settings should be ok due automatic
750 assert (spacing_grob->get_column () == l);
752 Staff_spacing::get_spacing_params (spacing_grob,
753 &space, &fixed_space);
755 if (Paper_column::when_mom (r).grace_part_)
758 Correct for grace notes.
760 Ugh. The 0.8 is arbitrary.
765 compound_space += space;
766 compound_fixed += fixed_space;
771 if (compound_space <= 0.0 || !wish_count)
773 standard_breakable_column_spacing (me, l, r, &compound_fixed, &compound_space,
779 compound_space /= wish_count;
780 compound_fixed /= wish_count;
783 assert (!isinf (compound_space));
784 compound_space = max (compound_space, compound_fixed);
787 There used to be code that changed spacing depending on
788 raggedright setting. Ugh.
790 Do it more cleanly, or rename the property.
793 Real inverse_strength = (compound_space - compound_fixed);
794 Real distance = compound_space;
795 Spaceable_grob::add_spring (l, r, distance, inverse_strength);
799 Get the measure wide ant for arithmetic spacing.
802 Spacing_spanner::get_duration_space (Grob *me, Moment d, Rational shortest, bool *expand_only)
804 Real k = robust_scm2double (me->get_property ("shortest-duration-space"), 1);
805 Real incr = robust_scm2double (me->get_property ("spacing-increment"), 1);
810 We don't space really short notes using the log of the
811 duration, since it would disproportionally stretches the long
812 notes in a piece. In stead, we use geometric spacing with constant 0.5
815 This should probably be tunable, to use other base numbers.
817 In Mozart hrn3 by EB., we have 8th note = 3.9 mm (total), 16th note =
818 3.6 mm (total). head-width = 2.4, so we 1.2mm for 16th, 1.5
819 mm for 8th. (white space), suggesting that we use
821 (1.2 / 1.5)^{-log2(duration ratio)}
825 Rational ratio = d.main_part_ / shortest;
827 return ((k - 1) + double (ratio)) * incr;
832 John S. Gourlay. ``Spacing a Line of Music, '' Technical
833 Report OSU-CISRC-10/87-TR35, Department of Computer and
834 Information Science, The Ohio State University, 1987.
836 Real log = log_2 (shortest);
838 Rational compdur = d.main_part_ + d.grace_part_ / Rational (3);
839 *expand_only = false;
841 return (log_2 (compdur) + k) * incr;
846 Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc,
847 Moment shortest, bool *expand_only)
849 Moment shortest_playing_len = 0;
850 SCM s = lc->get_property ("shortest-playing-duration");
852 if (unsmob_moment (s))
853 shortest_playing_len = *unsmob_moment (s);
855 if (! shortest_playing_len.to_bool ())
857 programming_error ("can't find a ruling note at " + Paper_column::when_mom (lc).to_string ());
858 shortest_playing_len = 1;
861 Moment lwhen = Paper_column::when_mom (lc);
862 Moment rwhen = Paper_column::when_mom (rc);
864 Moment delta_t = rwhen - lwhen;
865 if (!Paper_column::is_musical (rc))
868 when toying with mmrests, it is possible to have musical
869 column on the left and non-musical on the right, spanning
873 Moment *dt = unsmob_moment (rc->get_property ("measure-length"));
876 delta_t = min (delta_t, *dt);
879 The following is an extra safety measure, such that
880 the length of a mmrest event doesn't cause havoc.
882 shortest_playing_len = min (shortest_playing_len, *dt);
888 In normal situations, the next column is at most
889 SHORTEST_PLAYING_LEN away. However chord-tremolos do funky faking stuff
890 with durations, invalidating this assumption. Here we kludge
891 around to get chord tremolos to behave properly.
894 shortest_playing_len = max (shortest_playing_len, delta_t);
895 if (delta_t.main_part_ && !lwhen.grace_part_)
897 dist = get_duration_space (me, shortest_playing_len,
898 shortest.main_part_, expand_only);
899 dist *= double (delta_t.main_part_ / shortest_playing_len.main_part_);
901 else if (delta_t.grace_part_)
904 TODO: figure out how to space grace notes.
906 dist = get_duration_space (me, shortest, shortest.main_part_, expand_only);
909 = robust_scm2double (me->get_property ("grace-space-factor"), 1);
917 ADD_INTERFACE (Spacing_spanner, "spacing-spanner-interface",
918 "The space taken by a note is dependent on its duration. Doubling a\n"
919 "duration adds spacing-increment to the space. The most common shortest\n"
920 "note gets @code{shortest-duration-space}. Notes that are even shorter are\n"
921 "spaced proportonial to their duration.\n"
923 "Typically, the increment is the width of a black note head. In a\n"
924 "piece with lots of 8th notes, and some 16th notes, the eighth note\n"
925 "gets 2 note heads width (i.e. the space following a note is 1 note\n"
926 "head width) A 16th note is followed by 0.5 note head width. The\n"
927 "quarter note is followed by 3 NHW, the half by 4 NHW, etc.\n",
929 "grace-space-factor spacing-increment base-shortest-duration "
930 "shortest-duration-space common-shortest-duration"
934 ADD_INTERFACE (Spacing_interface, "spacing-interface",
935 "Something to do with line breaking and spacing. "
936 "Kill this one after determining line breaks.",