-/*
- paper-column:
-
- Don't be confused by right-items: each spacing wish can also contain
- a number of items, with which a spacing constraint may be kept. It's
- a little baroque, but it might come in handy later on?
-
- */
-class Spacing_spanner
-{
-public:
- static void standard_breakable_column_spacing (Grob * me, Item*l, Item*r,
- Real * fixed, Real * space, Moment);
-
-
- static Real default_bar_spacing (Grob*,Grob*,Grob*,Moment);
- static Real note_spacing (Grob*,Grob*,Grob*,Moment, bool*);
- static Real get_duration_space (Grob*,Moment dur, Rational shortest, bool*);
- static Rational find_shortest (Link_array<Grob> const &);
- static void breakable_column_spacing (Grob*, Item* l, Item *r, Moment);
- static void find_loose_columns () {}
- static void prune_loose_colunms (Grob*,Link_array<Grob> *cols, Rational);
- static void find_loose_columns (Link_array<Grob> cols);
- static void set_explicit_neighbor_columns (Link_array<Grob> cols);
- static void set_implicit_neighbor_columns (Link_array<Grob> cols);
- static void do_measure (Rational, Grob*me,Link_array<Grob> *cols);
- static void musical_column_spacing (Grob*,Item*,Item*, Real, Rational);
- DECLARE_SCHEME_CALLBACK (set_springs, (SCM ));
- static bool has_interface (Grob*);
-};
-
-/*
- Return whether COL is fixed to its neighbors by some kind of spacing
- constraint.
-*/
-static bool
-loose_column (Grob *l, Grob *c, Grob *r)
-{
- SCM rns = c->get_grob_property ("right-neighbors");
- SCM lns = c->get_grob_property ("left-neighbors");
-
- /*
- If this column doesn't have a proper neighbor, we should really
- make it loose, but spacing it correctly is more than we can
- currently can handle.
-
- (this happens in the following situation:
-
- |
- | clef G
- *
-
- | | ||
- | | ||
- O O ||
-
-
- the column containing the clef is really loose, and should be
- attached right to the first column, but that is a lot of work for
- such a borderline case.)
-
- */
- if (!gh_pair_p (lns) || !gh_pair_p (rns))
- return false;
-
- Item * l_neighbor = dynamic_cast<Item*> (unsmob_grob (gh_car (lns)));
- Item * r_neighbor = dynamic_cast<Item*> (unsmob_grob (gh_car (rns)));
-
- if (!l_neighbor || !r_neighbor)
- return false;
-
- l_neighbor = l_neighbor->column_l();
- r_neighbor = dynamic_cast<Item*> (Note_spacing::right_column (r_neighbor));
-
- if (l == l_neighbor && r == r_neighbor)
- return false;
-
- if (!l_neighbor || !r_neighbor)
- return false;
-
- /*
- Only declare loose if the bounds make a little sense. This means
- some cases (two isolated, consecutive clef changes) won't be
- nicely folded, but hey, then don't do that.
- */
- if ((Paper_column::musical_b (l_neighbor) || Item::breakable_b (l_neighbor))
- && (Paper_column::musical_b (r_neighbor) || Item::breakable_b (r_neighbor)))
- {
- return true;
- }
-
-
- /*
- If in doubt: we're not loose; the spacing engine should space for
- it, risking suboptimal spacing.
-
- (Otherwise, we might risk core dumps, and other weird stuff.)
-
- */
- return false;
-}
-
-/*
- Remove columns that are not tightly fitting from COLS. In the
- removed columns, set 'between-cols to the columns where it is in
- between.
-*/
-void
-Spacing_spanner::prune_loose_colunms (Grob*me,Link_array<Grob> *cols, Rational shortest)
-{
- Link_array<Grob> newcols;
- Real increment = gh_scm2double (me->get_grob_property ("spacing-increment"));
- for (int i=0; i < cols->size (); i++)
- {
- if (Item::breakable_b (cols->elem(i)) || Paper_column::musical_b (cols->elem (i)))
- {
- newcols.push (cols->elem(i));
- continue;
- }
-
- Grob *c = cols->elem(i);
- if (loose_column (cols->elem (i-1), c, cols->elem (i+1)))
- {
- SCM lns = c->get_grob_property ("left-neighbors");
- lns = gh_pair_p (lns) ? gh_car (lns) : SCM_BOOL_F;
-
- SCM rns = c->get_grob_property ("right-neighbors");
- rns = gh_pair_p (rns) ? gh_car (rns) : SCM_BOOL_F;
-
- /*
- Either object can be non existent, if the score ends
- prematurely.
- */
- rns = gh_car (unsmob_grob (rns)->get_grob_property ("right-items"));
- c->set_grob_property ("between-cols", gh_cons (lns,
- rns));
-
- /*
- Set distance constraints for loose columns
- */
- Drul_array<Grob*> next_door;
- next_door[LEFT] =cols->elem (i - 1);
- next_door[RIGHT] =cols->elem (i + 1);
- Direction d = LEFT;
- Drul_array<Real> dists(0,0);
-
- do
- {
- dists[d] = 0.0;
- Item *lc = dynamic_cast<Item*> ((d == LEFT) ? next_door[LEFT] : c);
- Item *rc = dynamic_cast<Item*> (d == LEFT ? c : next_door[RIGHT]);
-
- for (SCM s = lc->get_grob_property ("spacing-wishes");
- gh_pair_p (s); s = gh_cdr (s))
- {
- Grob *sp = unsmob_grob (gh_car (s));
- if (Note_spacing::left_column (sp) != lc
- || Note_spacing::right_column (sp) != rc)
- continue;
-
- Real space, fixed;
- fixed = 0.0;
- bool dummy;
-
- if (d == LEFT)
- {
- /*
- The note spacing should be taken from the musical
- columns.
-
- */
- Real base = note_spacing (me, lc, rc, shortest, &dummy);
- Note_spacing::get_spacing (sp, rc, base, increment, &space, &fixed);
-
- space -= increment;
-
- dists[d] = dists[d] >? space;
- }
- else
- {
- Real space, fixed_space;
- Staff_spacing::get_spacing_params (sp,
- &space, &fixed_space);
-
- dists[d] = dists[d] >? fixed_space;
- }
-
- }
- }
- while (flip (&d) != LEFT);
-
- Rod r;
- r.distance_f_ = dists[LEFT] + dists[RIGHT];
- r.item_l_drul_[LEFT] = dynamic_cast<Item*> (cols->elem(i-1));
- r.item_l_drul_[RIGHT] = dynamic_cast<Item*> (cols->elem (i+1));
-
- r.add_to_cols ();
- }
- else
- {
- newcols.push (c);
- }
- }
-
- *cols = newcols;
-}
-
-/*
- Set neighboring columns determined by the spacing-wishes grob property.
-*/
-void
-Spacing_spanner::set_explicit_neighbor_columns (Link_array<Grob> cols)