2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2005--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
21 #include "paper-column.hh"
22 #include "column-x-positions.hh"
23 #include "pointer-group-interface.hh"
24 #include "staff-spacing.hh"
25 #include "note-spacing.hh"
26 #include "spacing-spanner.hh"
29 #include "spacing-options.hh"
31 /* Find the loose columns in POSNS, and drape them around the columns
32 specified in BETWEEN-COLS. */
34 set_loose_columns (System
*which
, Column_x_positions
const *posns
)
36 int loose_col_count
= posns
->loose_cols_
.size ();
40 for (int i
= 0; i
< loose_col_count
; i
++)
41 dynamic_cast<Paper_column
*> (posns
->loose_cols_
[i
])->set_system (which
);
43 for (int i
= 0; i
< loose_col_count
; i
++)
46 Item
*loose
= dynamic_cast<Item
*> (posns
->loose_cols_
[i
]);
54 SCM between
= loose
->get_object ("between-cols");
55 if (!scm_is_pair (between
))
58 /* If the line was broken at one of the loose columns, split
59 the clique at that column. */
60 if (!loose
->get_system ())
63 Paper_column
*le
= dynamic_cast<Paper_column
*> (unsmob_grob (scm_car (between
)));
64 Paper_column
*re
= dynamic_cast<Paper_column
*> (unsmob_grob (scm_cdr (between
)));
71 left
= le
->get_column ();
72 if (!left
->get_system ())
73 left
= left
->find_prebroken_piece (RIGHT
);
75 clique
.push_back (left
);
78 clique
.push_back (loose
);
81 loose
= right
= re
->get_column ();
86 programming_error ("Can't attach loose column sensibly. Attaching to end of system.");
87 right
= which
->get_bound (RIGHT
);
90 if (right
->get_system ())
92 else if (right
->find_prebroken_piece (LEFT
)
93 && right
->find_prebroken_piece (LEFT
)->get_system () == which
)
94 right
= right
->find_prebroken_piece (LEFT
);
95 else if (Paper_column::get_rank (which
->get_bound (RIGHT
)) < Paper_column::get_rank (right
))
96 right
= which
->get_bound (RIGHT
);
99 clique
.back ()->programming_error ("Loose column does not have right side to attach to.");
100 System
*base_system
= dynamic_cast<System
*> (which
->original ());
101 int j
= Paper_column::get_rank (clique
.back ()) + 1;
102 int end_rank
= Paper_column::get_rank (which
->get_bound (RIGHT
));
103 extract_grob_set (base_system
, "columns", base_cols
);
104 for (; j
< end_rank
; j
++)
106 if (base_cols
[j
]->get_system () == which
)
107 right
= dynamic_cast<Item
*> ((Grob
*)base_cols
[j
]);
111 Grob
*common
= right
->common_refpoint (left
, X_AXIS
);
113 clique
.push_back (right
);
115 vector
<Real
> clique_spacing
;
116 clique_spacing
.push_back (0.0);
117 for (vsize j
= 1; j
+ 1 < clique
.size (); j
++)
119 Grob
*clique_col
= clique
[j
];
121 Paper_column
*loose_col
= dynamic_cast<Paper_column
*> (clique
[j
]);
122 Paper_column
*next_col
= dynamic_cast<Paper_column
*> (clique
[j
+ 1]);
124 Grob
*spacing
= unsmob_grob (clique_col
->get_object ("spacing"));
125 if (Grob
*grace_spacing
= unsmob_grob (clique_col
->get_object ("grace-spacing")))
127 spacing
= grace_spacing
;
130 Spacing_options options
;
132 options
.init_from_grob (spacing
);
134 programming_error ("Column without spacing object");
136 Real base_note_space
= 0.0;
138 if (Paper_column::is_musical (next_col
)
139 && Paper_column::is_musical (loose_col
))
140 base_note_space
= Spacing_spanner::note_spacing (spacing
, loose_col
, next_col
,
144 Spring spring
= Spacing_spanner::standard_breakable_column_spacing (spacing
,
148 base_note_space
= spring
.distance ();
151 base_note_space
= max (base_note_space
,
152 robust_relative_extent (loose_col
, loose_col
, X_AXIS
)[RIGHT
]
153 - robust_relative_extent (next_col
, next_col
, X_AXIS
)[LEFT
]);
155 clique_spacing
.push_back (base_note_space
);
158 Real default_padding
= 1.0;
159 clique_spacing
.push_back (default_padding
);
161 Real right_point
= robust_relative_extent (clique
.back (), common
, X_AXIS
)[LEFT
];
164 Grob
*finished_right_column
= clique
.back ();
166 for (vsize j
= clique
.size () - 2; j
> 0; j
--)
168 Paper_column
*clique_col
= dynamic_cast<Paper_column
*> (clique
[j
]);
170 right_point
= finished_right_column
->relative_coordinate (common
, X_AXIS
);
172 Real distance_to_next
= clique_spacing
[j
];
174 Real my_offset
= right_point
- distance_to_next
;
176 clique_col
->translate_axis (my_offset
- clique_col
->relative_coordinate (common
, X_AXIS
), X_AXIS
);
178 finished_right_column
= clique_col
;