2 spacing-loose-columns.cc -- implement loose column spacing.
4 source file of the GNU LilyPond music typesetter
6 (c) 2005--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
10 #include "paper-column.hh"
11 #include "column-x-positions.hh"
12 #include "pointer-group-interface.hh"
13 #include "staff-spacing.hh"
14 #include "note-spacing.hh"
15 #include "spacing-spanner.hh"
18 #include "spacing-options.hh"
20 /* Find the loose columns in POSNS, and drape them around the columns
21 specified in BETWEEN-COLS. */
23 set_loose_columns (System
*which
, Column_x_positions
const *posns
)
25 int loose_col_count
= posns
->loose_cols_
.size ();
29 for (int i
= 0; i
< loose_col_count
; i
++)
32 Item
*loose
= dynamic_cast<Item
*> (posns
->loose_cols_
[i
]);
33 Paper_column
*col
= dynamic_cast<Paper_column
*> (loose
);
35 if (col
->get_system ())
44 SCM between
= loose
->get_object ("between-cols");
45 if (!scm_is_pair (between
))
48 Item
*le
= dynamic_cast<Item
*> (unsmob_grob (scm_car (between
)));
49 Item
*re
= dynamic_cast<Item
*> (unsmob_grob (scm_cdr (between
)));
56 left
= le
->get_column ();
57 if (!left
->get_system ())
58 left
= left
->find_prebroken_piece (RIGHT
);
60 clique
.push_back (left
);
63 clique
.push_back (loose
);
66 loose
= right
= re
->get_column ();
69 if (right
->get_system ())
71 else if (right
->find_prebroken_piece (LEFT
)
72 && right
->find_prebroken_piece (LEFT
)->get_system () == which
)
73 right
= right
->find_prebroken_piece (LEFT
);
74 else if (Paper_column::get_rank (which
->get_bound (RIGHT
)) < Paper_column::get_rank (right
))
76 right
= which
->get_bound (RIGHT
);
79 clique
.back ()->programming_error ("Loose column does not have right side to attach to.");
80 System
*base_system
= dynamic_cast<System
*> (which
->original ());
81 int j
= Paper_column::get_rank (clique
.back ()) + 1;
82 int end_rank
= Paper_column::get_rank (which
->get_bound (RIGHT
));
83 extract_grob_set (base_system
, "columns", base_cols
);
84 for (; j
< end_rank
; j
++)
86 if (base_cols
[j
]->get_system () == which
)
87 right
= dynamic_cast<Item
*> ((Grob
*)base_cols
[j
]);
94 programming_error ("Can't attach loose column sensibly. Attaching to end of system.");
95 right
= which
->get_bound (RIGHT
);
97 Grob
*common
= right
->common_refpoint (left
, X_AXIS
);
99 clique
.push_back (right
);
101 vector
<Real
> clique_spacing
;
102 clique_spacing
.push_back (0.0);
103 for (vsize j
= 1; j
+ 1 < clique
.size (); j
++)
105 Grob
*clique_col
= clique
[j
];
107 Paper_column
*loose_col
= dynamic_cast<Paper_column
*> (clique
[j
]);
108 Paper_column
*next_col
= dynamic_cast<Paper_column
*> (clique
[j
+ 1]);
110 Grob
*spacing
= unsmob_grob (clique_col
->get_object ("spacing"));
111 if (Grob
*grace_spacing
= unsmob_grob (clique_col
->get_object ("grace-spacing")))
113 spacing
= grace_spacing
;
116 Spacing_options options
;
118 options
.init_from_grob (spacing
);
120 programming_error ("Column without spacing object");
122 Real base_note_space
= 0.0;
124 if (Paper_column::is_musical (next_col
)
125 && Paper_column::is_musical (loose_col
))
126 base_note_space
= Spacing_spanner::note_spacing (spacing
, loose_col
, next_col
,
130 Spring spring
= Spacing_spanner::standard_breakable_column_spacing (spacing
,
134 base_note_space
= spring
.distance ();
137 base_note_space
= max (base_note_space
,
138 robust_relative_extent (loose_col
, loose_col
, X_AXIS
)[RIGHT
]
139 - robust_relative_extent (next_col
, next_col
, X_AXIS
)[LEFT
]);
141 clique_spacing
.push_back (base_note_space
);
144 Real default_padding
= 1.0;
145 clique_spacing
.push_back (default_padding
);
147 Real right_point
= robust_relative_extent (clique
.back (), common
, X_AXIS
)[LEFT
];
150 Grob
*finished_right_column
= clique
.back ();
152 for (vsize j
= clique
.size () - 2; j
> 0; j
--)
154 Paper_column
*clique_col
= dynamic_cast<Paper_column
*> (clique
[j
]);
156 right_point
= finished_right_column
->relative_coordinate (common
, X_AXIS
);
158 Real distance_to_next
= clique_spacing
[j
];
160 Real my_offset
= right_point
- distance_to_next
;
162 clique_col
->set_system (which
);
163 clique_col
->translate_axis (my_offset
- clique_col
->relative_coordinate (common
, X_AXIS
), X_AXIS
);
165 finished_right_column
= clique_col
;